多个django模型值取决于选择字段值

时间:2017-11-08 12:00:19

标签: python django django-models

我的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类?
  • 使用Organization作为父类并创建子类 像:

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)
  • 还有别的吗?

2 个答案:

答案 0 :(得分:0)

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

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)

答案 1 :(得分:0)

我会喜欢

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)