Джанго учебник.Общие взгляды.context_object_name = 'latest_question_list' - PullRequest
2 голосов
/ 10 мая 2019

Я немного запутался с общими взглядами Джанго.Как показано в здесь , мы конвертируем пользовательские представления в общие представления.И хотя я понимаю, что происходит в DetailView и ResultsView, я не совсем понимаю, как это:

def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    template = loader.get_template('polls/index.html')
    context = {
        'latest_question_list': latest_question_list,
    }
    return render(request, 'polls/index.html', context)

преобразуется в следующее:

class IndexView(generic.ListView):
    template_name = 'polls/index.html'
    context_object_name = 'latest_question_list'

    def get_queryset(self):
        """Return the last five published questions."""
        return Question.objects.order_by('-pub_date')[:5]
  1. В первом примереlatest_question_list = Question.objects.order_by('-pub_date')[:5]
  2. Но во втором примере, чем равна latest_question_list переменная здесь?Мы даже не определили это ..

Кто-нибудь может пролить свет на это?

Ответы [ 2 ]

2 голосов
/ 10 мая 2019

A ListView за завесами выполняет множество операций для создания контекста и передачи его в механизм визуализации.Мы можем взглянуть на реализацию через Классные представления на основе классов .

По сути, когда вы запускаете такое представление на основе классов, вы будете зависеть от HTTP.метод, вызвать метод get(..), post(..) и т. д.

Метод get(..) определяется классом BaseListView и определяется как:

def get(self, request, *args, **kwargs):
    <b>self.object_list = self.get_queryset()</b>
    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 = not self.object_list
        if is_empty:
            raise Http404(_("Empty list and '%(class_name)s.allow_empty' is False.") % {
                'class_name': self.__class__.__name__,
            })
    <b>context = self.get_context_data()</b>
    return self.render_to_response(context)

Часть импорта состоит в том, что мы сначала получаем результат от get_queryset() до self.objects_list, а затем создаем контекст с self.get_context_data().Затем мы вызываем self.render_to_response(..), который в основном будет использовать указанный шаблон, и визуализируем его с указанным context.

. У данных get_context есть два родителя с реализацией.Самая базовая (самая высокая в иерархии наследования) - это ContextMixin, но эта функция мало что делает:

def get_context_data(self, **kwargs):
    kwargs.setdefault('view', self)
    if self.extra_context is not None:
        kwargs.update(self.extra_context)
    return kwargs

Она просто берет словарь, построенный по ключевому словуarguments (пусто, если нет ключевых слов аргументов, как здесь), и он добавляет дополнительный ключ 'view', связанный с self.Он также может добавлять дополнительные пары ключ-значение, которые могут быть определены в self.extra_context, но мы можем игнорировать это здесь.

Наиболее интересная логика реализована в MultipleObjectMixin:

def get_context_data(self, *, object_list=None, **kwargs):
    """Get the context for this view."""
    <b>queryset = object_list if object_list is not None else self.object_list</b>
    page_size = self.get_paginate_by(queryset)
    <b>context_object_name = self.get_context_object_name(queryset)</b>
    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:
        <b>context[context_object_name] = queryset</b>
    context.update(kwargs)
    return super().get_context_data(**context)

Здесь происходит то, что мы сначала назначаем self.object_list, переменную, которую мы сначала установили с результатом self.get_queryset, локальной переменной с именем queryset.Затем мы будем разбивать на страницы queryset, но это не очень важно для вашего вопроса.

Затем мы получим имя, позвонив по номеру self.get_context_object_name(queryset).По умолчанию это реализовано следующим образом:

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:
        <b>return self.context_object_name</b>
    elif hasattr(object_list, 'model'):
        return '%s_list' % object_list.model._meta.model_name
    else:
        return None

Поэтому, если вы установили атрибут context_object_name, как вы это сделали, он просто вернет это имя.Таким образом, мы можем заключить, что в методе get_context_data(..), context_object_name будет иметь имя, которое вы назначили, здесь 'latest_question_list'.

Затем мы продолжаем обрабатывать код в get_context_data(..): мы создаем словарьи внизу мы проверяем, не является ли context_object_name не None.Если это так, мы связываем queryset с этим ключом (так что здесь с 'latest_question_list').В конце концов, когда создается правильный контекстный словарь, мы делаем вызов super() с созданным контекстом как **kwargs, и, как мы уже говорили, ContextMixin просто вернет этот словарь с очень небольшими изменениями.

Таким образом, в конце context будет иметь имя вашего списка (здесь 'latest_question_list'), связанное с queryset, и он отобразит шаблон с этими данными контекста.

1 голос
/ 10 мая 2019

В представлении на основе классов вы использовали context_object_name = 'latest_question_list' Поэтому он похож на latest_question_list, который вы использовали в представлении на основе функций.

В представлении на основе классов, если вы не добавите context_object_name, тогда это значение автоматически object_list. Что-то вроде context_object_name='object_list'.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...