adnanmuttaleb
adnanmuttaleb

Reputation: 3624

Use @propert based attr as Model slug, django's views?

I am trying to use an attribute created using the @property decorator im my model as a slug field for django DetailsView, as follow:

class Province(models.Model):
    name = models.CharField(max_length=30)
    code = models.CharField(max_length=10)

    @property
    def slug(self):
        return slugify(self.name)

My url:

path("map/<slug:slug>", MyView.as_view())

My view:

class MyView(DetailView):
    template_name="myapp/map.html"
    context_object_name = "province"
    model = Province

But when accessing page I get the following exception:

Cannot resolve keyword 'slug' into field. Choices are: code, id, name

Is there a way to solve this, without using explicit SlugField?

Upvotes: 1

Views: 301

Answers (2)

KatBot
KatBot

Reputation: 26

That's not a good solution, in your model you don't have SlugField and you don't store slug in db. So you can't query off of a property - that's the reason it doesn't work.

Upvotes: 1

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476977

Short answer: you can not store the slug as a @property since then it is not stored in the database.

The problem is that you can not filter at the database side on the slug now, since it does not exists there, a property only exists at the Django/Python level.

A slug should therefore be stored in the database. A DetailView, will make a query that looks for the record with the given slug at the database side. A SlugField, or one of its subclasses, will normally add a db_index=True on the field, and thus the database will make an index to lookup the record effectively.

If you do not want to implement methods to specify the slug, you can make use of the AutoSlugField field, from django-autoslug package. You install this with:

pip3 install django-autoslug

in your virtual environment. Next, you can add this field with:

from autoslug import AutoSlugField
from django.db import models

class Province(models.Model):
    name = models.CharField(max_length=30)
    code = models.CharField(max_length=10)
    slug = AutoSlugField(populate_from='name')

Upvotes: 1

Related Questions