Django 多重<;slug:slug>;根上的URL模式
手动输入URL对于我正在工作的网站来说非常重要。几乎所有流量都来自直接访问Django 多重<;slug:slug>;根上的URL模式,django,django-models,django-views,Django,Django Models,Django Views,手动输入URL对于我正在工作的网站来说非常重要。几乎所有流量都来自直接访问domain.com/some string/的用户。最小的流量将来自搜索引擎 这意味着让URL像人们一样容易记住是非常重要的 有没有办法在根目录中有多个路径('/',…)URL模式 例如,我的模型: from django.db import models class Category(models.Model): class Meta: verbose_name_plural = 'categori
domain.com/some string/
的用户。最小的流量将来自搜索引擎
这意味着让URL像人们一样容易记住是非常重要的
有没有办法在根目录中有多个路径('/',…)
URL模式
例如,我的模型:
from django.db import models
class Category(models.Model):
class Meta:
verbose_name_plural = 'categories'
title = models.CharField(max_length=50)
slug = models.SlugField(max_length=50)
description = models.TextField()
parent = models.ForeignKey('self', on_delete=models.PROTECT, null=True, blank=True)
def __str__(self):
return self.title
class Widget(models.Model):
title = models.CharField(max_length=50)
slug = models.SlugField(max_length=50)
# and various other parameters specific to Widget
category = models.ForeignKey('Category', on_delete=models.PROTECT, related_name = 'widgets', null=True)
def __str__(self):
return self.title
我的看法是:
from django.views.generic import ListView, DetailView
from .models import Category, Widget
class WidgetDetailView(DetailView):
model = Widget
slug_field = 'slug'
slug_url_kwarg = 'slug'
class CategoryListView(ListView):
model = Category
slug_field = 'slug'
slug_url_kwarg = 'slug'
和我的网址:
from django.urls import path
from .views import WidgetDetailView, CategoryListView
urlpatterns = [
path('<slug:slug>/', WidgetDetailView.as_view(), name='widget-detail')
path('<slug:slug>/', CategoryListView.as_view(), name='category-list')
]
从django.url导入路径
从.views导入WidgetDetailView、CategoryListView
URL模式=[
路径('/',WidgetDetailView.as_view(),name='widget-detail')
路径(“/”,CategoryListView.as_view(),name='category-list')
]
但显然,这适用于domain.com/widget slug/
,但不适用于domain.com/category slug/
,因为只有第一个URL模式被调用,结果是404
我认为一个解决方案是在Widget和Category模型中创建一个与Slug模型的通用关系。然后,slug“view”可以使用“content\u type.model”和“content\u object.pk”返回正确的模型视图。但这似乎是一个不必要的复杂解决方案,我认为这是一个常见问题
我错过了什么明显的东西吗?当我搜索诸如“根上的多弹头模式”之类的东西时,我似乎找不到任何其他人试图实现这一点
我知道这不是构建URL的理想方式,但正如我所说的,输入流量对这个网站至关重要。使URL尽可能容易记住是非常重要的
谢谢。是的,您必须创建一个视图,然后根据传递的slug处理分配到正确型号的操作。您不能以任何方式将同一路径模式映射到多个视图。是的,您必须创建一个视图,然后根据传递的slug将其分派到正确的模型类型。您不能以任何方式将同一路径模式映射到多个视图。解决方案1:调度视图 您可以创建一个
dispatch\u视图
,如下所示:
url.py
urlpatterns=[
路径(“/”,调度视图,name='dispatch')
]
views.py
从django.http导入Http404
def dispath_视图(请求、段塞):
尝试:
Category.objects.get(slug=slug)
除Category.DoesNotExist外:
尝试:
Widget.objects.get(slug=slug)
除Widget.DoesNotExist外:
升起Http404(“未找到”)
其他:
返回WidgetDetailView.as_view()(请求,slug)
其他:
返回CategoryListView.as_view()(请求,slug)
解决方案2:调度模型
更深入地说,您可以创建一个Dispatch
模型来存储模型的每个slug(在save()
和delete()
上),如下所示(未测试),以防止小部件
和类别
之间的slug重复:
类调度(models.Model):
类视图选项(models.TextChoices):
类别='CAT','myapp.views.CategoryListView'
WIDGET='WDT','myapp.views.WidgetDetailView'
视图=models.CharField(
最大长度=3,
choices=ViewChoices.choices,
默认值=ViewChoices.CATEGORY,
)
slug=型号。SlugField(最大长度=50,唯一性=真)
以及相关视图:
来自django.utils.module\u加载导入\u字符串
def dispath_视图(请求、段塞):
尝试:
dispatch\u obj=dispatch.objects.get(slug=slug)
除Dispatch.DoesNotExist外:
提高Http404()
其他:
视图=导入字符串(dispatch\u obj.get\u view\u display()).as\u view()
返回视图(请求、段塞)
解决方案3:使用模型继承
另一种方法是使用模型继承来防止小部件
和类别
::
class BaseSlug(models.Model):
slug = models.SlugField(max_length=50, unique=True)
class Widget(BaseSlug):
...
class Category(BaseSlug):
...
并使用解决方案1中的视图解决方案1:调度视图 您可以创建一个
dispatch\u视图
,如下所示:
url.py
urlpatterns=[
路径(“/”,调度视图,name='dispatch')
]
views.py
从django.http导入Http404
def dispath_视图(请求、段塞):
尝试:
Category.objects.get(slug=slug)
除Category.DoesNotExist外:
尝试:
Widget.objects.get(slug=slug)
除Widget.DoesNotExist外:
升起Http404(“未找到”)
其他:
返回WidgetDetailView.as_view()(请求,slug)
其他:
返回CategoryListView.as_view()(请求,slug)
解决方案2:调度模型
更深入地说,您可以创建一个Dispatch
模型来存储模型的每个slug(在save()
和delete()
上),如下所示(未测试),以防止小部件
和类别
之间的slug重复:
类调度(models.Model):
类视图选项(models.TextChoices):
类别='CAT','myapp.views.CategoryListView'
WIDGET='WDT','myapp.views.WidgetDetailView'
视图=models.CharField(
最大长度=3,
choices=ViewChoices.choices,
默认值=ViewChoices.CATEGORY,
)
slug=型号。SlugField(最大长度=50,唯一性=真)
以及相关视图:
来自django.utils.module\u加载导入\u字符串
def dispath_视图(请求、段塞):
尝试:
dispatch\u obj=dispatch.objects.get(slug=slug)
除Dispatch.DoesNotExist外:
提高Http404()
其他:
视图=导入字符串(dispatch\u obj.get\u view\u display()).as\u view()
返回视图(请求、段塞)
解决方案3:使用模型继承
另一种方法是使用模型继承来防止小部件
和类别
::
class BaseSlug(models.Model):
slug = models.SlugField(max_length=50, unique=True)
class Widget(BaseSlug):
...
class Category(BaseSlug):
...
并使用来自solut的视图