Есть ли способ ввести значения списка в набор запросов как настраиваемый агрегированный столбец - PullRequest
1 голос
/ 21 апреля 2019

Я ищу способ запроса данных из таких моделей, как Author с полями [pk, name] и Book [pk, author, title, опубликовано], так что, в конце концов, у меня будет есть что-то подобное

[
  {
    'pk': 'author_pk_1', 'name': 'author__name_1', 'books': [
      {
        'pk': 'book__pk_1',
        'title': 'book_name_1',
        'published': 'book_published_1',
      },
      {
        'pk': 'book__pk_2',
        'title': 'book_name_2',
        'published': 'book_published_2',
      }
    ]
  }
]

На данный момент я достиг этого, перебирая QuerySet и группируя их вручную, но это выглядит не очень хорошо:

authors = Author.objects.values('pk', 'name')
grouped = list()
for author in authors:
    entry = dict()
    entry['pk'] = author['pk']
    entry['name'] = author['name']
    entry['books'] = list(Book.objects.filter(author=author['pk']).values('pk', 'title', 'published'))
    grouped.append(entry)

UPDATE:

Ну, это было проще, чем я думал; вот что у меня так далеко:

view.py

@api_view(['GET'])
def api_get_grouped_books(request, *args, **kwargs):
  if request.method == 'GET':
    authors = Author.objects.all()
    serializer = AuthorSerializer(authors, many=True)
    return Response(serializer.data)

serializers.py

class BookSerializer(serializers.ModelSerializer):
  class Meta:
    model = Book
    fields = ('title', 'published', )


class AuthorSerializer(serializers.ModelSerializer):

  books = BookSerializer(many=True)

  class Meta:
    model = Author
    fields = ('name', 'books', )

  def create(self, validated_data):
    books_data = validated_data.pop('books')

    author, _ = Author.objects.get_or_create(
      name=validated_data.get('name'),
      defaults=validated_data
    )

    for book_data in books_data:
      try:
        Book.objects.get(title=book_data.get('title'))
      except ObjectDoesNotExist:
        Book.objects.create(author=author, **book_data)

    return author

Примечание: сначала я получал AttributeError, когда пытался опубликовать некоторые данные - он жаловался на то, что поле books не является частью Author модели, поэтому я в итоге добавил атрибут related_name='books' в author Поле ForeignKey в модели Book.

...