Django ORM中的一对多关系查询,我想查询一个表,并希望获得许多表数据作为列表的输出

z9zf31ra  于 2023-05-30  发布在  Go
关注(0)|答案(1)|浏览(135)

以下是我的模型:

from django.db import models
from django.db.models.expressions import F

class Publication(models.Model):
    name = models.CharField('name of publication', max_length=1024, null=True, blank=True) 

    def __str__(self):

        return f'{self.name}' 

    class Meta:
        verbose_name = "Publication"
        verbose_name_plural = "Publications" 

class Book(models.Model):
    name = models.CharField('name of book', max_length=1024, null=True, blank=True) 
    publication = models.ForeignKey(Publication, on_delete=models.CASCADE, related_name='books_publications', null=True, blank=True)

    def __str__(self):

        return f'{self.name}//{self.publication.name}'

    class Meta:
        verbose_name = "Book"
        verbose_name_plural = "Book"

我希望输出json作为单个出版物与图书列表(请使用Django ORM查询和Django序列化器或使用DRF显示我):
需要输出如下JSON格式:

[
    {
        "id": 1,
        "name": "publication 001",
        "book": [
            {
                "id": 1,
                "name": "Book 001"
            },
            {
                "id": 2,
                "name": "Book 002"
            }
        ]
    },
    {
        "id": 2,
        "name": "publication 002",
        "book": [
            {
                "id": 3,
                "name": "Book 003"
            },
            {
                "id": 4,
                "name": "Book 004"
            }
        ]
    }
]

我尝试了几种方法,但无法使用django orm query解决它。我已经通过原始查询完成了。但是我想通过Django ORM Query实现它。所以请帮帮我。TIA

llycmphe

llycmphe1#

下面的代码使用简单的序列化程序就可以做到这一点

class BookSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    name = serializer.CharField()
   

class PublicationSerializer(serializers.Serializer):
    id = serializers.IntegerField()
    name = serializers.CharField()
    book = BookSerializer(source="books_publications.all", many=True)

qs = Publication.objects.all()
data = PublicationSerializer(qs, many=True).data

source="book_set"允许将对象字段Map到不同的序列化器字段。
book_set是Django提供的默认related_name。这意味着my_publication.book_set.all()等价于Book.objects.filter(publication=my_publication)
您应该考虑定义自己的related_name

publication = models.ForeignKey(Publication, on_delete=models.CASCADE, null=True, blank=True, related_name="books")

请注意,上面的代码将导致对数据库的N+1个查询。第一个用于获取所有出版物,每个出版物一个用于获取相关书籍。
您可以并且应该使用prefetch_related将查询的数量减少到两个。

qs = Publication.objects.all()
qs = qs.prefetch_related("books_publications")
data = PublicationSerializer(qs, many=True).data

您也可以使用ModelSerializer

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ("id", "name")

class PublicationSerializer(serializers.ModelSerializer):
    book = BookSerializer(source="books_publications.all", many=True)

    class Meta:
        model = Publication
        fields = ("id", "name", "book")

相关问题