3

我在 django 中有两个模型,我不确定如何编写它们(是否有抽象模型和继承等......或者有两个不同的模型)但通常我有两种类型的对象 A 和 B。

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

名称、价格

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

我如何使用模型等在 Django 中执行此操作...

4

3 回答 3

2

从您的评论中,我认为您只需要一个模型,并用一个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
}
于 2015-04-24T16:08:38.570 回答
0

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

选项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] 中:匹配 = 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 = 链(ModelX.objects.filter(name='Product2'), Model.Y.objects.filter(name='Product2'))

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

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

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

...:

产品 2 - 14.0

产品2 - 30.0

于 2015-04-24T13:40:35.030 回答
0

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

此解决方案假定Model A具有与 不同的属性Model B,否则带有 a 的单个模型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_(computer_science)

子类型多态性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-polymorphic

于 2015-04-24T17:25:42.417 回答