首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >根上的多个<slug:slug> the模式

根上的多个<slug:slug> the模式
EN

Stack Overflow用户
提问于 2020-08-23 20:49:35
回答 2查看 702关注 0票数 1

手动输入URL对于我正在做的网站来说是非常重要的。几乎所有的流量都来自直接去domain.com/some-string/的人。最少的流量将来自搜索引擎。

这意味着让URL像人们一样容易记住是非常重要的。

根目录中有多个path('<slug:slug>/', ...) URL模式吗?

例如,我的模型:

代码语言:javascript
复制
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

我的看法是:

代码语言:javascript
复制
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'

我的网址是:

代码语言:javascript
复制
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尽可能容易记住是非常重要的。

谢谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-08-23 21:10:02

解决方案1:调度视图

您可以创建这样的dispatch_view

urls.py

代码语言:javascript
复制
urlpatterns = [
  path('<slug:slug>/', dispatch_view, name='dispatch')
]

views.py

代码语言:javascript
复制
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()上),如下所示(未经测试),以防止WidgetCategory之间的段塞重复

代码语言:javascript
复制
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)

以及相关的观点:

代码语言:javascript
复制
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:使用模型继承

另一种方法是使用模型继承来防止WidgetCategory之间的段塞重复:

代码语言:javascript
复制
class BaseSlug(models.Model):
    slug = models.SlugField(max_length=50, unique=True)

class Widget(BaseSlug):
    ...

class Category(BaseSlug):
    ...

并使用解决方案1中的视图

票数 3
EN

Stack Overflow用户

发布于 2020-08-23 20:52:50

是的,您必须创建一个视图,然后根据传递的段塞处理调度到正确的模型类型。您不能以任何方式将相同的路径模式映射到多个视图。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63551874

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档