强制url中的两个子段都存在于datatabse中

时间:2018-10-19 13:25:20

标签: python django django-views django-urls django-class-based-views

我有多个类别,并通过ForeignKey与这些类别相关的一些详细信息。

例如,我有categorie1和detail1。

现在,我可以在url本地主机中调用类别:8000 / categorie1

 path('<slug>', views.CategorieView.as_view(), name='categorie_name')

和详细信息:localhost:8000 / categorie1 / detail1

path('<anythinghereworks>/<slug>', views.DetailView.as_view(), name='detail_name')

但是,如第一段所述,任何URL都可以使用,例如localhost:8000 / abc / details1。

我该如何针对2个弹头制作图案?

#Model

class Categorie(models.Model):
name = models.CharField(max_length=50,unique=True)
slug = models.SlugField(max_length=100,unique=True)

def __str__(self):
    return self.name

class Detail(models.Model):
    title = models.CharField(max_length=100)
    slug= models.SlugField(max_length=100,unique=True)
    categorie = models.ForeignKey('Categorie', on_delete=models.CASCADE,  related_name="details")


    def __str__(self):
        return self.title 

#Views

class CategorieView(DetailView):
    model = Categorie
    slug_field = 'slug'
    template_name = "app/categories.html"

class DetailView(DetailView):
    model = Detail
    slug_field = 'slug'
    template_name = "app/details.html"

#URLs

path('<slug>', views.CategorieView.as_view(), name='categorie_name'),
path('<anythinghereworks>/<slug>', views.DetailView.as_view(), name='detail_name'),

2 个答案:

答案 0 :(得分:1)

您使用slug: path converter [Django-doc]

path('<slug:slug>', views.CategorieView.as_view(), name='categorie_name'),
path(
    '<slug:anythinghereworks>/<slug:slug>',
    views.DetailDetailView.as_view(),
    name='detail_name'
),

路径转换器封装了一个正则表达式,该正则表达式指定了可接受的模式(例如int:路径转换器将只匹配一个数字序列),以及URL中的子字符串和对象之间的转换。例如,在使用slug的情况下,它可以是字符串,但是例如,在int:路径转换器中,目标是int

然后在您的View中,您可以覆盖get_queryset方法:

class DetailDetailView(DetailView):
    model = Detail
    slug_field = 'slug'
    template_name = "app/details.html"

    def get_queryset(self):
        return super(DetailView, self).get_queryset().filter(
            category__slug=self.request.kwargs['anythinghereworks']
        )

正确过滤查询集。对于具有无效sluganythinghereworks的请求,这将引发404。

(强烈)建议不要使用{em> not 来命名DetailView,因为它会覆盖模块中对新构造类的引用,并且因此,文件后面的其他视图将从您的 DetailView继承。

但是,我建议寻找比anythinghereworks更好的命名法。例如,您可以将参数重命名为category_slugdetail_slug。这样可以避免造成很多混乱,从而避免(潜在的)错误。

答案 1 :(得分:1)

首先,将x = 4.1 print(round(x)) print(round(x, 0)) 重命名为更有用的名称,然后重命名4 4.0 以避免与Django的'anythinghereworks'冲突。例如:

DetailView

然后,您可以覆盖DetailView以对path('<cat_slug>/<slug>', views.MyDetailView.as_view(), name='detail_name') get_object进行过滤。

slug

或者您可以覆盖cat_slug并在那里过滤类别。您无需在此处过滤class MyDetailView(DetailView): def get_object(self): return Detail.objects.get(slug=self.kwargs['slug'], categorie__slug='self.kwargs['cat_slug']) ,因为Django将在get_queryset方法中对其进行处理。

slug=self.kwargs['slug']

两种情况下都可以删除get_object,因为class MyDetailView(DetailView): def get_queryset(self): queryset = super().get_queryset() queryset = queryset.filter(categorie__slug=self.kwargs['cat_slug']) return queryset 是默认值。在第一种情况下,Django将使用您的slug_field = 'slug'方法,因此根本不会使用'slug'