#python #django #django-views #django-templates #django-orm
Вопрос:
Моя цель: получить количество элементов в месяц, отображаемых в моем шаблоне, т. е.: Май 2021 — 5, июнь 2021 — 10, сентябрь 2021 — 3, октябрь 2021 — 2 и т. Д
что я сделал. Я сначала создал тестовый проект и мое представление индекса, унаследованное от CreateView (это необходимо для формы). Все работало нормально. Однако в моем основном проекте мое представление индекса унаследовано от представления шаблонов django, и с тем же кодом оно отображается следующим образом: Сентябрь 2021 — 1, сентябрь 2021 — 1, Октябрь 2021 — 1, Октябрь 2021 — 1, Октябрь 2021 — 1, Октябрь 2021-1, Октябрь 2021-1… вы поняли, в чем дело. Поэтому по какой-то причине он рассматривает каждый пункт как отдельную дату, не пытаясь их агрегировать.
Таким образом, причиной различий должно быть наследование от разных представлений в django, однако в моем основном проекте я не могу сделать так, чтобы мое представление индекса наследовалось от CreateView. Кроме того, я все еще новичок в Django и был бы очень признателен за любую помощь, которую я могу получить. Мне потребовалось много усилий, чтобы понять это до этого момента.
Вот мой рабочий код (в тестовом проекте):
models.py
class Movie(models.Model):
title = models.CharField('Movie name', max_length=100)
gross = models.IntegerField('Gross', help_text='Worldwide, in dollars.')
release_date = models.DateField('Date of release', blank=True, null=True)
def __str__(self):
return self.title
views.py (обратите внимание на контекстную строку[«за месяц»])
class IndexView(CreateView):
form_class = CreateMovieForm
template_name = 'home/index.html'
success_url = '/'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# per_month = queryset of dictionaries: month number of movies in each month
context['per_month'] = Movie.objects.annotate(
month=TruncMonth('release_date')).values('month').annotate(c=Count('id')).values('month', 'c')
context['movies'] = Movie.objects.all()
return context
forms.py (не уверен, что это уместно здесь, но на всякий случай)
class CreateMovieForm(forms.ModelForm):
class Meta:
model = Movie
fields = '__all__'
widgets = {'release_date': DateInput(attrs={'value': timezone.now().date})}
index.html
{% for month in per_month %}
<ul>
<li>
{{ month.month|date:"M Y" }} - {{ month.c }}
</li>
</ul>
{% endfor %}
Выход:
Август 2021 — 2 сентября 2021 — 1 октября 2021 — 3
Вот мой нерабочий код (основной проект):
models.py
class Item(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(User, on_delete=models.CASCADE)
assigned_to = models.ManyToManyField(User)
date_posted = models.DateTimeField(auto_now_add=True)
deadline_date = models.DateField(null=True)
Примечание: Я попытался поэкспериментировать с обоими: date_posted и deadline_date (в случае, если проблема заключалась в поле времени даты, а не в поле даты), но это не помогло.
views.py (тот же контекст [строка «за месяц»])
class IndexView(LoginRequiredMixin, TemplateView):
template_name = 'bugtracker/main.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# per_month = queryset of dictionaries: month number of movies in each month
context['per_month'] = Item.objects.annotate(
month=TruncMonth('date_posted')).values('month').annotate(c=Count('id')).values('month', 'c')
index.html (то же, что и выше)
Выход:
Авг 2021 -1 Авг 2021 -1 Окт 2021 — 1 Окт 2021 — 1 Окт 2021 — 1 Окт 2021 — 1
Ответ №1:
Вы должны добавить a .order_by(…)
в группировку по силе, поэтому:
context['per_month'] = Item.objects.values(
month=TruncMonth('date_posted')
).annotate(c=Count('id')).order_by('month')
Комментарии:
1. Ну, я буду… это действительно так. Вы, сэр, спасаете мне жизнь. Теперь в этом так много смысла. Большое вам спасибо!