Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django calls wrong function on given url

Tags:

python

django

django calls the "listing" function even though I told it to use the "watchlist" function when handling the request which arises when going to the .../watchlist url. I can't find the problem. Here is the error:

  File "/home/simon/Dokumente/cs50WebProgramming/commerce/auctions/views.py", line 103, in listing
    listing_obj = AuctionListing.objects.get(id=int(listing_id))
ValueError: invalid literal for int() with base 10: 'watchlist'

urls.py

urlpatterns = [
    path("", views.index, name="index"),
    path("login", views.login_view, name="login"),
    path("logout", views.logout_view, name="logout"),
    path("register", views.register, name="register"),
    path("create", views.create_listing, name="create"),
    path("after_create", views.after_create, name="after_create"),
    path("<str:listing_id>", views.listing, name="listing"),
    path("<str:listing_id>/bid", views.after_bid, name="after_bid"),
    path("watchlist", views.watchlist, name="watchlist")
]

views.py

def listing(request, listing_id):
    listing_obj = AuctionListing.objects.get(id=int(listing_id))

    return render(request, "auctions/listing.html", {
        "listing": listing_obj
    })

def watchlist(request):
    return render(request, "auctions/watchlist.html")
like image 538
Simon Rechermann Avatar asked Jan 20 '26 00:01

Simon Rechermann


2 Answers

The problem is with the order of your URL paths. You have <str:listing_id> before watchlist which leads to any string path to be matched with <str:listing_id>. Simply re-order your paths and you should be fine:

urlpatterns = [
    path("", views.index, name="index"),
    path("login", views.login_view, name="login"),
    path("logout", views.logout_view, name="logout"),
    path("register", views.register, name="register"),
    path("create", views.create_listing, name="create"),
    path("after_create", views.after_create, name="after_create"),
    path("watchlist", views.watchlist, name="watchlist")
    path("<str:listing_id>/bid", views.after_bid, name="after_bid"),
    path("<str:listing_id>", views.listing, name="listing"),
]
like image 151
Navid Zarepak Avatar answered Jan 21 '26 15:01

Navid Zarepak


This is because <str:listing_id> matches any string, including watchlist, and since watchlist is defined first, it will fire the listing view. You can change the order, but you can alo restrict the path to only accept ints:

urlpatterns = [
    path('', views.index, name='index'),
    path('login/', views.login_view, name='login'),
    path('logout/', views.logout_view, name='logout'),
    path('register/', views.register, name='register'),
    path('create/', views.create_listing, name='create'),
    path('after_create/', views.after_create, name='after_create'),
    path('watchlist/', views.watchlist, name='watchlist'),
    path('<int:listing_id>/', views.listing, name='listing'),
    path('<int:listing_id>/bid/', views.after_bid, name='after_bid')
]

By using <int:…>, it will only fire for sequences of digits, furthermore using int is no longer necessary, since the value is automatically converted to an int:

from django.shortcuts import get_object_or_404

def listing(request, listing_id):
    listing_obj = get_object_or_404(AuctionListing, id=listing_id)

    return render(request, "auctions/listing.html", {
        "listing": listing_obj
    })

Note: It is often better to use get_object_or_404(…) [Django-doc], then to use .get(…) [Django-doc] directly. In case the object does not exists, for example because the user altered the URL themselves, the get_object_or_404(…) will result in returning a HTTP 404 Not Found response, whereas using .get(…) will result in a HTTP 500 Server Error.

like image 45
Willem Van Onsem Avatar answered Jan 21 '26 13:01

Willem Van Onsem



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!