Отредактировано ... или лучше ... заменено! :)
Это правда, что авторы без сопоставления документов не будут включены в набор запросов, поэтому вам придется добавить их обратно после (я не смог найти лучшего способа, но, возможно, кто-то знает, как не удалять их, не используя raw sql).
Вы получаете полное количество документов авторов, потому что вы не используете набор запросов для получения количества документов:
qryset = Author.objects.all()
qryset = qryset.filter(documents__categories__name__in = category_list).distinct()
qryset = qryset.filter(documents__date_published__year=year)
print(qryset)
дает [<Author: Author object>]
(если только один автор соответствует всем категориям), а qryset[0].documents.count()
вернет только количество найденных документов (не все документы от автора - 2 в случае I проверено, и у автора было 4, но только 2 соответствовали всем условиям).
Если вы используете dict (.values ()) вместо наборов запросов в описанных выше шагах, вы не сможете сделать это (я думаю), потому что dict не будет иметь поля документов, так:
qryset_dict = Author.objects.values()
qryset_dict = qryset_dict.filter(documents__categories__name__in = category_list).distinct().values()
qryset_dict = qryset_dict.filter(documents__date_published__year=year).values()
при выдаче qryset_dict[0].documents.count()
появляется сообщение об ошибке:
AttributeError: 'dict' object has no attribute 'documents'
Теперь, чтобы добавить отфильтрованных авторов обратно, вы можете сделать:
res = []
for a in Author.objects.all():
if a in qryset:
res.append([a,a.documents.count()])
else:
res.append([a,0])
и res будет список с <authors>
в 1-м столбце и количеством документов, совпадающих во 2-м столбце.
Я знаю, что это далеко от совершенства ... но если вас интересует только count()
соответствующих документов на автора, я думаю, вы могли бы найти лучший способ, используя агрегацию и аннотацию django или возможно сделать это с помощью raw sql, используя left join
от авторов к документам.
РЕДАКТИРОВАТЬ после уточнения в вопросе:
def possible_view(request, categories=None, year=None):
# you will pass these as parmeters of course
category_list = ['c2', 'c3']
year = 2010
qryset = Document.objects.filter(categories__name__in = category_list).distinct()
qryset = qryset.filter(date_published__year=year)
authors = Author.objects.all()
return render_to_response('blar.html', { 'result': qryset, 'authors': authors, 'categories': category_list, 'year': year }, RequestContext(request))
Шаблон blar.html
:
{% for a in authors %}
<b>{{a.name}}</b><br />
{% for d in result %}
{% if d.author.name == a.name %}
{{ d.title }} is almost certainly in one of these categories: {{ categories }} and was absolutely published in {{ year }}. If not, .something_magical_happens_to_documents didn't work.<br />
{% endif %}
{% endfor %}<br />
{% endfor %}
Это даст вам что-то не очень красивое, но со всеми авторами и ниже каждого из них, список их документов, попадающих в одно из category_list
(условие ИЛИ для AND, вам нужно отфильтровать запрос для каждой категории вместо использования __in
).
Если у автора нет документа в category_list
, он будет указан без документов под ним.
Что-то вроде:
aut1
tit2 is almost certainly in one of these categories: ['c2', 'c3'] and was absolutely published in 2010. If not, .something_magical_happens_to_documents didn't work.
tit1 is almost certainly in one of these categories: ['c2', 'c3'] and was absolutely published in 2010. If not, .something_magical_happens_to_documents didn't work.
aut2
tit3 is almost certainly in one of these categories: ['c2', 'c3'] and was absolutely published in 2010. If not, .something_magical_happens_to_documents didn't work.
aut3