繁体   English   中英

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

[英]force both slugs in url to exist in datatabse

我有多个类别,并通过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'),

您使用slug: 路径转换器 [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 slug的请求,这将引发404。

这也是(强)建议不要说出什么DetailView ,因为这将覆盖你的模块中的新构造类的参考,从而其他视图在文件后面,就会从继承DetailView

我劝不过看起来比一个更好的命名anythinghereworks 例如,您可以将参数重命名为category_slugdetail_slug 这样可以避免很多混乱,从而避免(潜在的)错误。

首先,将'anythinghereworks'重命名为更有用的名称,然后重命名DetailView以避免与Django的DetailView冲突。 例如:

path('<cat_slug>/<slug>', views.MyDetailView.as_view(), name='detail_name')

然后,您可以覆盖get_object以对slugcat_slug进行过滤。

class MyDetailView(DetailView):
    def get_object(self):
        return Detail.objects.get(slug=self.kwargs['slug'], categorie__slug='self.kwargs['cat_slug'])

或者,您可以覆盖get_queryset并在那里过滤类别。 您无需在此处过滤slug=self.kwargs['slug'] ,因为Django将在get_object方法中进行处理。

class MyDetailView(DetailView):
    def get_queryset(self):
        queryset = super().get_queryset()
        queryset = queryset.filter(categorie__slug=self.kwargs['cat_slug'])
        return queryset

在两种情况下都可以删除slug_field = 'slug' ,因为'slug'是默认值。 在第一种情况下,Django将使用您的get_object方法,因此根本不会使用slug_field

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM