MrTomRod
MrTomRod

Reputation: 344

Django: Dots in slug don't work in DetailView

I'm modelling genome assemblies whose names often contain a dot (.) I wrote a DetailView which works for names without dots but noth names with dots. I get this error:

404 - Using the URLconf defined in genomeDBmanager.urls, Django tried these URL patterns, in this order: ...

My model:

class Assembly(models.Model):
    ...
    identifier = models.SlugField('unique identifier', max_length=50, unique=True)
    ...

My view.py:

class AssemblyDetailView(DetailView):
    slug_field = 'identifier'
    template_name = 'overview/assembly.html'
    model = Assembly
    context_object_name = 'assembly'

My overview/urls.py:

app_name = 'overview'
urlpatterns = [
...
    path('assembly/<slug>/', views.AssemblyDetailView.as_view(), name='assembly-detail')
]

This URL works: 127.0.0.1:8000/strain/SomeAssembly-1, this one doesn't: 127.0.0.1:8000/strain/SomeAssembly.2.

Upvotes: 1

Views: 1449

Answers (2)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476659

Short answer: this is correct behavior for a slug, since a slug is not supposed to have dots.

A slug simply does not allow dots in the slug. Indeed, if we slugify(..) [Django-doc] for example 'foo.bar', we get:

>>> from django.utils.text import slugify
>>> slugify('foo.bar')
'foobar'

It is therefore absolutely valid to not accept dots. It thus means that the SlugField of your model, likely does not slugify the title (or whatever is "slugified") correctly.

You can accept strings, and paths with the str and path path converters, as is specified in the documentation on path converters [Django-doc]:

  • str - Matches any non-empty string, excluding the path separator, '/'. This is the default if a converter isn’t included in the expression.

(..)

  • path - Matches any non-empty string, including the path separator, '/'. This allows you to match against a complete URL path rather than just a segment of a URL path as with str.

So you can specify for example:

path('assembly/<str:slug>/', views.AssemblyDetailView.as_view(), name='assembly-detail')

but again, this is not a slug.

Upvotes: 4

MrTomRod
MrTomRod

Reputation: 344

The problem was that the default slug-regex doesn't accept dots. The solution is to specify one using re_path like this:

re_path(r'^assembly/(?P<slug>[0-9a-zA-Z.\-_ ]+)/$', views.AssemblyDetailView.as_view(), name='assembly-detail')

Everything else works the same.

Upvotes: 1

Related Questions