2015-08-25 1 views
3

Я устанавливаю {{ title }} для каждой страницы моего проекта. Иногда этот title является статической строкой, такой как Enter your Name, и иногда она основана на соответствующем объекте на этой странице, например Employee.first_name.Django CBV - Как избежать повторения get_context_data для каждого представления, чтобы получить собственный заголовок?

Чтобы создать context['title'], я использую get_context_data внутри каждого класса. Но это, по-видимому, приводит к тому, что я каждый раз повторяю кусок кода, и я хочу как-то уменьшить это.

Например, чтобы написать пользовательский заголовок для каждой страницы, я должен был бы написать так:

def get_context_data(self, **kwargs): 
    context = super(SomeView, self).get_context_data(**kwargs) 
    context['title'] = 'Title for This page' 
    return context 

Я чувствую, что было бы идеально иметь подмешать, что я как-то просто передать в переменной для title и мой словарь context автоматически добавит context['title'] на основе переданной переменной.

Возможно ли это? Есть ли способ создать mixin, так что все, что мне нужно сделать, это передать переменную, и она даст мне контекст только для названия вместо того, чтобы записывать этот кусок кода для каждого отдельного представления?

ответ

1

я обычно решить эту проблему с Mixin:

class TitleMixin(object): 
    """Pass a defined title to context""" 

    title = None 

    def get_title(self): 
     return self.title 

    def get_context_data(self, **kwargs): 
     context = super().get_context_data(**kwargs) 
     context['title'] = self.get_title() 

     return context 

В вас взглядов, то вы можете сделать:

class BlogIndex(TitleMixin, ListView): 
    title = 'Blog entries' 

class EntryDetail(TitleMixin, DetailView) 
    def get_title(self): # for dynamic title, such as coming from a model field 
     return self.object.title 
+2

Это не будет работать. Вероятно, вы имели в виду 'context ['title'] = self.get_title()'? –

+0

Да, вы правы, извините за опечатку>. < –

+1

это предполагает, что каждая модель имеет метод get_title' в определении своей модели? Что, если мне нужен титул «Все записи в блоге от автора:' author.first_name' »? Этот тип названия представляет собой сочетание статических данных и данных объекта. – Garfonzo

4

Да, это возможно и легко:

class YourTitleMixin(object): 
    title = None # or your default title if you won't provide any 

    def get_title(self): 
     return self.title 

    def get_context_data(self, **kwargs): 
     context= super(YourTitleMixin, self).get_context_data(**kwargs) 
     context['title'] = self.get_title() 
     return context 

И вы используете его:

def YourPageView(YourTitleMixin, DetailView): 
    title = "Your Page Title" # you can either use this ... 

    def get_title(self): 
     return self.get_object().name # ... or that, if your title should be generated from some data 

Но разве это необходимо? Вы используете свой заголовок только один раз в шаблоне? Вы делитесь одним шаблоном между представлениями? Может быть, вы можете сделать это исключительно в ваших шаблонах? Например:

{# base.html #} 
<html> 
    <head> 
    <title>{% block page_title %}My page{% endblock %}</title> 
    </head> 
</html> 

{# detail.html #} 
{% extends "base.html" %} 
{% block title %}{{ article.name }} - {{ block.super }}{% endblock %} 
{# will result in "article name - My Page". You don't need to use super if you don't want to #} 
+0

это то, о чем я думал, но мне нравится настраивать заголовок в представлении, потому что часто использую шаблон с несколькими видами. – Garfonzo

+0

Будьте осторожны с 'get_object', он добавит один запрос к вашему представлению, поскольку он уже вызывается в' super(). Get_context_data() ';) –

+0

Вы также можете использовать супер в решении на основе mixin, чтобы получить заголовок из родительского класса и склейте 2 названия вместе, как, например, в примере на основе шаблонов. Также вы можете смешивать оба решения, чтобы получить еще большую гибкость. Это полностью зависит от вас. – GwynBleidD