Django Urls - 具有相同正则表达式的两个视图

时间:2017-09-20 19:07:39

标签: python django django-models django-urls

我有两个具有相同正则表达式的视图,如下所示。这是一个类别和文章视图,它们的入口slu will永远不会相同,所以应该没问题。但目前它并不能很好地运作,因为你们知道类别视图会被触发。

请不要建议使网址结构独特,类别和文章的slu will永远不会相同。它应该尽可能短。

urls.py

urlpatterns = [
    url(r'^index', index.Index.as_view(), name='index'),
    url(r'^search', search.Index.as_view(), name='search'),
    url(r'^(?P<slug>.+)$', category.Index.as_view(), name='category'),
    url(r'^(?P<slug>.+)$', article.Index.as_view(), name='article'),
]

如果没有可以找到的类别,我试图从views.category转回urls.py:

views.category.py

class Index(View):
    def get(self, request, slug):
        category = CategoryModel.objects.get(slug=slug)
        if category is None:
            return HttpResponseRedirect(reverse('article', args=[slug]))

        context = {
            'category': category
        }
        return render(request, 'category/index.html', context)

错误(但有一篇文章有​​slug'test123'):

NoReverseMatch at /wiki/test123
Reverse for 'article' with arguments '('test123',)' and keyword arguments '{}' not found. 0 pattern(s) tried: []

使用Python 3.6

4 个答案:

答案 0 :(得分:0)

为什么不尝试区分这样的网址

urlpatterns = [
    url(r'^index', index.Index.as_view(), name='index'),
    url(r'^search', search.Index.as_view(), name='search'),
    url(r'^category/(?P<slug>.+)$', category.Index.as_view(), name='category'),
    url(r'^article/(?P<slug>.+)$', article.Index.as_view(), name='article'),
]

您可以使用相同的正则表达式,而不会使URL不明确。

答案 1 :(得分:0)

您可以移除article.Index视图,而不是在Category没有对象时尝试重定向,您可以使用与article.Index相同的参数调用您在get中定义的方法{1}}方法接收article.Index视图。

示例

urls.py

urlpatterns = [
  url(r'^index', index.Index.as_view(), name='index'),
  url(r'^search', search.Index.as_view(), name='search'),
  url(r'^(?P<slug>.+)$', category.Index.as_view(), name='category'),
  # article url removed
]

views.category.py

from path.to.article import Index as ArticleIndexView

class Index(View):
    def get(self, request, slug):
        category = CategoryModel.objects.get(slug=slug)
        if category is None:
            # calling article app's Index get method
            article_index_view_obj = ArticleIndexView()
            return article_index_view_obj.get(request, slug)

        context = {
            'category': category
        }
        return render(request, 'category/index.html', context)

如果将article.Index类视图作为基于函数的视图。 您可以导入from path.to.article import index as article_index 然后,您可以直接调用article_index(request, slug)

,而不是实例化对象

答案 2 :(得分:0)

这里有几个问题。

(1)您使用reverse致电args,但您指定了kwarg

if category is None:
    return HttpResponseRedirect(reverse('article', args=[slug]))
  

使用参数'('test123',)'和关键字参数'{}'找不到'article'的反转。

确切地说 - 由于您没有提供关键字参数,因此无法找到匹配的网址格式。这是正确的:

if category is None:
    return HttpResponseRedirect(reverse('article', kwargs={'slug':slug}))

(2)你将一次又一次地使用相同的代码 - 一旦你修复了(1)我就会发生这种情况。因为如果reverse确实反转了网址 - reverse的结果当然也会匹配category网址,这意味着它只会再次调用category.Index视图。 / p>

我认为您的网址设置实际上可以正常工作,因为解析器会按顺序尝试所有网址,直到找到匹配项。我只是不确定您是否可以让视图返回会导致URL解析器启动的内容,并决定采用下一个网址(article)而不是刚解决的category。可能不是。

在这种情况下,如果你对重定向很好,你可以定义3个URL模式。 1表示将作为开关操作并分别重定向到CategoryView或ArticleView的视图。

否则,请与Sachin Kukreja在一个视图中处理两者的解决方案一起使用。

答案 3 :(得分:0)

最后我这样做了。实际上我想使用2种不同的视图但我觉得它也很好。有人看到了错误吗?

class Index(View):
    def get(self, request, slug):
        self.request = request
        self.slug = slug
        self.item = None
        is_article = ArticleModel.objects.filter(slug=self.slug).exists()

        if is_article:
            self.item = 'article'
            return self.article()

        is_category = CategoryModel.objects.filter(slug=self.slug).exists()
        if is_category:
            self.item = 'category'
            return self.category()

        self.item = None
        # 404 here
        return HttpResponse(self.item)

    def article(self):
        article = ArticleModel.objects.get(slug=self.slug)
        context = {
            'article': article
        }
        return render(self.request, 'article/index.html', context)

    def category(self):
        category = CategoryModel.objects.get(slug=self.slug)
        context = {
            'category': category
        }
        return render(self.request, 'article/index.html', context)