Django嵌套多个外键模型的Json

时间:2015-12-04 22:45:21

标签: django orm

我有4个通过FK建立关系的模型。

class Journal(models.Model):
    name = models.CharField(max_length=255)

class Volume(models.Model):
    journal = models.ForeignKey(Journal, related_name='volumes')
    number = models.IntegerField()

class Issue(models.Model):
    volume = models.ForeignKey(Volume, related_name='issues')
    number = models.IntegerField()

class Article(models.Model):
    issue = models.ForeignKey(Issue, related_name='articles')
    title = models.CharField(max_length=255)

我需要一种JSON格式,如跟随结构。

journal: [
    { name: 'Volume number goes here', type: 'folder',  id: 'F1',
        data: [
            { name: 'Issue number goes here', type: 'folder', id: 'F1F1',
                data: [
                    { name: 'Article name goes here>', type: 'item', id: 'F1F1I1' },
                    { name: 'Article name goes here>', type: 'item', id: 'F1F1I2' },
                    { name: 'Article name goes here>', type: 'item', id: 'F1F1I3' },
                ]},
            { name: 'Issue number goes here', type: 'folder', id: 'F1F2',
                data: [
                    { name: 'Article name goes here>', type: 'item', id: 'F1F2I1' },
                    { name: 'Article name goes here>', type: 'item', id: 'F1F2I2' },
                    { name: 'Article name goes here>', type: 'item', id: 'F1F2I3' },
                ]},
        ]
    },
    { name: 'Volume number goes here', type: 'folder',  id: 'F2',
        data: [
            { name: 'Issue number goes here', type: 'folder', id: 'F1F1',
                data: [
                    { name: 'Article name goes here>', type: 'item', id: 'F2F1I1' },
                    { name: 'Article name goes here>', type: 'item', id: 'F2F1I2' },
                    { name: 'Article name goes here>', type: 'item', id: 'F2F1I3' },
                ]},
            { name: 'Issue number goes here', type: 'folder', id: 'F1F2',
                data: [
                    { name: 'Article name goes here>', type: 'item', id: 'F2F2I1' },
                    { name: 'Article name goes here>', type: 'item', id: 'F2F2I2' },
                    { name: 'Article name goes here>', type: 'item', id: 'F2F2I3' },
                ]},
        ]
    }
],

我尝试过几种东西,但它会导致数百次SQL查询(因为for循环)

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

使用select_relatedprefetch_related。这些方法在Django ORM中用于执行SQL JOIN,因此您不会重复查询。

答案 1 :(得分:1)

您可以使用4个查询创建该JSON文件。您只需使用prefetch_related

以下是一些概念证明(对于与工作相关的查询,您必须有DEBUG=True):

from django.db import connection

journals = Journal.objects.all().prefetch_related('volumes', 'volumes__issues', 'volumes__issues__articles')

for journal in journals:
    print "%s" % journal.name
    for volume in journal.volumes.all():
        print "  %d" % volume.number
        for issue in volume.issues.all():
            print "    %d" % issue.number
            for article in issue.articles.all():
                print "      %s" % article.title

print len(connection.queries)

这将打印对象的简单树和最后的查询数量,这将等于4(如果在该连接之前没有进行任何查询)。从那里创建你的JSON输出并不远。

在创建精确的JSON时,Django REST Framework可能会有所帮助。假设您已完成并嵌套所有序列化程序,使用上述查询集提供JournalSerializer,将为数据库创建4个查询。