Django Urls - 具有相同正则表达式的两个视图
Posted
技术标签:
【中文标题】Django Urls - 具有相同正则表达式的两个视图【英文标题】:Django Urls - two views with same regular expression 【发布时间】:2018-03-01 23:35:01 【问题描述】:我有两个具有相同正则表达式的视图,如下所示。这是一个 Category 和一个 Article 视图,它们的条目 slug 永远不会相同,所以应该没问题。但目前它不能很好地工作,因为你知道类别视图会被触发。
请不要建议使 url 结构独特,类别和文章的 slug 永远不会相同。它应该尽可能短。
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
【问题讨论】:
如果您不这样做,而是使您的 URL 明确,您将有一个更轻松的时间。 这完全不是我想要的,但还是谢谢。 我想你可能不明白你要求路由器做什么。仅凭文字如何区分类别和文章? 【参考方案1】:你为什么不尝试像这样区分网址
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 不明确。
【讨论】:
【参考方案2】:您可以删除article.Index
视图,而不是在没有Category
的对象时尝试重定向,您可以调用您在article.Index
中定义的方法,其参数与get
方法在@ 中的参数相同987654325@查看。
示例:
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)
,而不是实例化对象。
【讨论】:
谢谢。这就是我发现的,但我认为可以使用两个不同的视图文件来解决这个问题。 是的,然后您可以实例化article.Index
视图并在创建的实例上调用get
方法或使用基于函数的视图,这比基于类的视图更容易。
是的对不起我想我不明白
不起作用。我猜是因为它是一个 as_view() 类【参考方案3】:
这里有几个问题。
(1) 您使用args
调用reverse
,但您指定了kwarg
。
if category is None:
return HttpResponseRedirect(reverse('article', args=[slug]))
找不到带有参数“('test123',)”和关键字参数“”的“文章”。
确切地说 - 因为您没有提供关键字参数,所以它找不到匹配的 URL 模式。这是正确的:
if category is None:
return HttpResponseRedirect(reverse('article', kwargs='slug':slug))
(2) 您将一次又一次地使用相同的代码 - 这是我希望在您修复 (1) 后发生的情况。因为如果 reverse
确实反转了 URL - reverse
的结果当然也会匹配 category
URL,这意味着它会再次调用 category.Index
视图。
我认为您的 URL 设置实际上可以工作,因为解析器确实会按顺序尝试所有 URL,直到出现匹配的 URL。我只是不确定您是否可以让视图返回导致 URL 解析器启动并决定采用下一个 URL (article
) 而不是刚刚解析的 category
的内容。应该不会吧。
在这种情况下,如果您可以使用重定向,您可以定义 3 个 URL 模式。 1 表示将作为开关操作并分别重定向到 CategoryView 或 ArticleView 的视图。
否则,请使用 Sachin Kukreja 的解决方案,在一个视图中处理这两个问题。
【讨论】:
【参考方案4】:最后我做到了。实际上我想使用 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)
【讨论】:
以上是关于Django Urls - 具有相同正则表达式的两个视图的主要内容,如果未能解决你的问题,请参考以下文章
如何在我的 Django urls.py 中使用单个正则表达式捕获多个参数?