【问题标题】:Multiple django model values depend on choice field value多个 django 模型值取决于选择字段值
【发布时间】:2017-11-08 12:00:19
【问题描述】:

我的 Django 模型有一个 pricing_plan 选择字段。有 12 个字段的值取决于 pricing_plan 值。

class Organisation(models.Model):
    PRICING_CHOICES = (
        ('basic', 'Basic'),
        ('team', 'Team'),
        ('super', 'Super')
    )

    # some fields...

    pricing_plan = models.CharField(max_length=50, default='basic')
    max_host_accounts = models.IntegerField(default=1)
    max_admin_accounts = models.IntegerField(default=1)
    max_guests = models.IntegerField(default=10)

    # more fields whose value depends on pricing_plan value

对于每个不同的pricing_plan,这些字段都会获得特定的值。在代码中可以这样描述:

if pricing_plan == 'basic':
    max_host_accounts = 1
    max_admin_accounts = 1
    max_guests = 10
    ...
elif pricing_plan == 'team':
    max_host_accounts = 10
    max_admin_accounts = 3
    max_guests = 25
    ...

但是,未来可能会有更多定价计划和更多选择,我担心if/elif/else 声明会很大且不易阅读。

在 Django 模型中实现它的最佳/惯用方式是什么?

  • 为每个定价计划使用更多具有恒定值的 CHOICE 元组?
  • 为每个定价计划使用具有恒定值的 Enum 类?
  • 使用组织作为父类并创建子类 喜欢:

.

class BasicOrganisation(Organisation):
    max_host_accounts = models.IntegerField(default=1)
    max_admin_accounts = models.IntegerField(default=1)
    max_guests = models.IntegerField(default=10)

class TeamOrganisation(Organisation):
    max_host_accounts = models.IntegerField(default=10)
    max_admin_accounts = models.IntegerField(default=3)
    max_guests = models.IntegerField(default=25)
  • 还有别的吗?

【问题讨论】:

  • 只有字段的默认值会随着每个定价计划而变化?
  • @mkurnikov,实际上是的。这些字段将具有固定值(取决于定价计划)。即使我们转移到另一个计划,我们也可以将值重置为新的默认值。
  • 或选中此项以覆盖保存方法fosshelp.blogspot.in/2010/12/…
  • 简而言之,获取定价计划并保存模型,然后为其他属性设置默认值

标签: python django django-models


【解决方案1】:

我会这样做(我使用 django-choices 包进行伪枚举仿真):

from django.db import models
from djchoices import ChoiceItem, DjangoChoices


def get_max_admin_accounts(pricing_plan):
    if pricing_plan == Organization.Pricing.BASIC:
        return 1
    # other code


class Organization(models.Model):
    class Pricing(DjangoChoices):
        BASIC = ChoiceItem('basic', 'Basic')
        TEAM = ChoiceItem('team', 'Team')
        SUPER = ChoiceItem('super', 'Super')

    pricing_plan = models.CharField(max_length=50, default=Pricing.BASIC)

    max_host_accounts = models.IntegerField()
    max_admin_accounts = models.IntegerField()
    max_guests = models.IntegerField()

    def save(self, **kwargs):
        if not self.max_admin_accounts:
            self.max_admin_accounts = get_max_admin_accounts(self.pricing_plan)

        # other fields filled

        super().save(**kwargs)

【讨论】:

    【解决方案2】:

    我愿意

    class Organisation(models.Model):
        PRICING_CHOICES = {
            "basic": ("Basic", (1, 1, 10)),
            "team": ("Team", (10, 3, 25)),
        }
    
        # some fields...
    
        pricing_plan = models.CharField(choices=tuple([(i,j[0]) for i, j in PRICING_CHOICES.items()]), max_length=50, default='basic')
        #other fields
    
        def set_plan(self, max_host_accounts, max_admin_accounts, max_guests):
            self.max_host_accounts = max_host_accounts
            self.max_admin_accounts = max_admin_accounts
            self.max_guests = max_guests
    
        def save(self, *args, **kwargs):
            if getattr(self, "plan_changed", ""): #you need to set this attribute whenever updating a plan. like model_obj.plan_changed = True
                #otherwise you need to check db whether plan is changed or not.
                self.set_plan(*self.PRICING_CHOICES[self.pricing_plan][1])
            super(Organisation, self).save(*args, **kwargs)
    

    【讨论】:

      猜你喜欢
      • 2014-08-17
      • 2019-04-20
      • 1970-01-01
      • 2016-12-28
      • 1970-01-01
      • 2021-03-03
      • 2022-11-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多