具有可变 "required" 字段的 Django 表单

Django forms with variable "required" fields

我有一个多租户应用程序,其中每个 "tenant"(公司模型对象)都有多个客户端。 每个租户都可以为其应用设置他们需要的必填字段。

class Client(models.Model):
    """
    Client information
    """
    company = models.ForeignKey(Company, blank=True, null=True, default=1, on_delete=models.SET_NULL)
    name = models.CharField(max_length=150, blank=True)
    email = models.EmailField(max_length=255, unique=True)
    phone_number = models.CharField(max_length=50, blank=True, null=True)

class RequiredClientFields(models.Model):
    """
    Let each business decide how to enforce the data filling requirements for its staff/clients.
    0 - dont even show it
    1 - show it, but dont require (default)
    2 - require field for either staff or client
    3 - require for clients when self-filling their form, but not the staff members
    """
    company = models.ForeignKey(Company, db_index=True, on_delete=models.CASCADE)
    field_name = models.CharField(max_length=50)
    status = models.PositiveSmallIntegerField(choices=FIELD_STATUS_CHOICES, default=1)

因此,在创建要在模板上使用的 django 表单时,根据公司政策显示(和验证)每个字段的最佳方式是什么?

谢谢

这样的事情可能会奏效。

声明一个 ModelForm 并用逻辑覆盖 __init__() 以删除字段或更改它们的 required 状态:

class ClientForm(forms.ModelForm):
    class Meta:
        model = Client
        fields = '__all__'

    def __init__(self, company, user, *args, **kwargs):
        super(ClientForm, self).__init__(*args, **kwargs)
        # For each RequiredClientFields instance, 
        # get the matching form field and make changes
        for rule in RequiredClientFields.objects.filter(company=company):
            # get the form field
            field = self.fields.get(rule.field_name, None)
            if field:
                if rule.status == 0:
                    # remove field from form
                    self.fields.pop(rule.field_name)
                elif rule.status == 2:
                    # require field
                    field.required = True
                elif rule.status == 3 and not user.is_staff:
                    # require for clients when self-filling their form, 
                    # but not the staff members
                    field.required = True

然后在您的视图中创建一个 ModelForm 实例,为公司和用户传递参数。

company = Company.objects.get(pk=1)
client_form = ClientForm(company=company, user=request.user)

请注意,以这种方式控制表单字段时存在潜在的安全隐患。查看 Django ModelForm 文档中的 relevant section