属性相似的两个查询集的Django交集



我在django中有两个模型,我不知道如何编写它们(是有一个抽象模型和继承等…还是有两个不同的模型),但通常我有两种类型的对象A和B。

A和B完全一样,因为它们只是项目。它们都具有以下属性:

名称、价格

现在我想比较A和B中所有相似的项目(相似项目是同名的项目),并查看它们之间的价格差异(注意:假设没有重复,但假设交叉点包含可能不在A或B或两者中的项目,这意味着A和B不是完全相同的数据集,因此A可能有20个项目,但B可能有643个)

我如何在Django中使用模型等来做到这一点…

根据您的评论,我认为您只想要一个单一的模型,带有vendor字段来区分它们

class Product(models.Model):
VENDOR_CHOICES = (
('a', 'Vendor A'),
('b', 'Vendor B')
)
# you may find it more appropriate to have a ForeignKey to
# a Vendor model instead of this choice field:
vendor = models.CharField(max_length=16, choices=VENDOR_CHOICES)
name = models.CharField(max_length=255)
price = models.DecimalField(max_digits=6, decimal_places=2)

然后你可以得到任何两个供应商之间的价格差异(Django 1.8):

from django.db.models import Func, F
prices = (
Product.objects
.filter(vendor__in=('a', 'b'))
.order_by('name', 'vendor')  # order rows within each group
.values('name')  # GROUP BY `name`
.annotate(
first_vendor_price=Func(F('price'), function='FIRST'),
second_vendor_price=Func(F('price'), function='LAST')
)
)
price_diffs = {
group['name']: group['first_vendor_price'] - group['second_vendor_price']
for group in prices
}

我不确定这是否正是您所问的,但我可以想出两种方法来查询共享字段。

选项1

首先,您可以通过使用模型继承来获得具有两种模型类型的对象的单个QuerySet。

代码:

class ModelBase(models.Model):
name = models.CharField(max_length=10)
price = models.FloatField()
class ModelA(ModelBase):
field_a = models.BooleanField()
class ModelB(ModelBase):
field_b = models.BooleanField()

测试:

In[4]:从test_app.models导入ModelA、ModelB、ModelBase

在[5]中:matches=ModelBase.objects.filter(name='Product1')

在[6]中:matches.count()

输出[6]:2

在[7]中:对于匹配中的m:

…:打印"%s-%s"%(m.name,m.price)

…:

产品1-10.5

产品1-3.5

选项2

或者,如果您不想要继承并且不介意评估整个QuerySet,则可以使用itertools。

代码

class ModelX(models.Model):
name = models.CharField(max_length=10)
price = models.FloatField()
field_x = models.BooleanField()
class ModelY(models.Model):
name = models.CharField(max_length=10)
price = models.FloatField()
field_y = models.BooleanField()

测试

从test_app.models导入ModelX、ModelY

从itertools导入链

full_set=chain(ModelX.objects.filter(name='Product2'),Model.Y.objects.filter

在[5]中:full_set=chain(ModelX.objects.filter(name='Product2'),>ModelY.objects.filter

在[6]中:对于完整集中的m:

…:打印"%s-%s"%(m.name,m.price)

…:

产品2-14.0

产品2-30.0

我会使用一个抽象类,并实现多态关系;通过Django的ContentType框架进行查询。

该解决方案假设Model A具有区别于Model B的属性,否则具有ChoiceField的单个模型将是最合适的。

Django的多态性

ModelManager(models.Manager):
def get_intersection_on_name_for(self, name):
model = Model.objects.filter(model_object__name=name).distinct()
return model

Model(models.Model):
content_type = models.ForeignKey(ContentType, null=True)
object_id = models.PositiveIntegerField(null=True)
model_object = generic.GenericForeignKey('content_type', 'object_id') # this gets the actual field obj
objects = ModelManager()

ModelBase(models.Model):
name = models.CharField(max_length=255)
price = models.CharField(max_length=255)
class Meta:
abstract = True
ModelA(ModelBase):
weight = models.CharField(max_length=255)

ModelB(ModelBase):
url = models.UrlField(max_length=255)

使用中:

name = "Test Name"
Model.objects.get_intersection_on_name_for(name)

参考文献:

多态性:http://en.wikipedia.org/wiki/Polymorphism_(计算机科学)

亚型多态性:http://en.wikipedia.org/wiki/Subtyping

Django ContentTypes框架:https://docs.djangoproject.com/en/1.8/ref/contrib/contenttypes/

Django自定义管理器:https://docs.djangoproject.com/en/1.8/topics/db/managers/

Django查询集.distinct():https://docs.djangoproject.com/en/1.8/ref/models/querysets/#django.db.models.query.QuerySet.distinct

要了解django中更强大的多态性,请查看django多态性。

最新更新