DragonBobZ
DragonBobZ

Reputation: 2444

Django Using Slug Field for Detail URL

I'm attempting to setup my site so that the url for my job-detail will use a slug field instead of a pk. It's telling me that it cannot find my job with the given slug (which is an int, 147).

Update:

After looking at the DetailView description at https://ccbv.co.uk/projects/Django/1.11/django.views.generic.detail/DetailView/ I realized there is a slug_field attribute for DetailView. My new view looks like:

class JobDetailView(CacheMixin, DetailView):
    model = Job
    slug_field = 'slug'

Question:

enter image description here

urls:

urlpatterns = [
    url(r'^careers$', views.job_list, name='job-list'),
    url(r'^careers/(?P<slug>[0-9]+)/$', views.JobDetailView.as_view(), name='job-detail'),
]

view:

class JobDetailView(CacheMixin, DetailView):
    model = Job
    pk_url_kwarg = 'slug'
    def get_object(self, *args, **kwargs):
        # Call the superclass
        object = super(JobDetailView, self).get_object()
        # Return the object
        return object

    def get(self, request, *args, **kwargs):
        object = super(JobDetailView, self).get(request, *args, **kwargs)
        return object

model:

class Job(UpdateAble, PublishAble, models.Model):
    slug = models.CharField(unique=True, max_length=25)
    facility = models.ForeignKey('Facility')
    recruiter = models.ForeignKey('Recruiter')
    title = models.TextField()
    practice_description = models.TextField(blank=True, default="")
    public_description = models.TextField(blank=True, default="")

    objects = JobManager()

    def get_next(self, **kwargs):
        jobs = Job.objects.published()
        next = next_in_order(self, qs=jobs)
        if not next:
            next = jobs[0]
        return next

    def get_prev(self, **kwargs):
        jobs = Job.objects.published()
        prev = prev_in_order(self, qs=jobs)
        if not prev:
            prev = jobs[len(jobs)-1]
        return prev

    def __str__(self):
        return f'{self.facility}; {self.title}'

manager:

class JobManager(models.Manager):

    def published(self):
        return super(JobManager, self).get_queryset().filter(is_published=True).order_by('facility__name', 'title')

Upvotes: 3

Views: 4601

Answers (1)

Daniel Roseman
Daniel Roseman

Reputation: 599530

You actually don't need to define pk_url_kwarg at all, and in fact by doing so you have confused things leading to the object not being found.

As you can see from the default implementation of get_object, the view normally looks for either a pk or slug kwarg in the URL; whichever it finds will be used for the lookup. But by setting pk_url_kwarg to slug, you're telling the view to get the URL kwarg named "slug" but use it to look up against the PK field, which obviously won't work.

Just remove that attribute altogether, and Django will detect your slug kwarg and use it to correctly look up against the slug field.

Upvotes: 4

Related Questions