#django #django-views
#django #django-views
Вопрос:
У меня есть приложение Django, которое использует JSON API в качестве источника данных.
Вот упрощенный пример использования в одном из моих views.py
:
class GroupsList(LoginRequiredMixin):
def get(self, request, **kwargs):
# Get file list and totals
try:
group_list = group_adapter.list() # makes an API call and ALSO populates a meta info class
except APIAccessForbidden:
return HttpResponseRedirect(reverse('logout'))
return render(request, 'groups/index.html', {
# can I make a mixin to add data here gained from the API call?
'group_list': group_list,
})
Эта строка:
group_adapter.list()
Вызов помещает некоторую метаинформацию в другой класс, который не связан с самим group_list . Я хотел бы передать эти данные в шаблон. Обычно я бы использовал a context_processor
, но при вызове контекстного процессора вызов API еще не был выполнен. Я мог бы вручную проверить информацию и добавить ее в render()
метод, но тогда мне нужно было бы сделать это в десятках разных представлений.
Потенциальное решение № 1: создайте для него микширование
Могу ли я использовать здесь микширование, которое добавляет эту информацию в контекст ПОСЛЕ запуска кода представления, но ДО того, как рендеринг передаст информацию в шаблон?
Другими словами, есть ли способ сделать это:
class GroupsList(LoginRequiredMixin, AddMetaInfoToContextMixin):
а затем создайте микширование примерно так?
class AddMetaInfoToContextMixin(ContextMixin):
def get_context_data(self, **kwargs):
# self.request
context = super().get_context_data(**kwargs)
context['global_meta_information'] = get_global_meta_information()
return context
Потенциальное решение № 2: создайте переопределенный templateview
Комментатор Melvyn указал, что я потенциально могу подкласс TemplateView и переопределить get_context_data()
, так будет ли что-то вроде этого работать?
class TemplateViewWithMeta(TemplateView):
def get_context_data(self, *args, **kwargs):
context = super(Home. self).get_context_data(*args, **kwargs)
context['global_meta_information'] = get_global_meta_information()
return context
class GroupsList(LoginRequiredMixin, TemplateViewWithMeta):
[...]
Комментарии:
1. Я не понимаю этот дизайн. Вы заполняете синглтон метаинформацией при вызове API? Почему бы не вернуть это? И вы говорите, что это должно быть сделано после запуска представления, но до рендеринга шаблона, что противоречит. В любом случае, любой подкласс
TemplateView
hasget_context_data
, который вызывается раньшеrender_to_response
.2. Спасибо за ответ. Вы правы, что я «заполняю синглтон метаинформацией» при вызове API. Что касается «почему бы не вернуть это», это потому, что это информация о лицензировании для приложения, которую нужно было закрепить после факта. Я бы хотел, чтобы мне не нужно было загрязнять каждое отдельное представление кодом обработки для него. Похоже, я могу подкласс TemplateView и обрабатывать эту логику в переопределенном get_context_data?
Ответ №1:
Типичный рабочий процесс для общего шаблона Django TemplateView:
- get()
- get_context_data()
- render_to_response()
- get_context_data()
Итак, в вашем случае, следуя духу общих представлений, вы могли бы сделать это следующим образом:
from django.views import generic
class BaseRemoteApiView(generic.TemplateView):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.group_list = None
def get(self, request, *args, **kwargs):
try:
self.group_list = group_adapter.list() # makes an API call and ALSO populates a meta info class
except APIAccessForbidden:
return HttpResponseRedirect(reverse('logout'))
return super().get(request, *args, **kwargs)
class RemoteApiContextMixin(generic.base.ContextMixin):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["group_list"] = self.group_list
context["meta_information"] = get_global_meta_information()
return context
class ConcreteRemoteApiView(RemoteApiContextMixin, BaseRemoteApiView):
pass
Конечно, вам не нужно создавать 3 класса и вы можете просто объединить 3 в один — зависит от того, насколько смешиваемым вы хотите быть.
Комментарии:
1. Прежде всего, спасибо, что нашли время, чтобы напечатать это.
2. Итак, все, что мне действительно нужно для микширования, это ДОБАВИТЬ глобальную мета-информацию, мне не нужно добавлять материал group_list, который я могу делать во всех отдельных представлениях. Итак, я создал
StoreLicenseMixin(ContentMixin)
класс и добавил глобальную мету к информации и вернул контекст, но я не вижу этих данных в своем шаблоне.3. Я обновил свое доказательство концепции «микширования» выше. Это в основном то, что я делаю, и у меня все еще нет этих данных, доступных в шаблоне.
4. Когда создаются эти данные? Если он создан в промежуточном программном обеспечении при выходе ответа, то представление никогда не сможет получить информацию. если он создан за пределами какого-либо другого процесса после завершения просмотра — та же проблема. Рендеринг является частью кода представления, вы не можете его разделить — по крайней мере, без изменения / обхода архитектуры ядра Django.
5. «Итак, все, что мне действительно нужно для микширования, это ДОБАВИТЬ глобальную мета-информацию, мне не нужно добавлять материал group_list, который я могу делать во всех отдельных представлениях». — Ну, вы говорите, что мета-информация создается при вызове API. Во-вторых, вы хотите выйти из системы пользователя по ошибке с перенаправлением. Итак, вы уже подключены к списку групп, и неразумно его разделять. Все еще непонятно, что оно не попадает в шаблон, если только у вас нет опечатки / ошибки в вашем шаблоне.