在 django generic.DetailView 里设置缓存(重写 get_object )

2023-02-18 14:03:23 浏览数 (1)

开发环境

  • django 1.11

DetailView  的相关源码

# ..Libsite-packagesdjangoviewsgenericdates.py

代码语言:javascript复制
class DateDetailView(SingleObjectTemplateResponseMixin, BaseDateDetailView):
    """
    Detail view of a single object on a single date; this differs from the
    standard DetailView by accepting a year/month/day in the URL.
    """
    template_name_suffix = '_detail'
代码语言:javascript复制
class BaseDateDetailView(YearMixin, MonthMixin, DayMixin, DateMixin, BaseDetailView):
    """
    Detail view of a single object on a single date; this differs from the
    standard DetailView by accepting a year/month/day in the URL.
    """
    def get_object(self, queryset=None):
        """
        Get the object this request displays.
        """
        year = self.get_year()
        month = self.get_month()
        day = self.get_day()
        date = _date_from_string(year, self.get_year_format(),
                                 month, self.get_month_format(),
                                 day, self.get_day_format())

        # Use a custom queryset if provided
        qs = self.get_queryset() if queryset is None else queryset

        if not self.get_allow_future() and date > datetime.date.today():
            raise Http404(_(
                "Future %(verbose_name_plural)s not available because "
                "%(class_name)s.allow_future is False."
            ) % {
                'verbose_name_plural': qs.model._meta.verbose_name_plural,
                'class_name': self.__class__.__name__,
            })

        # Filter down a queryset from self.queryset using the date from the
        # URL. This'll get passed as the queryset to DetailView.get_object,
        # which'll handle the 404
        lookup_kwargs = self._make_single_date_lookup(date)
        qs = qs.filter(**lookup_kwargs)

        return super(BaseDetailView, self).get_object(queryset=qs)

# ..Libsite-packagesdjangoviewsgenericdetail.py

代码语言:javascript复制
class SingleObjectMixin(ContextMixin):
    """
    Provides the ability to retrieve a single object for further manipulation.
    """
    model = None
    queryset = None
    slug_field = 'slug'
    context_object_name = None
    slug_url_kwarg = 'slug'
    pk_url_kwarg = 'pk'
    query_pk_and_slug = False

    def get_object(self, queryset=None):
        """
        Returns the object the view is displaying.

        By default this requires `self.queryset` and a `pk` or `slug` argument
        in the URLconf, but subclasses can override this to return any object.
        """
        # Use a custom queryset if provided; this is required for subclasses
        # like DateDetailView
        if queryset is None:
            queryset = self.get_queryset()

        # Next, try looking up by primary key.
        pk = self.kwargs.get(self.pk_url_kwarg)
        slug = self.kwargs.get(self.slug_url_kwarg)
        if pk is not None:
            queryset = queryset.filter(pk=pk)

        # Next, try looking up by slug.
        if slug is not None and (pk is None or self.query_pk_and_slug):
            slug_field = self.get_slug_field()
            queryset = queryset.filter(**{slug_field: slug})

        # If none of those are defined, it's an error.
        if pk is None and slug is None:
            raise AttributeError("Generic detail view %s must be called with "
                                 "either an object pk or a slug."
                                 % self.__class__.__name__)

        try:
            # Get the single item from the filtered queryset
            obj = queryset.get()
        except queryset.model.DoesNotExist:
            raise Http404(_("No %(verbose_name)s found matching the query") %
                          {'verbose_name': queryset.model._meta.verbose_name})
        return obj

看了源码发现 get_object,就是返回 单一的对象,相当于 return YouModel.objects.get(pk='pk') 

重写 generic.DetailView 里面的 get_object

代码语言:javascript复制
class DetailView(generic.DetailView):
    model = Article  # 模型名称
    template_name = 'lw-article.html' # 模板名称
    context_object_name = "article" # 传递给模板的变量名称

    def get_object(self, queryset=None):
        """
        Get the object this request displays. 获取对应文章的信息
        """
        # 文章详情增加缓存
        pk = self.kwargs.get(self.pk_url_kwarg)  # 获取主键
        obj = cache.get("article_obj_%s" % pk)  # 获取该主键的缓存
        if not obj:  # 如果没有就
            obj = super(DetailView, self).get_object()  # get_object() 重新获取单个对象
            cache.set("article_obj_%s" % pk, obj, CACHE_TIMEOUT_2D)  # 设置该主键的缓存

        return obj

0 人点赞