Ich habe viele Ansichten, die jedes Mal die gleichen Funktionen aufrufen, und ich frage mich, bevor ich mit diesem Ansatz fortfahre, ob ich ihn trotzdem trockener machen kann.

Zum Beispiel habe ich viele Seiten auf einer Site, die auf der linken Seite eine Liste der gleichen Artikel und Fotos haben. Bei jeder meiner Ansichten mache ich Folgendes:

context_dict = {'articles': get_articles(blogger.id), 'photos': get_photos(blogger.id)}

return render_to_response('...', context_dict, context)

Es muss eine Möglichkeit geben, dass ich mich nicht jedes Mal wiederholen muss, da sie auf 90% der Seiten erforderlich sind.

2
Yannick 29 Dez. 2015 im 22:29

3 Antworten

Beste Antwort

Du meinst so etwas wie

def get_extra_context(blog_id):
    return {'articles': get_articles(blogger.id), 'photos': get_photos(blogger.id)}

Ein Aufruf von get_extra_context muss natürlich in jeder Ansicht erfolgen.

1
Ramez Ashraf 29 Dez. 2015 im 21:35

Das Problem der Wiederholung der Ansichtsfunktionalität ist Teil dessen, warum viele Leute klassenbasierte Ansichten mögen. Sie können eine Methode implementieren, die diese Variablen zur Basisklasse hinzufügt und dann andere Ansichten von dieser erben lässt, oder eine standardisierte "Render" -Methode bereitstellen. Zum Beispiel:

class BaseView(View):
    template = 'public/base_template.html'

    def get(self, *args, **options):
         return render_to_response(self.template, self.render_view())

    def render_view(self, *args, **options):
         context = {"photos": Photo.objects.all()}
         return context

class OtherView(BaseView):
    template = 'public/other_template.html'

    def render_view(self, *args, **options):
        context = super(OtherView, self).render_view(*args, **options)
        context['additional_context'] = True
        return context

...oder etwas ähnliches. Dann müssen Sie sich keine Gedanken mehr über das Aufrufen von Rendering mit bereits enthaltenen Variablen machen.

Ich kann mir ein paar Möglichkeiten vorstellen, dies mit funktionsbasierten Ansichten zu erreichen, aber ich denke, klassenbasiert eignet sich sehr gut für DRY-Prinzipien, also dachte ich, ich würde das Evangelium verbreiten :)

https://docs.djangoproject.com/en/1.9/topics/class-based-views/intro/

2
Robert Townley 29 Dez. 2015 im 21:48

Wie Robert Townley sagt, sind klassenbasierte Ansichten sehr hilfreich, um die DRY-Prinzipien einzuhalten. Ich benutze oft einige einfache Mixins, um eine Logik zwischen verschiedenen Ansichten zu teilen. Ihre klassenbasierten Ansichten können dann von diesem Mixin erben, wenn sie diese Funktionalität benötigen. Zum Beispiel:

class BloggerMixin(object):
    articles_context_name = 'articles' 
    photos_context_name = 'photos'

    def get_blogger(self):
        """ I'm just assumming your blogger is the current user for simplicity.    
        (And I'm assuming they're logged in already)"""
        return self.request.user

    def get_articles(self):
        return Article.objects.filter(blogger=self.get_blogger())

    def get_photos(self):
        return Photo.objects.filter(blogger=self.get_blogger())

    def get_context_data(self, **kwargs):
        context = super(BloggerMixin, self).get_context_data(**kwargs)
        context[self.articles_context_name] = self.get_articles()
        context[self.photos_context_name] = self.get_photos()
        return context

Auf diese Weise können Sie diese zusätzliche Funktionalität für klassenbasierte Ansichten erben, die sie benötigen:

class ExampleView(BloggerMixin, ListView):
    model = SomeOtherModel

Unsere sehr einfache ExampleView-Klasse enthält jetzt eine Liste mit Artikeln, Fotos und SomeOtherModel in ihrem Kontext.

1
Richard Price 30 Dez. 2015 im 11:35