2016-08-17 3 views
1

Учитывая следующие модели:Как получить доступ к настраиваемому менеджеру обратных моделей в шаблоне?

class Author(models.Model): 
    name = models.CharField(max_length=20) 

class CustomQuerySet1(models.QuerySet): 
    def some_method(self): 
     return 'custom queryset 1' 

class CustomQuerySet2(models.QuerySet): 
    def some_method(self): 
     return 'custom queryset 2' 

class Book(models.Model): 
    author = models.ForeignKey(Author, related_name='books') 
    title = models.CharField(max_length=50) 

    objects = models.Manager() 
    custom1 = CustomQuerySet1.as_manager() 
    custom2 = CustomQuerySet2.as_manager() 

В моем РЕПЛА я могу получить доступ к обычаю, связанным менеджеры, как так:

>>> author = Author.objects.create(name='John') 
>>> book = Book.objects.create(author=author, title='Hello') 
>>> author.books(manager='custom1').some_method() 
    'custom queryset 1' 
>>> author.books(manager='custom2').some_method() 
    'custom queryset 2' 

И в наших шаблонах мы обычно доступ связанных объектов с помощью менеджера по умолчанию, как так:

{% for book in author.books.all %} 
    {{ book.title }} 
{% endfor %} 

Мы явно не разрешено делать вызовы функций и передать параметры в шаблонах:

{% for book in author.books(manager='custom1').some_method %} 
{% endfor %} 

Итак, есть ли способ доступа к этим пользовательским менеджерам моделей в наших шаблонах, о которых я не знаю? Что-то подобное никогда не предназначалось? Любые внешние решения?

Edit: В случае существует некоторая путаница в комментариях, я не предлагаю следующее:

def some_view(request): 
    context = {} 
    template = 'my_template.html' 
    context['author'] = Author 
    return render(request, template, context) 

и затем вызвать author.objects.all, но вместо этого:

def some_view(request): 
    context = {} 
    template = 'my_template.html' 
    author = Author.objects.get(name='John') 
    context['author'] = author 
    return render(request, template, context) 

, а затем доступ к author.books.custom1.some_method , Обратите внимание на related_name на author, определенный на модели Book.

+1

Я не думаю, что это возможно. Однако вы можете создать запрос в представлении и передать его в шаблон. Это на самом деле предпочтительный способ, поскольку концептуально шаблон не должен вызывать запросы. – spectras

+1

Из того, что я видел, я тоже не думаю, что это возможно. Даны ли запросы на запросы, ленивы, не заставляют шаблоны всегда запускать запросы? Не помешало бы запросам в шаблонах упасть на что-то вроде 'select_related' и' prefetch_related'? –

+0

Точка зрения была создана для создания, а не шаблона. Это правда, что они ленивы, поэтому шаблонная оценка вызовет их, но это детализация реализации. Например, шаблон может зацикливаться на 'all_books', но это зависит от представления, чтобы определить, что такое' all_books'. – spectras

ответ

0

Существует нет, и я думаю, что это не будет (потому что это не должно). Шаблон - это место, где представлены данные, поэтому он должен быть подготовлен, а шаблонная разметка используется только для его удобства.

Однако это может быть хорошей идеей для фильтра шаблонов.

+1

Не могли бы вы подробнее рассказать о том, почему это не должно быть? В чем разница между вызовом 'author.books.all' и' author.books (manager = 'custom1'). Custom_method' в шаблоне, если они оба представляют данные? Кроме того, нам разрешено писать собственные методы в диспетчере моделей по умолчанию и обращаться к ним в шаблоне 'author.books.i_only_want_a_subset_of_this_authors_books' –

+0

Вы также не должны называть' author.books.all' в шаблоне. Тот факт, что он работает, не означает, что он прав. Посмотрите, как работают общие представления Django, они действительно хорошо разработаны. Ни при каких обстоятельствах они не дают модель или менеджер шаблону. – spectras

+0

Я никогда не слышал этого совета. Даже это [учебник по Django] (https://docs.djangoproject.com/en/1.10/intro/tutorial03/#use-the-template-system) предлагает это. –

Смежные вопросы