【问题标题】:Mutually exclusive many-to-many relationship in Django modelsDjango模型中的互斥多对多关系
【发布时间】:2017-04-27 12:17:52
【问题描述】:

我正在尝试创建一个简单的模型来跟踪 Django 1.10 中的 折扣券(使用 Postgres 9.5 作为基础数据库),我想知道是否有办法确保优惠券instanceid,也许是一个更准确的术语?)不会同时出现在两个 M2M 关系中。

我相信每个人都熟悉折扣券的工作原理,但为了以防万一,让我解释一下我的用例

  1. 总是会应用一些优惠券。例如:“第一次购买免费送货”,或“百事可乐 10% 的余生”……诸如此类。
  2. 其他一些优惠券将通过用户必须在某处输入的代码(实际上是一个简单的字符串)应用(例如 “使用代码“5-OFF”获得 5% 的折扣”...是的,我可能不得不对代码进行混淆处理:-D)
  3. 用户可以说“不,我不想将此优惠券应用于此订单,我稍后会使用它”。例如:如果用户可以使用一次性 5% 的优惠券,但想保留它以进行大额购买。假设客户知道他将在即将到来的将来进行大笔购买,而现在他正在做小额购买。他可能想保留 5% 的折扣,以便以后(更大)购买。

为了跟踪这些事情,我有一个这样的模型:

class CouponTracker(models.Model):
    # Coupons that require a code to be activated:
    extra_applied_coupons = ManyToManyField('Coupon', related_name='+')

    # Coupons that the user could have applied and specifically
    # said no (such as 5% off if the purchase is small, and wants
    # to use it later):
    vetoed_coupons = ManyToManyField('Coupon', related_name='+')

所以,问题是:

如何强制(在数据库级别,通过约束)优惠券不会同时出现在 extra_applied_couponsvetoed_coupons 中?

提前谢谢你!

【问题讨论】:

    标签: python django django-models many-to-many constraints


    【解决方案1】:

    为什么不将 2 个 extra_applied_couponsvetoed_coupons 组合起来,再多出 1 个字段(例如,type)来确定优惠券的组。那么问题会更简单,只需确保在 1 ManyToMany 关系中唯一

    class CouponTracker(models.Model):
        coupons = ManyToManyField('Coupon', related_name='+')
        type = models.IntegerField(default=0)
    

    type 对于extra_applied_coupons 可以是0,对于vetoed_coupons 可以是1。 如果要添加更多的关系属性,可以查看https://docs.djangoproject.com/en/1.11/topics/db/models/#extra-fields-on-many-to-many-relationships

    【讨论】:

    • 这是一种非常有趣的方法。我没有想过这样做。但是,这也会迫使我在 Python 方法中控制 type 字段(Django ......意思是......不是 SQL 级别)。我正在编写一个 set_vetoedset_extra_applied 做类似的事情(检查如果你否决优惠券它不在 ExtraApplied 中,反之亦然)。但我很欣赏这个答案。谢谢你。
    【解决方案2】:

    由于ManyToMany 关系创建了一个单独的表,因此AFAIK 无法跨表创建UNIQUE 约束。所以没有直接的方法在数据库级别添加约束。检查this。要么你必须在应用层上做,要么像this这样的黑客方式。

    【讨论】:

      猜你喜欢
      • 2018-06-09
      • 2018-01-04
      • 2019-05-09
      • 1970-01-01
      • 2012-07-22
      • 2015-02-03
      • 2012-12-04
      • 1970-01-01
      • 2019-02-09
      相关资源
      最近更新 更多