在派生字段上查询Django

时间:2019-04-25 16:26:23

标签: django django-models django-queryset

使用Django 1.8

我有一个非托管模型,该模型指向数据库中的视图,并且我试图基于派生字段返回查询集。

这是模型结构的基本示例:

class Book(models.Model):
    book_id = models.IntegerField()
    publisher = models.CharField(max_length=20, null=True) # Can join to Publisher.publisher_name
    sku = models.CharField(max_length=15, null=True) # Can join to Sku.sku

    class Meta:
        managed = False
        db_table = 'vw_book'


class Sku(models.Model):
    sku = models.CharField(max_length=15)
    publisher = models.ForeignKey('myapp.Publisher')


class Publisher(models.Model):
    publisher_name = models.CharField(max_lenth=20)
    region = models.ForeignKey('myapp.Region')


class Region(models.Model):
    region_name = models.CharField(max_length=20)

我正在寻找一种方法,该方法根据地区(从出版商派生为首选字段,然后是sku)返回Book的查询集。 Book中的这些字段可能引用不同的区域字段,因为数据是不均匀的,并且是从多个来源派生的。我可以在Book模型中添加一种方法来推导区域,但是尝试从中获取查询集太慢了。

class Book(models.Model):
    publisher = models.CharField(max_length=20, null=True)
    sku = models.CharField(max_length=15, null=True)

    class Meta:
        managed = False
        db_table = 'vw_book'

    def get_region(self):
        if not self.publisher:
            if not self.sku:
                return ''
            try:
               sku = Sku.objects.get(sku=self.sku)
               return sku.publisher.region.region_name
            except Sku.DoesNotExist:
               return ''
         try:
             publisher = Publisher.objects.get(publisher_name=self.publisher)
             return publisher.region.region_name
         except Publisher.DoesNotExist:
             return ''


region_dict = {}
for book in Book.objects.all():
    region_dict.setdefault(book.get_region(), []).append(book.book_id)

Book.objects.filter(book_id__in=region_dict.get('UK', []))

我无法在Book模型中添加额外的字段。有没有更有效的方法可以做到这一点?

1 个答案:

答案 0 :(得分:1)

我先过滤出skus,然后根据收到的sksk过滤书

skus = Sku.objects.filter(publisher__region__region_name=region).values_list('sku', flat=True)
Book.objects.filter(sku__in=skus)

如果需要,可以对发布者执行相同操作,然后执行“或”查询。

 .filter(Q(publisher__in=publishers) |Q(sku__in=skus))