Использование имен переменных, а не целых в пути URL Django - PullRequest
0 голосов
/ 14 декабря 2018

У меня есть модель с именем Label:

class Label(models.Model):
"""The label a song was released on."""
name = models.CharField(max_length=100)

def __str__(self):
    """String for representing the model object."""
    return self.name

И я определяю пути URL для каждого отдельного экземпляра модели метки:

# Page for a single label.
path('labels/<int:label_id>/', views.label, name='label'),

Возможно лииспользовать атрибут label.name вместо int: label_id в пути URL?Как это можно сделать?

Это соответствующий код в views.py:

def label(request, label_id):
"""Show a single label and associated songs."""
label = Label.objects.get(id=label_id)
context = {'label': label}

return render(request, 'great_songs_app/label.html', context)

Ответы [ 2 ]

0 голосов
/ 14 декабря 2018

Да, вы можете изменить имя вашего входящего параметра и URL:

# Page for a single label.
path('labels/<str:name>/', views.label, name='label'),

def label(request, name):
    try:
       label = Label.objects.get(name=name)
    except Label.MultipleObjectsReturned:
       label = None # TODO have a strategy

Обратите внимание, что, поскольку вы отключаете неуникальный параметр, вы можете столкнуться.Кроме того, у вас есть очень открытый CharField, который может включать пробелы, косые черты и т. Д. Лучше было бы иметь явный «SlugField» для генерации этого слага:

class Label(models.Model):
    name = models.CharField(max_length=100)
    slug = models.SlugField()

Затем вы можете установить этот SlugFieldдля предварительного заполнения в вашем админ-файле ( docs ):

class LabelAdmin(admin.ModelAdmin):
    prepopulated_fields = {"slug": ("name",)}

Наконец, я бы настоятельно рекомендовал использовать DetailView для этого, где вы получите много предварительно настроенных функций для "бесплатно"":

from django.views.generic.detail import DetailView
class LabelDetailView(DetailView):
    queryset = Label.objects.all()
    slug_field = 'slug' # Or Name, Or Id
    slug_url_kwargs = 'slug' # Or name or label_id

Подробнее о Подробном представлении на основе классов

0 голосов
/ 14 декабря 2018

Это буквально то же самое, вы просто переключаете int для str (= строка) и id для name:

urls:

path('labels/<str:label_name>/', views.label, name='label')

view:

def label(request, label_name):
    l = Label.objects.get(name=label_name)
    …

Было бы разумно добавить unique=True для предотвращения столкновений.

Если вы планируете иметь имена с пробелами или другими не относящимися к URL символами, вместо этого вы можете использовать slug для частей URL:

class Label(models.Model):
    name = models.CharField(max_length=100)
    slug = models.SlugField(max_length=100, editable=False)

    def save(self, *args, **kwargs): # create slug from name when saving for the first time
        if not self.slug:
            self.slug = slugify(self.name)
        super(Label, self).save(*args, **kwargs)

path('labels/<slug:label_slug>/', views.label, name='label')

def label(request, label_slug):
    l = Label.objects.get(slug=label_slug)
    …

Также удобно использовать слаг в качестве первичного ключа.

...