2017-06-24 1 views
0

Ich möchte Informationen über ein Objekt in vielen Ansichten einfügen, ohne es in get_context_data in jeder Ansicht zu wiederholen. Wie Sie verstehen, brauche ich eine Klasse mit get_context_data, die ich mit anderen Ansichten mischen kann. Hier in meinem Beispiel möchte ich in Zusammenhang mit UpdateAnotherObjectView ‚some_object‘ sehen:Wie kann man denselben Kontext in vielen verschiedenen Django-Ansichten einfügen?

class BaseObjectInfoView(View): 
    def get_context_data(self, **kwargs): 
     context_data = super(BaseObjectInfoView, self).get_context_data(**kwargs) 
     context_data['some_object'] = SomeObjects.objects.get(pk=1) 
     return context_data 

class UpdateAnotherObjectView(BaseObjectInfo, UpdateView): 
    template_name = 'create_object.html' 
    form_class = AnotherObjectForm 
    model = AnotherObjects 

    def get_context_data(self, **kwargs): 
     context_data = super(UpdateAnotherObjectView, self).get_context_data(**kwargs) 
     context_data['all_another_objects'] = AnotherObjects.objects.all() 
     return context_data 

es funktioniert, aber get_context_data ist nicht ein Teil der Eltern ‚Ansicht‘ Klasse. Kann ich brauchen mehr spezielle Klasse von in BaseObjectInfoView zu erben?

oder vielleicht besser, Kontext mit einer anderen Methode zu konstruieren?

Antwort

0

Mixins brauchen nicht zu sein, aber es hilft, IDE, wenn sie die Methoden haben zwingende sie.

Contexts werden von django.views.generic.base.ContextMixin (Details auf this very handy site) behandelt, also die klassenbasierte Ansichten Art und Weise der Dinge wäre dies:

from django.views import generic 

class WebsiteCommonMixin(generic.base.ContextMixin): 
    page_title = '' 
    active_menu = None 

    def get_context_data(self, **kwargs): 
     context = super(WebsiteCommonMixin, self).get_context_data(**kwargs) 
     context.update(dict(page_title=self.page_title, active_menu=self.active_menu)) 
     return context 

class NewsListView(WebsiteCommonMixin, ListView): 
    page_title = 'News list' 
    active_menu = 'News' 
    model = News 
    paginate_by = 12 

Ich tue dies für viele Projekte und die einfachen Ansichten, die Sie auf jeden Fall zu schaffen haben , sind vollständig deklarativ. Und ich meine einfach, dass sie aus mehreren Mixins bestehen können, die alle die harten Sachen entweder in get_queryset, get_context_data oder form_valid erledigen. Ausführlichere Beispiel, direkt aus einem Projekt:

class FeedbackMixin(object): 
    message = 'Well Done!' 

    def __init__(self): 
     self._message_kwargs = {} 
     super().__init__() 

    def add_message_kwarg(self, name, value) -> None: 
     self._message_kwargs[name] = value 

    def format_message(self, kwargs) -> str: 
     return self.message.format(**kwargs) 

    def generate_message(self) -> None: 
     msg = self.format_message(self._message_kwargs) 
     messages.success(getattr(self, 'request'), msg) 


class ModelFeedbackMixin(FeedbackMixin, generic.edit.ModelFormMixin): 
    success_view_name = None 
    success_url_kwargs = None 

    def get_success_url_kwargs(self): 
     return self.success_url_kwargs 

    def get_success_url(self) -> str: 
     success_url_kwargs = self.get_success_url_kwargs() 
     if not self.success_view_name: 
      url = super().get_success_url() 
     elif success_url_kwargs is not None: 
      url = reverse(self.success_view_name, kwargs=success_url_kwargs) 
     else: 
      if hasattr(self.object, 'slug'): 
       url_kwargs = {'slug': self.object.slug} 
      else: 
       url_kwargs = {'pk': self.object.pk} 
      url = reverse(self.success_view_name, kwargs=url_kwargs) 
     return url 

    def form_valid(self, form): 
     response = super().form_valid(form) 
     self.generate_message() 
     return response 
+0

Es ist sehr nett! Aber wie kann ich mit context mixin umgehen, wenn ich einige Objekte, die von view kwargs abhängen, im url pattern (ex. 'Object_pk') im Kontext platzieren muss? In meinem Beispiel habe ich Objekt mit pk = 1, aber PK-Mast wird von URL genommen. –

+0

Das PK ist in 'self.kwargs' in der Ansicht verfügbar. Dies geschieht mit 'View.as_view()'. Aber [SingleObjectMixin] (http://ccbv.co.uk/projects/Django/1.11/django.views.generic.detail/SingleObjectMixin/), das Teil von 'DetailView' ist, wird die ganze harte Arbeit für Sie tun, wenn es ist das Hauptobjekt der Ansicht. – Melvyn

0

Vielleicht könnte auf diese Weise einfacher sein Blick zu lesen ...

def add_context(func): 
# this is a wrapper function 
    def wrapper(*args, **kwargs): 
     context_data = func(*args, **kwargs) 
     context_data['some_object'] = SomeObjects.objects.get(pk=1) 
     return context_data 
return wrapper 


class UpdateAnotherObjectView(BaseObjectInfo, UpdateView): 
    template_name = 'create_object.html' 
    form_class = AnotherObjectForm 
    model = AnotherObjects 

    @add_context 
    def get_context_data(self, **kwargs): 
     kwargs['all_another_objects'] = AnotherObjects.objects.all() 
     return kwargs 
Verwandte Themen