手动输入URL对于我正在做的网站来说是非常重要的。几乎所有的流量都来自直接去domain.com/some-string/的人。最少的流量将来自搜索引擎。
这意味着让URL像人们一样容易记住是非常重要的。
根目录中有多个path('<slug:slug>/', ...) 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')
]但是,这显然适用于domain.com/widget-slug/,而不是domain.com/category-slug/,因为只有第一个URL模式被调用并得到一个404。
我认为一种解决方案是在Widget和分类模型中创建一个GenericRelation到一个段塞模型。弹格' view‘然后可以使用'content_type.model’和'content_object.pk‘返回正确的模型视图。但这似乎是一个不必要的复杂的解决方案,我认为这是一个共同的问题。
我漏掉了什么明显的东西吗?当我搜索“根上的多个弹状模式”这样的东西时,我似乎找不到其他人试图实现这一点。
我知道这不是一个理想的方式来构造URL,但正如我说过,在流量类型是这个网站的关键。使URL尽可能容易记住是非常重要的。
谢谢。
发布于 2020-08-23 21:10:02
解决方案1:调度视图
您可以创建这样的dispatch_view:
urls.py
urlpatterns = [
path('<slug:slug>/', dispatch_view, name='dispatch')
]views.py
from django.http import Http404
def dispath_view(request, slug):
try:
Category.objects.get(slug=slug)
except Category.DoesNotExist:
try:
Widget.objects.get(slug=slug)
except Widget.DoesNotExist:
raise Http404("Not found")
else:
return WidgetDetailView.as_view()(request, slug)
else:
return CategoryListView.as_view()(request, slug)解决方案2:调度模型
为了更深入地理解,您可以创建一个Dispatch模型,它将存储模型的每个段塞(在save()和delete()上),如下所示(未经测试),以防止Widget和Category之间的段塞重复
class Dispatch(models.Model):
class ViewChoices(models.TextChoices):
CATEGORY = 'CAT', 'myapp.views.CategoryListView'
WIDGET = 'WDT', 'myapp.views.WidgetDetailView'
view = models.CharField(
max_length=3,
choices=ViewChoices.choices,
default=ViewChoices.CATEGORY,
)
slug = models.SlugField(max_length=50, unique=True)以及相关的观点:
from django.utils.module_loading import import_string
def dispath_view(request, slug):
try:
dispatch_obj = Dispatch.objects.get(slug=slug)
except Dispatch.DoesNotExist:
raise Http404()
else:
view = import_string(dispatch_obj.get_view_display()).as_view()
return view(request, slug)解决方案3:使用模型继承
另一种方法是使用模型继承来防止Widget和Category之间的段塞重复:
class BaseSlug(models.Model):
slug = models.SlugField(max_length=50, unique=True)
class Widget(BaseSlug):
...
class Category(BaseSlug):
...并使用解决方案1中的视图
发布于 2020-08-23 20:52:50
是的,您必须创建一个视图,然后根据传递的段塞处理调度到正确的模型类型。您不能以任何方式将相同的路径模式映射到多个视图。
https://stackoverflow.com/questions/63551874
复制相似问题