2012-02-03 2 views
0

Я создаю приложение, где люди смогут делать сообщения для городов. Я хотел бы создать представление для страны страны, в которой будет показан список городов, в которых есть плакаты, и количество сколько плакатов было сделано для каждого города.Django Query and Grouping

У меня есть загородный стол и стол города с иностранным ключом для страны. У меня также есть таблица плакатов с внешним ключом к таблице City.

Это успешно дает мне список плакатов, но как я могу группировать их в Города и передавать их? В шаблоне я хотел бы показать название города, плакат.изображения, которые находятся в этом городе, и общее количество плакатов в этом городе, для каждого города в стране, для которого были созданы плакаты.

def country_page(request, country_name): 
    country = get_object_or_404(Country, name__iexact=country_name)  
    posters = Poster.objects.filter(city__country=country)   
    variables = RequestContext(request, { 
     'location' : country, 
     'posters' : posters, 
    }) 
    return render_to_response('country_page.html', variables) 

Любая помощь будет принята с благодарностью.

ответ

0

Что вы ищете, это «группа» в sql-стране.

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

posters = Poster.objects.filter(city__country=country) 
poster_cities = {} 
for poster in posters: 
    if city not in poster_cities: 
     poster_cities[city] = [] 
    poster_cities[city].append(poster) 

Теперь вы можете получить плакаты по городу, как это использовать из шаблона:

for city in sorted(poster_cities.keys()): 
    city_posters = poster_cities[city] 
    city_poster_count = len(poster_cities[city]) 

фон:

How to query as GROUP BY in django?

0

В сыром sql вы бы сделали это с помощью «group by» и т. Д., Но для django вы должны изучить функции агрегации для моделей.

https://docs.djangoproject.com/en/dev/topics/db/aggregation/

я столкнулся с подобной проблемой несколько дней назад, и это, как я решил. Сначала вы фильтруете объекты из определенного критерия, затем указываете нужные поля и, наконец, делаете подсчет, чтобы узнать общее количество строк.

Ваше решение может выглядеть примерно так:

posters = Poster.objects.filter(city__country=country).values('city_name','poster_image',..).annotate(total=Count('city')) 
+0

Не следует ли считать граф из городов? – Raekkeri

+0

О да, прости. Я взял этот код из своего собственного проекта, и я неправильно изменил параметры. – Vannen

0

Это также может быть достигнуто в коде, а не все SQL, но, принимая во внимание характер вашего приложения - что там может быть много плакатов в много городов - это решение может легко занять слишком много системных ресурсов. Но вот краткий отрывок:

key = lambda poster: poster.city 
posters = Poster.objects.filter(city__country=country) 
posters = sorted(posters, key=key) 
di = {} 
for k, g in itertools.groupby(posters, key): 
    di[k] = list(g) 

Теперь di содержит каждый город, как ключи, со списком всех плакатов в качестве значений.

0

Это возвращает Города, каждый с количеством плакатов для этого города:

cities = City.objects.filter(country=my_country).annotate(num_posters=Count('posters')) 

Затем вы можете цикл в шаблоне:

<h1>{{ country }}</h1> 
{% for city in cities %} 
<p> 
    {{ city.name }} - {{ city.num_posters }} posters 
    {% for poster in city.posters.all %} 
     <img src="{{ poster.image.url }}"> 
    {% endfor %} 
</p> 
{% endfor %} 

Теперь, приведенный выше код извлекает плакаты отдельно для каждого Город, который может быть неэффективным.Чтобы исправить это, вы можете использовать либо prefetch_related (если вы можете себе позволить, используя ствол Джанго), или сделать это вручную самостоятельно, как here

0

С кодом у вас уже есть, вы можете использовать regroup в шаблоне, что-то вроде:

{% regroup posters by city as city_list %} 

<ul> 
{% for city in city_list %} 
    <li>{{ city.grouper }} ({{city.list|length}}) 
    <ul> 
     {% for poster in city.list %} 
     <li>{{ poster.image}}</li> 
     {% endfor %} 
    </ul> 
    </li> 
{% endfor %} 
</ul> 

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