django通用视图的DetailView

5 篇文章 0 订阅
3 篇文章 0 订阅

SingleObjectMixin

主要功能:

  1. def get_queryset(self):返回query_set里的所有对象

    • 如果提供的queryset为空且model不为空,返回self.model._default_manager.all()
    • 提供了queryset,返回self.queryset.all()
  2. get_object(self, queryset=None):根据请求url里的关键字参数pk或者slug过滤query_set来获取单一对象(obj)

    queryset = queryset.filter(pk=pk) 或者 queryset = queryset.filter(**{slug_field: slug})
    obj = queryset.get()
    return obj
    
  3. def get_context_data(self, **kwargs):将对象(obj)其插入到渲染模板所需的上下文中

    self.object = self.get_object
    context['object'] = self.object
    # 或者可以自定义对象名,两者是同时存在的:
    context[context_object_name] = self.object
    
class SingleObjectMixin(ContextMixin):
    """
    提供了可以操纵检索单一对象的能力
    """
    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):
        # 根据pk和slug查找object
        # 如果自定义了queryset就使用它,这是子类需要的
        # 比如DateDetailView
        if queryset is None:
            queryset = self.get_queryset()

        # 接着试着查询pk
        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)

        # 接着试着查询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 in the URLconf." % 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


    def get_context_data(self, **kwargs):
        """插入单一对象到上下文字典中"""
        context = {}
        if self.object:
            context['object'] = self.object
            context_object_name = self.get_context_object_name(self.object)
            if context_object_name:
                context[context_object_name] = self.object
        context.update(kwargs)
        return super().get_context_data(**context)

BaseDetailView

BaseDetailView主要是组合SingleObjectMixinview的各种方法来实现服务器处理一个获取单一对象的get请求的一般流程。

class BaseDetailView(SingleObjectMixin, View):
    """一个展示单一对象的基本视图"""
    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        context = self.get_context_data(object=self.object)
        return self.render_to_response(context)

SingleObjectTemplateResponseMixin

SingleObjectTemplateResponseMixin主要是重写了get_template_names方法,也就是其模板的名字是

app_label + model_name(小写) + template_name_suffix(_detail)

class SingleObjectTemplateResponseMixin(TemplateResponseMixin):
    template_name_field = None
    template_name_suffix = '_detail'

    def get_template_names(self):
        	# 省略....
            if isinstance(self.object, models.Model):
                object_meta = self.object._meta
                names.append("%s/%s%s.html" % (
                    object_meta.app_label,
                    object_meta.model_name,
                    self.template_name_suffix
                ))
            elif getattr(self, 'model', None) is not None and issubclass(self.model, models.Model):
                names.append("%s/%s%s.html" % (
                    self.model._meta.app_label,
                    self.model._meta.model_name,
                    self.template_name_suffix
                ))



        return names

DetailView

class DetailView(SingleObjectTemplateResponseMixin, BaseDetailView):
    """
    Render a "detail" view of an object.

    By default this is a model instance looked up from `self.queryset`, but the
    view will support display of *any* object by overriding `self.get_object()`.
    """

总结

  1. SingleObjectMixin.get_context_data获取含有单个对象的上下文(context)

  2. SingleObjectTemplateResponseMixin.render_to_response利用上下文进行渲染并返回响应,并重写其

    get_template_names方法

  3. BaseDetailView组合SingleObjectMixin和View并实现get请求和分发

  4. DetailView组合SingleObjectTemplateResponseMixinBaseDetailView实现完整的逻辑处理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值