Django验证列组合存在(与布尔字段唯一)

时间:2016-03-15 13:49:03

标签: python django validation model

我在使用Django 1.9。我有一个简单的模型:

#Goods
class Goods(models.Model):
    code = models.CharField(max_length=50)
    decription = models.CharField(max_length=100)
    ...etc

#Vendors
class Vendors(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=100)
    ...etc

和一个类来定义多个供应商以获得好处。

#Purchase_options
class PurchaseOptions(models.Model):
    preferred_vendor = models.BooleanField()
    vendor = models.ForeignKey(Vendors)
    good = models.ForeignKey(Goods)

以下是问题: 如何确保将特定商品的仅一个供应商设置为首选?

表格上接受的值:

**Vendor | Product | Preferred**
  V_01   | Good_01 | True
  V_02   | Good_01 | False
  V_03   | Good_01 | False
  V_02   | Good_02 | True
  V_04   | Good_02 | False

桌子上的错误值:

**Vendor | Product | Preferred**
  V_01   | Good_01 | True
  V_02   | Good_01 | **True**  <-There's already a preferred vendor.
  V_03   | Good_01 | False
  V_02   | Good_02 | True
  V_04   | Good_02 | False

我正在使用Django的管理界面来填充Puchase_Options上的数据。 我试过这个:

1)定义一个验证器,给定优先值和产品ID,检查表中是否存在这种组合:

def validator(preferred, id):
    if Purchase_Option.objects.filter(good.id=id,preferred_vendor=preferred).exists():
        Raise ValidationError("There's already a preferred vendor defined for this product")

但它告诉我对象Purchase_Options不存在。我相信我实际上无法在验证器函数中查询数据库或处理查询集。

2)我尝试使用元属性 unique-together(“preferred_vendor”,“good_id”)。除了我必须允许 False + Good_Id 的多种组合(因为我有很多非首选供应商)以外,这样才有用......但只有1种 True + Good_id的组合

我真的不知道还有什么可以尝试,我真的很期待听到你的想法。你以前在多个场合救了我:D

1 个答案:

答案 0 :(得分:4)

您可以将NullBooleanField用于preferred_vendor,将unique_together用于preferred_vendorgood。对于一个首选供应商,请使用True;对于所有其他供应商,请使用NULL代替False

这将允许您拥有多对(goodNULL)并且只有一对(goodTrue)。缺点是你只能有一对(goodFalse),但这不应该是一个问题。

E.g:

class PurchaseOptions(models.Model):
    preferred_vendor = models.NullBooleanField()
    vendor = models.ForeignKey(Vendors)
    good = models.ForeignKey(Goods)

    class Meta:
        unique_together = ("preferred_vendor", "good")

然后:

  Vendor | Product | Preferred
  V_01   | Good_01 | True
  V_02   | Good_01 | NULL
  V_03   | Good_01 | NULL
  V_02   | Good_02 | True
  V_04   | Good_02 | NULL