Django экспорт модели в csv для ManyToManyField
У меня есть несколько таблиц, для которых я успешно создал экспорт в CSV, основанный на Моделях. Однако для одной из них, где я подсчитываю "лайки" для новостей (постов), у меня ничего не получается
Вот моя модель:
class News(models.Model):
news_title = models.CharField(max_length=300)
news_text = models.TextField(max_length=2000)
news_author = models.CharField(max_length=150)
news_date = models.DateField(default=now)
likes = models.ManyToManyField(User, related_name='user_like', blank=True)
@property
def total_likes(self):
return self.likes.count()
Проблема в том, что я могу вывести в CSV все элементы из модели, но если я вывожу "лайки", я получаю дублированные (или более) строки в CSV. Причина в том, что если новость понравилась 3 пользователям, я получаю 3x строки в CSV для каждого пользователя и в колонке "Like Count" я получаю их ID.
Что я хотел бы получить вместо этого: 1x строка для каждой новости с общим количеством лайков для каждой новости.
и view.py
@login_required
def export_news(request):
newss = News.objects.all()
response = HttpResponse(content_type='txt/csv')
writer = csv.writer(response)
writer.writerow(["ID","Title","Author","Date","Text","Likes Count"])
for news in newss.values_list('id','news_title','news_author','news_date','news_text','likes'):
writer.writerow(news)
response['Content-Disposition'] = 'attachment; filename="News_list.csv"'
return response
Благодарю за любую помощь. Thx
Вам нужно аннотировать подсчет лайков на кверисете newss
и затем вызвать это агрегированное значение в values_list
. Что-то вроде:
from django.db.models import Count
newss = News.objects.annotate(num_likes=Count('likes')).all()
...
for news in newss.values_list('id','news_title','news_author','news_date','news_text','num_likes'):
writer.writerow(news)
Ваша проблема в том, что запрос values_list
действительно вернет элемент списка для каждой совпадающей записи, как если бы вы сделали этот запрос на SQL. Поскольку вы возвращаете likes
, который не является полем 1:1, вы можете ожидать, что в этом запросе будет более одной строки для каждой новости. Если вам нужен только свернутый агрегат, вам нужно указать это в запросе с помощью аннотации, а затем вернуть только аннотированное значение, а не полную запись likes
из запроса.