DRF как получить группировку элементов по категориям
Я понимаю, что мой вопрос часто повторяется, но я застрял на этом. Я хочу сделать простой api с DRF. У меня есть две модели:
models.py
class Rubrics(models.Model):
id = models.AutoField(primary_key=True)
rubric = models.CharField(max_length=255, blank=True, null=True)
class Books(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=255, blank=True, null=True)
author = models.CharField(max_length=255, blank=True, null=True)
date = models.CharField(max_length=255, blank=True, null=True)
rubrics = models.ForeignKey('Rubrics', on_delete=models.DO_NOTHING, related_name='books', blank=True, null=True)
Я хотел бы просмотреть сериализованный результат следующим образом:
[
rubric1: [
{
title: "title1",
author:"author1"
},
book_obj2,
so on
],
rubric2: [
book_obj4,
book_obj5
]
]
my views.py:
class BooksByRubricView(APIView):
"""List of books by rubrics"""
def get(self, request):
last_date = Books.objects.latest("date").date
books_last = Books.objects.filter(date=last_date)
serializer = RubricsSerializer(books_last, many=True)
return Response(serializer.data)
Я пробую много примеров в этой теме,
sorry this garbage
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Books
#fields = ("title",)
exclude = ()
class RubricsSerializer(serializers.ModelSerializer):
rubrics = BookSerializer(read_only=True)
class Meta:
model = Rubrics
fields = ("rubrics",)
#exclude = ()
"""
class RubricSerializer(serializers.ModelSerializer):
#rubrics = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
#books = RecursiveSerializer(many=True)
#print(books)
rubrics = RubricSerializer(read_only=True)
#books = BooksListSerializer(many=True)
class Meta:
model = Books
fields = ("title", "rubrics",)
#fields = ['rubric', 'rubrics']
#fields = ['books', 'rubrics']
"""
но возможно я не понимаю принципов обратных связей и сериализации в DRF. Пожалуйста, подскажите мне WAIDW. Спасибо.
В модели rubrics
отсутствует поле Rubrics
, доступны следующие поля:
id
,rubric
из самой модели,books_set
, которые представляют все книги, имеющие FK ссылку на данный экземплярRubrics
. Взгляните на эту официальную документацию .
Book имеют одну рубрику (внешний ключ rubrics), а рубрики имеют несколько книг (books_set). Я бы также предложил изменить имя FK с rubrics
на rubric
, так как он может быть только один.
Попробуйте это и работайте дальше:
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Books
#fields = ("title",)
exclude = ()
class RubricsSerializer(serializers.ModelSerializer):
class Meta:
model = Rubrics
fields = ("books_set",)
#exclude = ()
Сначала я попытался получить результат, который вы хотели, используя ваше представление, но ничего не получилось! Поэтому я создал другое представление:
from .serializers import *
from rest_framework import generics
from .models import *
class BooksByRubricView(generics.ListAPIView):
serializer_class = RubricsSerializer
queryset = Rubric.objects.all()
# You should try!
Конечно, мне также пришлось создать путь (только для тестов! Не обращайте внимания!):
from django.urls import path
from .views import BooksByRubricView
urlpatterns = [
path('books/', BooksByRubricView.as_view(), name='books')
]
В ваших моделях:
from django.db import models
class Rubric(models.Model):
id = models.AutoField(primary_key=True) # Do not use plural in the models name!
rubric_name = models.CharField(max_length=255, blank=True, null=True)
class Meta:
ordering = ['id'] # Create a ordering!
def __str__(self):
return self.rubric_name
class Book(models.Model):
rubric = models.ForeignKey(Rubric, related_name='rubrics', on_delete=models.CASCADE)
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=255, blank=True, null=True)
author = models.CharField(max_length=255, blank=True, null=True)
date = models.CharField(max_length=255, blank=True, null=True)
class Meta:
ordering = ['id'] # Create a ordering!
В вашем файле serializers.py:
from rest_framework import serializers
from .models import *
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = (
"title",
"author",
"date"
)
class RubricsSerializer(serializers.ModelSerializer):
rubrics = BookSerializer(many=True, read_only=True)
class Meta:
model = Rubric
fields = (
"id", # Put an Id if you want!
"rubrics",
)
Возможно, проблема была только в вашем представлении! Поэтому я просто сделал все это, чтобы получить результат, который вы хотите, но локально; изображения результата: