通过 mixins 处理带有自定义 slug 的重复对象

Posted

技术标签:

【中文标题】通过 mixins 处理带有自定义 slug 的重复对象【英文标题】:handling duplicate objects with custom slugs via mixins 【发布时间】:2019-07-28 12:36:07 【问题描述】:

我们有一个 django 应用程序,其中包含两个对象,城市和事件。对我们来说,一个常见的 url 模式是:

app.com/city/name-of-city/event/name-of-event 其中name-of-cityname-of-event 是蛞蝓。例如:

class City(models.Model):
      name = models.CharField(max_length=100, unique=True)
      slug = AutoSlugField(populate_from='name', always_update=True, unique=True, sep='-', max_length=255)
      ...

事件在 Event 模型中以相同的方式获得它们的 slug:

slug = AutoSlugField(populate_from='name', always_update=True, unique_with='city', sep='-', max_length=255)

我难以解决的问题是如何处理同一个城市有多个同名事件的实例。

mixins.py

class CityMixin(object):
    city_slug_url_kwarg = 'slug'
    city = None

    def fetch_city(self, request, *args, **kwargs):
        if not self.city:
            self.city = get_object_or_404(
                City, slug=kwargs.get(self.city_slug_url_kwarg))
        return self.city

    def get_context_data(self, **kwargs):
        kwargs.setdefault('city', self.city)
        return super(CityMixin, self).get_context_data(**kwargs)

    def dispatch(self, request, *args, **kwargs):
        """
        Sets 'city' within the view
        """
        self.city = self.fetch_city(request, *args, **kwargs)
        return super(CityMixin, self).dispatch(request, *args, **kwargs)


class EventMixin(CityMixin):
    city_slug_url_kwarg = 'city_slug'
    event_slug_url_kwarg = 'slug'
    event = None

    def fetch_event(self, request, *args, **kwargs):

        if not self.event:
            event = get_list_or_404(
                Event, slug=kwargs.get(self.event_slug_url_kwarg))

        return self.event

    def dispatch(self, request, *args, **kwargs):
        """
        Sets 'city' and 'event' within the view
        """
        user = request.user
        self.city = self.fetch_city(request, *args, **kwargs)
        self.event = self.fetch_event(request, *args, **kwargs)
        if self.event.city != self.city:
            raise Http404

        return super(EventMixin, self).dispatch(request, *args, **kwargs)

如果我通过以下方式请求事件:

event = get_object_or_404(Event, slug=kwargs.get(self.event_slug_url_kwarg))

如果有多个同名事件,它会抛出一个错误(MultipleObjectsReturned)。

如果我通过以下方式请求事件:

event = get_list_or_404(Event, slug=kwargs.get(self.event_slug_url_kwarg))

并且存在相同的事件,应用程序不知道列表中的哪个 obj 或索引是正确的 obj。

是否有一种方法可以确保请求正确的 obj 并且还可以处理重复事件名称的情况?

谢谢

【问题讨论】:

为什么会有多个同名事件?你的 autoslugfield 上有 unique_with='city' 例如,在同一个城市(即伦敦)可以创建多个名为“鸡尾酒会”的活动,并且可以在许多不同的城市举办“鸡尾酒会” 【参考方案1】:

每个城市的蛞蝓总是唯一的,因为您已经设置了 unique_with 属性。但是您没有在查询中使用城市,因此您将获得所有城市的事件 - 它们可以使用相同的 slug。您需要在查找中使用城市:

event = get_list_or_404(
    Event,
    slug=kwargs.get(self.event_slug_url_kwarg),
    city__slug=kwargs.get(self.city_slug_url_kwarg)
)

【讨论】:

以上是关于通过 mixins 处理带有自定义 slug 的重复对象的主要内容,如果未能解决你的问题,请参考以下文章

自定义帖子类型 Slug 冲突

Wordpress - 如何通过 slug 获取自定义帖子类型?

在函数文件中更改自定义帖子类型 slug

您可以使用 LESS mixins 创建自定义断点吗?

net core天马行空系列: 一个接口多个实现类,利用mixin技术通过自定义服务名,实现精准属性注入

来自自定义帖子分类法循环的 slug 列表(Wordpress + ACF Pro)