在Django网址路径中使用变量名称而不是整数

时间:2018-12-14 17:04:35

标签: django python-3.x django-urls

我有一个名为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'),

是否可以在URL路径中使用label.name属性而不是int:label_id?该怎么办?

这是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 :(得分:1)

是的,您可以更改传入参数的名称和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

详细了解Class Based Detail View

答案 1 :(得分:0)

从本质上讲是一样的,您只需将int(=字符串)的strid的{​​{1}}切换:

网址:

name

视图:

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

添加def label(request, label_name): l = Label.objects.get(name=label_name) … 以防止冲突是明智的。

如果您打算使用带有空格或其他非URL友好的字符的名称,则可能要使用slug作为URL部分:

unique=True

使用子弹作为主键也很方便。