2017-04-26 2 views
0

Mit Django suche ich nach einer Möglichkeit, ein url patern (mit slug) zu verwenden, um ein Modell abzufragen, und wenn nichts gefunden wird, ein zweites Modell abzufragen. Ich verwende klassenbasierte Ansichten.Django: eine URL Suche in zwei Modellen (cbv)

Ich folge diesem answer, und die nächste Ansicht wird aufgerufen. Aber dann bekomme ich den folgenden Fehler:

"Generische Detailansicht muss entweder mit einem Objekt PK oder einem Slug aufgerufen werden."

Ich kann nicht herausfinden, wie man den Slug an die nächste Ansicht übergeben.

Meine url:

url(r'^(?P<slug>[-\w]+)/$', SingleView.as_view(), name='singleview'), 

Mein CBV ist:

class SingleView(DetailView): 

    def dispatch(self, request, *args, **kwargs): 
    post_or_page_slug = kwargs.pop('slug') 

    if Page.objects.filter(slug=post_or_page_slug).count() != 0: 
     return PageDetailView.as_view()(request, *args, **kwargs) 
    elif Post.objects.filter(slug=post_or_page_slug).count() != 0: 
     return PostDetailView.as_view()(request, *args, **kwargs) 
    else: 
     raise Http404 


class PageDetailView(DetailView): 

    model = Page 
    template_name = 'page-detail.html' 


class PostDetailView(DetailView): 

    model = Post 
    template_name = 'post-detail.html' 

Antwort

0

Das Problem ist, dass Sie die Schnecke knallen, die sie von kwargs entfernt. Dies bedeutet, dass der Slug nicht in die Ansicht gelangt.

können Sie ändern, um es:

post_or_page_slug = kwargs.pop['slug'] 

Ich würde entmutigen in der Regel MyView.as_view(request, *args, **kwargs) in eine andere Ansicht aufrufen. Klassenbasierte Ansichten sollen durch Unterklassen erweitert werden, nicht indem sie in anderen Ansichten aufgerufen werden.

Für die beiden Ansichten in Ihrem Beispiel könnten Sie diese zu einer einzelnen Ansicht kombinieren, indem Sie get_object und get_template_names überschreiben.

from django.http import Http404 

class PageOrPostDetailView(DetailView): 

    def get_object(self): 
     for Model in [Page, Post]: 
      try: 
       object = Model.objects.get(slug=self.kwargs['slug']) 
       return object 
      except Model.DoesNotExist: 
       pass 
     raise Http404 

    def get_template_names(self): 
     if isinstance(self.object, Page): 
      return ['page-detail.html'] 
     else: 
      return ['post-detail.html'] 
+0

Ich ging mit Ihrer vorgeschlagenen Lösung von überschreiben 'get_object' und' get_template_names', einfach und sauber! –