根据您的评论,我认为您只需要一个模型,并使用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()
测试一下:
在[4]中:从test_app.models导入ModelA、ModelB、ModelBase
在[5]中:matches = ModelBase.objects.filter(name='Product1')
在[6]中:matches.count()
Out[6]:2
在[7]中:对于m in matches:
...: 打印 "%s - %s" % (m.name, m.price)
...:
Product1 - 10.5
Product1 - 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()
测试一下
from test_app.models import ModelX, ModelY
from itertools import chain
full_set = chain(ModelX.objects.filter(name='Product2'), Model.Y.objects.filter(name='Product2'))
In [5]: full_set = chain(ModelX.objects.filter(name='Product2'), > ModelY.objects.filter(name='Product2'))
In [6]: for m in full_set:
...: print "%s - %s" % (m.name, m.price)
...:
Product2 - 14.0
Product2 - 30.0
我会选择使用抽象类,并实现多态关系;通过Django的ContentType框架进行查询。
这个解决方案假设模型A
具有可与模型B
区分开来的属性,否则一个带有ChoiceField
的单一模型是最合适的。
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)
Polymorphism: http://en.wikipedia.org/wiki/Polymorphism_(computer_science)
子类型多态:http://en.wikipedia.org/wiki/Subtyping
Django内容类型框架:https://docs.djangoproject.com/en/1.8/ref/contrib/contenttypes/
Django自定义管理器:https://docs.djangoproject.com/en/1.8/topics/db/managers/
Django Queryset .distinct()
:https://docs.djangoproject.com/en/1.8/ref/models/querysets/#django.db.models.query.QuerySet.distinct
要了解更强大的Django多态性,请查看django-polymorphic。