Django `The current path, detail/PayPal, matched the last one` error
I'm using Django's DetailView
to display detailed information in my web app. I've set up a Processor
model with a name
and a slug
field, and I'm using the slug
field in the URL pattern and the DetailView.
However, I'm running into an issue where the DetailView is not able to find the Processor
object if the capitalization of the URL slug doesn't exactly match the slug
field in the database.
For example if I visit localhost:8000/detail/paypal
I get the following error:
Using the URLconf ... Django tried these URL patterns, in this order:
...
detail/<slug:slug> [name='processor_detail']
The current path, detail/PayPal, matched the last one.
In addition the url I entered in the url field changes to localhost:8000/detail/PayPal
, capitalizing the letters.
Finally, the url only works if I first visit it by clicking on a link to it from another page. After that it works perfectly normally whether I go incognito mode or not and no matter the capitalization I use in the slug. But if I go incognito mode and visit the url directly(ie, after not having visit it by clicking on a link to it from another page) it doesn't load at all whether I capitalize the slug or not. I hope you can understand my point.
Here is my code:
views.py
:
class ProcessorDetailView(DetailView):
model = Processor
template_name = 'finder/processor_detail.html'
slug_field = 'slug' # Tell DetailView to use the `slug` model field as the DetailView slug
slug_url_kwarg = 'slug' # Match the URL parameter name
models.py
:
class Processor(models.Model): #the newly created database model and below are the fields
name = models.CharField(max_length=250, blank=True, null=True) #textField used for larger strings, CharField, smaller
slug = models.SlugField(max_length=250, blank=True)
...
def __str__(self): #displays some of the template information instead of 'Processot object'
if self.name:
return self.name[0:20]
else:
return '--no processor name listed--'
def get_absolute_url(self): # new
return reverse("processor_detail", args=[str(self.name)])
def save(self, *args, **kwargs): #`save` model a certain way(detailed in rest of function below)
if not self.slug: #if there is no value in `slug` field then...
self.slug = slugify(self.name) #...save a slugified `name` field value as the value in `slug` field
super().save(*args, **kwargs)
urls.py
:
path("detail/<slug:slug>", views.ProcessorDetailView.as_view(), name='processor_detail')
If I follow a link on a separate template to the the problem url using <a href="{%url 'processor_detail' processor.slug%}" class="details-link"> Details → </a>
, for example, it works perfectly fine afterward.
when you're using a url, django uses your model's get_absolute_url
to retrieve the right object, which returns the name
field. but you asked your view to use slug
instead so it breaks. just return slug in your get_absolute_url
and it should work
def get_absolute_url(self): # new
return reverse("processor_detail", args=[str(self.slug)])