来自关系模型的 Django 复杂查询

时间:2021-05-13 21:16:16

标签: python django django-rest-framework

使用 django-rest-framework,我有一个简单的模型

enter image description here

有一本书正在翻译中,这本书有章节(每一章都有一个名字),每一章都有段落。翻译表包含章节的外键(用于章节名称)和段落范围(从到),因为每个翻译者可以在一个翻译中翻译一组段落,并且翻译集可以无序,但没有重叠,例如Translator1可以翻译Chapter 3第4段到第10段,Translator2可以翻译Chapter3第20段到30段,但是Translator3不能翻译Chapter3第9段到20段,因为它会导致重复翻译。现在这是手动完成的,我不知道如何设置约束来防止它。

class Chapters(models.Model):
    id = models.PositiveIntegerField(primary_key=True)
    name_fr = models.CharField(max_length=45, db_collation='utf8_unicode_ci')
    name_en = models.CharField(max_length=50, db_collation='utf8_unicode_ci', blank=True, null=True)

    def __str__(self):
        return self.name_fr


class TheBook(models.Model):
    id = models.AutoField(primary_key=True)  # Field name made lowercase.
    chapterid = models.OneToOneField(Chapters,on_delete=models.PROTECT)  # Field name made lowercase.
    paragraphID = models.IntegerField()  # Field name made lowercase.
    paragraphText = models.TextField(db_collation='utf8_unicode_ci')  # Field name made lowercase.
    
    def __str__(self):
        return self.paragraphText


class Translate(models.Model):
    id = models.AutoField(primary_key=True)
    chapterid = models.ForeignKey(Chapters, to_field='id',on_delete=models.SET_NULL,null=True)
    parag_from = models.IntegerField(blank=True, null=True)
    parag_to = models.IntegerField(blank=True, null=True)
    translate = models.TextField(db_collation='utf8_unicode_ci', blank=True, null=True)

    def __str__(self):
        return ("{}: {} - {}").format(self.chapter, self.parag_from ,self.parag_to)

现在我的问题是选择所有有翻译的段落,然后用户点击翻译段落的组并阅读该组的翻译


class ParagraphList(APIView):
    def get(self, request, chapterName):

        # Get a list of paragraphs that has translation
        ParagraphList = Translate.objects.filter(
            chapter__name_en=chapterName
        ).values_list(
            'parag_from', 'parag_to', named=True
        ).order_by('parag_from')

        # variable to store the paragraph text
        ParagraphText = []

        # Loop through the List, and query the Book for the paragraphs in the 
        # range of parag_from to parag_to

        for i in range(len(ParagraphList)):
            ParagraphText.extend(list(
                Book.objects.filter(chapter__name_en=chapterName).filter(
                    paragraphID__range=list(ParagraphList[i]))
            ))

        serialized = BookParagSerializer(ParagraphText, many=True)
        return Response(serialized.data)

这段代码有两个问题:

  1. 效率不高。我必须向数据库发送多个查询才能获取数据
  2. 返回的数据就像一个列表:
[
 {
   "paragraphID": 1,
   "paragraphText":"Lorem ipsum dolor sit amet consectetur."
 },
 {
   "paragraphID": 2,
   "paragraphText":"Lorem ipsum dolor sit amet consectetur."
 },
 {
   "paragraphID": 3,
   "paragraphText":"Lorem ipsum dolor sit amet consectetur."
 },
....
]

我无法通过翻译将它们分组。像这样:

    [
    {
      "group":1,
      "parag_from":1,
      "parag_to":3,
      "translation_id":124,
      "context":[
                {
                  "paragraphID": 1,
                  "paragraphText":"Lorem ipsum dolor sit amet consectetur."
                },
                {
                  "paragraphID": 2,
                  "paragraphText":"Lorem ipsum dolor sit amet consectetur."
                },
                {
                  "paragraphID": 3,
                  "paragraphText":"Lorem ipsum dolor sit amet consectetur."
                },
      ]
    },
    {
      "group":2,
      "parag_from":9,
      "parag_to":11,
      "translation_id":321,
      "context":[
                {
                  "paragraphID": 9,
                  "paragraphText":"Lorem ipsum dolor sit amet consectetur."
                },
                {
                  "paragraphID": 10,
                  "paragraphText":"Lorem ipsum dolor sit amet consectetur."
                },
                {
                  "paragraphID": 11,
                  "paragraphText":"Lorem ipsum dolor sit amet consectetur."
                },
      ]
    },
    ...
]

在序列化器中,我不能有多个模型,而这个“分组”我不知道该怎么做。

我感谢任何建议。

0 个答案:

没有答案