django 원본 해석 유니버설 보기 편의ListView

29121 단어 django 일반 보기
                 ,         ,      。      。

계승 방식
  • ListView(MultipleObjectTemplateResponseMixin, BaseListView)
  • MultipleObjectTemplateResponseMixin
  • TemplateResponseMixin

  • BaseListView
  • MultipleObjectMixin
  • ContextMixin

  • View


  • graph TD
        ListView[ListView] --> |            | MultipleObjectTemplateResponseMixin(MultipleObjectTemplateResponseMixin) 
        ListView --> |     get           | BaseListView(BaseListView)
        MultipleObjectTemplateResponseMixin --> |            | TemplateResponseMixin(TemplateResponseMixin)
        BaseListView --> |           | MultipleObjectMixin(MultipleObjectMixin)
        BaseListView --> |                  |View(View)
        MultipleObjectMixin -->|              | ContextMixin(ContextMixin)
  • 처음 블로그에 올렸는데 이 안에 있는 관계도 문법이 어떤지 몰라서 노트에 붙여서 이렇게 됐어요.어떤 신이 쓰실지 알려주세요. 감사합니다.

  • ListView 프로세스
    url는 Request 대상과 다른 사용자 정의 매개 변수를ListView에 전송합니다.View 부류는 초기화 방법을 실행하고 사용자 정의 변수를 클래스 속성에 추가하고 as 를 호출합니다view 방법은 요청 방식에 대한 처리 함수를 찾습니다. (BaseListView의 get 방법)get 방법은 페이지 나누기 여부를 판단하는 문장을 실행하고MultipleObjectMixin 클래스의 get 를 호출합니다context_데이터 방법(부류ContextMixin)은 조회 데이터를 가져오고TemplateResponseMixin의render 를 호출합니다.to_response 방법은 렌더링된 템플릿을 되돌려줍니다.Template Response Mixin에 필요한 템플릿 정보는 Multiple Object Template Response Mixin 클래스에서 정의됩니다.ListView 클래스는 다중 상속을 사용했고 각 상속은 부모 클래스에 대응하는 매개 변수 정보를 정의하여 결합성을 크게 낮추었다.
    사용법
    일반적인 매개변수:
  • 모델,queryset이 지정한 조회 모듈이나 조회 집합
  • context_object_name 되돌아오는 상하문 이름 지정하기
  • template_name 렌더링할 템플릿 파일 지정
  • 결과 반환
    지정된 질의 세트를 반환하고 템플릿을 렌더링합니다.
    코드 해석
    ContextMixin
    주요 매개 변수
  • extra_context에 사용자 정의 데이터를 추가합니다. 사전 형식으로
  • 기능 함수
  • get_context_데이터가 상하문 데이터를 되돌려줍니다.'view'키워드 추가,self의 모든 데이터 (매개 변수),extracontext 내용
  • 코드
    class ContextMixin:
        """
        A default context mixin that passes the keyword arguments received by
        get_context_data() as the template context.
        """
        extra_context = None
    
        def get_context_data(self, **kwargs):
            if 'view' not in kwargs:
                kwargs['view'] = self
            if self.extra_context is not None:
                kwargs.update(self.extra_context)
            return kwargs

    MultipleObjectMixin
    물려받다
    ContextMixin에서 상속
    주요 매개 변수
  • 조회 대상 정의(queryset, 모델)
  • 정의 페이지 나누기(paginate by,paginate orphans)
  • 컨텍스트에서 반환되는 이름 정의(context object name)
  • 정렬 기준 정의(ordering)
  • 렌더링 템플릿 정의(get allow empty)(여기서 확인하지 않음)
  • 기능 함수
  • get_queryset은 데이터 조회 집합을 되돌려주고 정렬합니다. (기본적으로 정렬하지 않습니다.)여기queryset과 모델은 하나를 정의해야 합니다. 그렇지 않으면 이상이 발생할 수 있습니다.모델을 지정하면 기본 관리자를 사용하여 검색합니다. (모델에 정의된 첫 번째 관리자는 기본 관리자입니다. 지정하지 않으면 object입니다.)
  • get_ordering은 지정한 정렬을 되돌려줍니다. ordering의 값
  • paginate_queryset get_paginate_by get_paginator get_paginate_orphans 페이지 관련
  • get_allow_empty 반환getallow_empty 값, True 또는 False.기본값은 True
  • 입니다.
  • get_context_object_name 컨텍스트 이름 반환, contextobject_name의 값입니다.기본값은 데이터 객체list
  • get_context_데이터 수가 데이터를 반환하고 부모 클래스'ContextMixin '을 호출하고 매개 변수에 따라 페이지를 나눈다.데이터는'데이터베이스 조회 데이터'와 페이지 관련 정보(페이지 나누기 여부, 페이지 수 등)를 포함한다.

  • 코드
    class MultipleObjectMixin(ContextMixin):
        """A mixin for views manipulating multiple objects."""
        allow_empty = True
        queryset = None
        model = None
        paginate_by = None
        paginate_orphans = 0
        context_object_name = None
        paginator_class = Paginator
        page_kwarg = 'page'
        ordering = None
    
        def get_queryset(self):
            """
            Return the list of items for this view.
    
            The return value must be an iterable and may be an instance of
            `QuerySet` in which case `QuerySet` specific behavior will be enabled.
            """
            if self.queryset is not None:
                queryset = self.queryset
                if isinstance(queryset, QuerySet):
                    queryset = queryset.all()
            elif self.model is not None:
                queryset = self.model._default_manager.all()
            else:
                raise ImproperlyConfigured(
                    "%(cls)s is missing a QuerySet. Define "
                    "%(cls)s.model, %(cls)s.queryset, or override "
                    "%(cls)s.get_queryset()." % {
                        'cls': self.__class__.__name__
                    }
                )
            ordering = self.get_ordering()
            if ordering:
                if isinstance(ordering, str):
                    ordering = (ordering,)
                queryset = queryset.order_by(*ordering)
    
            return queryset
    
        def get_ordering(self):
            """Return the field or fields to use for ordering the queryset."""
            return self.ordering
    
        def paginate_queryset(self, queryset, page_size):
            """Paginate the queryset, if needed."""
            paginator = self.get_paginator(
                queryset, page_size, orphans=self.get_paginate_orphans(),
                allow_empty_first_page=self.get_allow_empty())
            page_kwarg = self.page_kwarg
            page = self.kwargs.get(page_kwarg) or self.request.GET.get(page_kwarg) or 1
            try:
                page_number = int(page)
            except ValueError:
                if page == 'last':
                    page_number = paginator.num_pages
                else:
                    raise Http404(_("Page is not 'last', nor can it be converted to an int."))
            try:
                page = paginator.page(page_number)
                return (paginator, page, page.object_list, page.has_other_pages())
            except InvalidPage as e:
                raise Http404(_('Invalid page (%(page_number)s): %(message)s') % {
                    'page_number': page_number,
                    'message': str(e)
                })
    
        def get_paginate_by(self, queryset):
            """
            Get the number of items to paginate by, or ``None`` for no pagination.
            """
            return self.paginate_by
    
        def get_paginator(self, queryset, per_page, orphans=0,
                          allow_empty_first_page=True, **kwargs):
            """Return an instance of the paginator for this view."""
            return self.paginator_class(
                queryset, per_page, orphans=orphans,
                allow_empty_first_page=allow_empty_first_page, **kwargs)
    
        def get_paginate_orphans(self):
            """
            Return the maximum number of orphans extend the last page by when
            paginating.
            """
            return self.paginate_orphans
    
        def get_allow_empty(self):
            """
            Return ``True`` if the view should display empty lists and ``False``
            if a 404 should be raised instead.
            """
            return self.allow_empty
    
        def get_context_object_name(self, object_list):
            """Get the name of the item to be used in the context."""
            if self.context_object_name:
                return self.context_object_name
            elif hasattr(object_list, 'model'):
                return '%s_list' % object_list.model._meta.model_name
            else:
                return None
    
        def get_context_data(self, *, object_list=None, **kwargs):
            """Get the context for this view."""
            queryset = object_list if object_list is not None else self.object_list
            page_size = self.get_paginate_by(queryset)
            context_object_name = self.get_context_object_name(queryset)
            if page_size:
                paginator, page, queryset, is_paginated = self.paginate_queryset(queryset, page_size)
                context = {
                    'paginator': paginator,
                    'page_obj': page,
                    'is_paginated': is_paginated,
                    'object_list': queryset
                }
            else:
                context = {
                    'paginator': None,
                    'page_obj': None,
                    'is_paginated': False,
                    'object_list': queryset
                }
            if context_object_name is not None:
                context[context_object_name] = queryset
            context.update(kwargs)
            return super().get_context_data(**context)

    View
    주요 매개 변수
  • http_method_names http 접근 방식.GET, POST 등 포함
  • 기능 함수
  • init는 setattr를 사용하여 모든 초기화 파라미터를 클래스 속성으로 설정합니다
  • as_view는python 클립을 사용하여 Request 대상과 클래스 속성에 전송된 파라미터를 추가하고 클립에서 디스패치 함수를 호출합니다.업데이트를 수동으로 호출했습니다함수 서명이 변하지 않도록 wrapper 함수입니다.
  • dispatch는 처리 요청의 함수를 되돌려줍니다. 이 함수는 계승 후 사용자 정의로 http 와 일치합니다.method_names에서 성명한 이름입니다.요청 형식에 대응하는 함수가 존재하지 않으면 http 터치method_not_allowed 함수, 상태를 되돌려줍니까 405
  • http_method_not_allowed 요청 함수를 거부합니다.오류 로그 인쇄, 상태 반환 405
  • options는response에 헤더 정보를 추가합니다.호출allowed_methods 함수에'ALLOW'태그를 추가합니다.
  • _allowed_methods는 httpmethod_names 목록의 요청 방식을 대문자로 변경합니다
  • 코드
    class View:
        """
        Intentionally simple parent class for all views. Only implements
        dispatch-by-method and simple sanity checking.
        """
    
        http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
    
        def __init__(self, **kwargs):
            """
            Constructor. Called in the URLconf; can contain helpful extra
            keyword arguments, and other things.
            """
            # Go through keyword arguments, and either save their values to our
            # instance, or raise an error.
            for key, value in kwargs.items():
                setattr(self, key, value)
    
        @classonlymethod
        def as_view(cls, **initkwargs):
            """Main entry point for a request-response process."""
            for key in initkwargs:
                if key in cls.http_method_names:
                    raise TypeError("You tried to pass in the %s method name as a "
                                    "keyword argument to %s(). Don't do that."
                                    % (key, cls.__name__))
                if not hasattr(cls, key):
                    raise TypeError("%s() received an invalid keyword %r. as_view "
                                    "only accepts arguments that are already "
                                    "attributes of the class." % (cls.__name__, key))
    
            def view(request, *args, **kwargs):
                self = cls(**initkwargs)
                if hasattr(self, 'get') and not hasattr(self, 'head'):
                    self.head = self.get
                self.request = request
                self.args = args
                self.kwargs = kwargs
                return self.dispatch(request, *args, **kwargs)
            view.view_class = cls
            view.view_initkwargs = initkwargs
    
            # take name and docstring from class
            update_wrapper(view, cls, updated=())
    
            # and possible attributes set by decorators
            # like csrf_exempt from dispatch
            update_wrapper(view, cls.dispatch, assigned=())
            return view
    
        def dispatch(self, request, *args, **kwargs):
            # Try to dispatch to the right method; if a method doesn't exist,
            # defer to the error handler. Also defer to the error handler if the
            # request method isn't on the approved list.
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
            return handler(request, *args, **kwargs)
    
        def http_method_not_allowed(self, request, *args, **kwargs):
            logger.warning(
                'Method Not Allowed (%s): %s', request.method, request.path,
                extra={'status_code': 405, 'request': request}
            )
            return HttpResponseNotAllowed(self._allowed_methods())
    
        def options(self, request, *args, **kwargs):
            """Handle responding to requests for the OPTIONS HTTP verb."""
            response = HttpResponse()
            response['Allow'] = ', '.join(self._allowed_methods())
            response['Content-Length'] = '0'
            return response
    
        def _allowed_methods(self):
            return [m.upper() for m in self.http_method_names if hasattr(self, m)]

    BaseListView
    물려받다
    MultipleObjectMixin 및 View에서 상속
    기능 함수
  • get 이 보기는 GET 요청에만 응답하고 조회 데이터를 되돌려줍니다.판단할 때 전시를 허용합니다. 만약 상태 코드 404를 되돌려주지 않는다면.

  • 코드
    class BaseListView(MultipleObjectMixin, View):
        """A base view for displaying a list of objects."""
        def get(self, request, *args, **kwargs):
            self.object_list = self.get_queryset()
            allow_empty = self.get_allow_empty()
    
            if not allow_empty:
                # When pagination is enabled and object_list is a queryset,
                # it's better to do a cheap query than to load the unpaginated
                # queryset in memory.
                if self.get_paginate_by(self.object_list) is not None and hasattr(self.object_list, 'exists'):
                    is_empty = not self.object_list.exists()
                else:
                    is_empty = len(self.object_list) == 0
                if is_empty:
                    raise Http404(_("Empty list and '%(class_name)s.allow_empty' is False.") % {
                        'class_name': self.__class__.__name__,
                    })
            context = self.get_context_data()
            return self.render_to_response(context)

    MultipleObjectTemplateResponseMixin
    물려받다
    Template ResponseMixin에서 상속
    주요 매개 변수
  • template_name_suffix 정의 템플릿 이름의 접미사
  • 기능 함수
  • get_template_names는 목록 형식으로 템플릿 이름을 되돌려줍니다.이 함수는 먼저 부모 방법을 호출하여 사용자 성명template 를 호환시키려고 시도합니다name의 경우.다음에 이 함수에 정의된 템플릿 이름, 즉'app 이름'+'모듈 이름'+'템플릿 이름 접미사'를 추가합니다.html

  • 코드
    class MultipleObjectTemplateResponseMixin(TemplateResponseMixin):
        """Mixin for responding with a template and list of objects."""
        template_name_suffix = '_list'
    
        def get_template_names(self):
            """
            Return a list of template names to be used for the request. Must return
            a list. May not be called if render_to_response is overridden.
            """
            try:
                names = super().get_template_names()
            except ImproperlyConfigured:
                # If template_name isn't specified, it's not a problem --
                # we just start with an empty list.
                names = []
    
            # If the list is a queryset, we'll invent a template name based on the
            # app and model name. This name gets put at the end of the template
            # name list so that user-supplied names override the automatically-
            # generated ones.
            if hasattr(self.object_list, 'model'):
                opts = self.object_list.model._meta
                names.append("%s/%s%s.html" % (opts.app_label, opts.model_name, self.template_name_suffix))
    
            return names
    

    TemplateResponseMixin
    주요 매개 변수
  • template_name 정의 템플릿 이름
  • template_engine 정의 템플릿 엔진
  • response_class 정의 반환 함수, 기본값은 TemplateResponse
  • content_type 정의 반환 형식
  • 기능 함수
  • render_to_response 호출responseclass가 렌더링된 템플릿을 되돌려줍니다.
  • get_template_names가 템플릿 이름을 되돌려줍니다.사용자가 지정하지 않으면 예외 발생
  • 코드
    class TemplateResponseMixin:
        """A mixin that can be used to render a template."""
        template_name = None
        template_engine = None
        response_class = TemplateResponse
        content_type = None
    
        def render_to_response(self, context, **response_kwargs):
            """
            Return a response, using the `response_class` for this view, with a
            template rendered with the given context.
    
            Pass response_kwargs to the constructor of the response class.
            """
            response_kwargs.setdefault('content_type', self.content_type)
            return self.response_class(
                request=self.request,
                template=self.get_template_names(),
                context=context,
                using=self.template_engine,
                **response_kwargs
            )
    
        def get_template_names(self):
            """
            Return a list of template names to be used for the request. Must return
            a list. May not be called if render_to_response() is overridden.
            """
            if self.template_name is None:
                raise ImproperlyConfigured(
                    "TemplateResponseMixin requires either a definition of "
                    "'template_name' or an implementation of 'get_template_names()'")
            else:
                return [self.template_name]

    좋은 웹페이지 즐겨찾기