【问题标题】:Custom ORM in Django. Based on Entity ID & Entity TypeDjango 中的自定义 ORM。基于实体 ID 和实体类型
【发布时间】:2020-08-06 08:48:18
【问题描述】:

我的目标是使用实体类型和实体 id 的引用从不同模型中检索数据。

示例: 我有客户模型和地址模型

from django.db import models

class Customer(models.Model):
    name = models.CharField(null=False, blank=False, max_length=255)
    email = models.EmailField(null=False, blank=False, unique=True)

class Address(models.Model):
    entity_type = models.CharField(null=False, max_length=255)
    entity_id = models.PositiveIntegerField(null=False)
    address1 = models.CharField(max_length=255)
    address2 = models.CharField(max_length=255)

现在我使用原始查询

cursor.execute("SELECT * FROM customers AS cust 
     INNER JOIN addresses AS addrs ON 
     (cust.id = addrs.entity_id AND 'customer' = addrs.entity_type) 
     WHERE cust.id IN (%s)", [ids])

但这不是好的解决方案。 id 在数千范围内时花费太多时间。

如果有任何其他方式来存档这些数据。那么请在 cmets 中给出你的解决方案..

【问题讨论】:

标签: django database postgresql django-models django-orm


【解决方案1】:

使用“entity_id”字段管理外部实体的 ID 似乎很尴尬。为什么不对客户使用 ForeignKey 字段,或者如果实体不总是客户,请使用 GenericForeignKey ?

现在您正在重新发明轮子。

class Address(models.Model):
    entity_type = models.CharField(null=False, max_length=255)
    customer = models.ForeignKey(Customer, on_delete=models.SET_NULL)

然后:

q = Address.objects.filter(customer in cutomers_collection)

关于 ForeignKey 的文档:https://docs.djangoproject.com/en/3.0/ref/models/fields/#django.db.models.ForeignKey

【讨论】:

  • - GenericForeignKey 是一个很好的解决方案 - 但在我的情况下,一个客户有很多地址, - 如果我使用 GenericForeignKey 我无法检索那些多个地址对象!
【解决方案2】:
query_set = Address.objects.filter(
    Q(entity_type='R') | Q(entity_id=1)
)

【讨论】:

  • 这不是一个好的解决方案。它只给出地址对象,我也想要客户对象!你用了|OR运算符,我们需要使用AND运算符!
【解决方案3】:
from django.db import models

class Customer(models.Model):
    name = models.CharField(null=False, blank=False, max_length=255)
    email = models.EmailField(null=False, blank=False, unique=True)

class Address(models.Model):
    entity_type = models.CharField(null=False, max_length=255)
    customer = models.ForeignKey(Customer, on_delete=models.SET_NULL)
    address1 = models.CharField(max_length=255)
    address2 = models.CharField(max_length=255)

data = Address.objects.filter(entity_type='customer', customer_id__in=[ids]).values('address1', 'address2', 'customer__name', 'customer__email')

【讨论】:

  • 兄弟,我在项目中也有其他模型,如供应商。该供应商模型也使用地址模型。所以我不能在地址模型中将entity_id 更新为customer 字段与外部关系!
  • 那又怎样?为 Vendor 使用另一个 fk 字段,您对此没有限制
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-20
  • 2022-10-17
  • 2020-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多