Django - urls 中的视图或条件选择两种 url 模式中的一种,以判断参数是不是具有值或为 NONE

Posted

技术标签:

【中文标题】Django - urls 中的视图或条件选择两种 url 模式中的一种,以判断参数是不是具有值或为 NONE【英文标题】:Django - View or condition in urls chooses one of two url patterns with regard to whether the parameter has the value or is NONEDjango - urls 中的视图或条件选择两种 url 模式中的一种,以判断参数是否具有值或为 NONE 【发布时间】:2019-01-22 12:02:48 【问题描述】:

有两种型号:groupsposts。帖子可以是以下两种中的一种:分配给组和未分配给组。 posts 模型中将组分配给帖子的外键字段是可选的。属于某个组的帖子应该与不属于该组的帖子具有不同的地址。这是一般规则。前一个地址是当帖子不属于任何组时,如果是后一个地址。

.../posts/[year]/[month]/[day]/[slug of the post]/

.../groups/[name of the group]/posts/[year]/[month]/[day]/[slug of the post]/

问题出现了。创建帖子后,两个网址都可以使用。

这并不奇怪,因为我include 来自posts 应用的网址在urls.pygroups 应用中。

我想要做的是使 url 地址对于 group 参数是可选的(无论它是否被传递)。它可以像这样工作:

如果groups参数不是None,从groups.urls中选择url 如果groups参数不是None,则从posts.urls中排除url

基本上我只想选择一个网址,而不是两个。

在 Django 中是否有可能以简单的方式做到这一点?还是唯一的解决方案是创建两个模型/两个应用而不是一个?

我的代码摘录:

groups/urls.py

app_name = 'groups'

urlpatterns = [
    ...
    path('<slug:slug>/posts/', include('posts.urls', namespace='grouppost')),
    ...
]

posts/urls.py

app_name = 'posts'

urlpatterns = [
    path('', views.PostList.as_view(), name='list'),
    path('create', views.CreatePost.as_view(), name='create'),
    path('<int:year>/<int:month>/<int:day>/<slug:slug>/', views.PostDetail.as_view(), name='detail'),
    path('<int:year>/<int:month>/<int:day>/<slug:slug>/update/', views.UpdatePost.as_view(), name='update'),
    path('<int:year>/<int:month>/<int:day>/<slug:slug>/delete/', views.DeletePost.as_view(), name='delete'),
]

我正在使用 Django 2.0.7。

更新 16.08

我也是includepath在mu根urls.py。很抱歉遗漏了这些重要信息。

urls.py

urlpatterns = [
    ...
    path('groups/', include('groups.urls')),
    path('posts/', include('posts.urls')),
    ...
] 

【问题讨论】:

什么调用了 url?一个阿贾克斯电话?一个视图? 为什么将帖子 url 添加到组而不是根 urls.py?你说的可选是什么意思?在您的视图中还是在模板中? 视图调用 url。我的根urls.py 中的path 中也有include posts。这就是为什么我的问题列表中的第一个 url 地址也有效。在我看来,我希望它是可选的。我想要的是,如果帖子模型中的group 外键不是None,则第一个url 地址将被停用,如果帖子模型中的group 外键是None,那么列表中的第二个url 地址行不通。 我要补充一点,如果group 外键是None,那么地址/groups/None/posts/[year]/[month]/[day]/[slug of the post]/ 有效...它不应该是这样的,即使我可以在模板中处理没有人会输入那个地址... 【参考方案1】:

您应该尽量避免 url 中的逻辑。这就是更低级别的视图或业务逻辑的用途。相反,您可以创建一个充当重定向页面的视图,该页面采用您想要的参数,并根据它的内容重定向到正确的 url。

如果这样做,则需要跟踪所有请求参数。

# url (located wherever you want):
(r'post-redirection/<string:posts_or_group>/<int:year>/<int:month>/<int:day>/<slug:slug>/', post_redirection, name="post_redirection")

# view:
def post_redirection(request, post_or_group, year, month, day, slug):
    if post_or_group == "post":
         post_url_name = "..." # This is the url that you want to go to if it is a request to .../posts/[year]/[month]/[day]/[slug of the post]/
         return HttpResponseRedirect(reverse(post_url_name, kwargs="year": year, "month": month, "day": day, "slug": slug))

    elif post_or_group == "groups":
         group_url_name = "..." # This is the url that you want to go to if it is a request to .../groups/[name of the group]/posts/[year]/[month]/[day]/[slug of the post]/
         return HttpResponseRedirect(reverse(group_url_name, kwargs="year": year, "month": month, "day": day, "slug": slug))

    else:
        # error. However you want to handle it. You could return an error response or do something else. Maybe return a message that says they didn't choose the right option.

您可能遇到的唯一问题是保留请求数据(即 request.POST 或 request.GET)。您仍然可以使用这种方法,您只需要找到一种方法在新的重定向请求中传递该数据,因为该数据仅持续一个请求。

【讨论】:

以上是关于Django - urls 中的视图或条件选择两种 url 模式中的一种,以判断参数是不是具有值或为 NONE的主要内容,如果未能解决你的问题,请参考以下文章

Django 模板视图 url 或 FileField

Django url 模式不是注册的视图函数或模式

Django框架中的视图和模板

当前路径具有子目录或 url 参数时,使用 AJAX 调用视图函数不起作用(Django)

Django:视图如何从 url 获取多个值?

Django:两个模型中的一个 url 搜索(cbv)