首页 > 解决方案 > 使用模型的值创建一个 Django 表单

问题描述

我有一个模型如下:

class BloodTestType(models.Model):
    type = models.CharField(max_length=200)
    def __str__(self):
        return str(self.type)

class BloodParameters(models.Model):
    type = models.ForeignKey(BloodTestType, on_delete=models.CASCADE)
    parameter = models.CharField(max_length=200)
    minimum_value = models.FloatField()
    maximum_value = models.FloatField()
    unit = models.CharField(max_length=200)
    required = models.BooleanField(default=True)
    GENDER_CHOICES =  [
    ('B', 'Both'),
    ('M', 'Male'),
    ('F', 'Female'),
    ]
    gender = models.CharField(max_length = 100,choices = GENDER_CHOICES,default = 'B')

    def __str__(self):
        return str(self.type) + ' ' + str(self.parameter)

考虑 BloodParameters 模型有 3 个参数,类型 = '1'

我想创建一个包含这 3 个参数作为输入字段的 Django 表单,但表单加载为空白。我正在我的表单文件中的这些行上尝试一些东西:

class BloodReportCBCIronForm(forms.Form):
    cbc_iron_parameters = BloodParameters.objects.filter(type = 1)
    print('asd')
    print(cbc_iron_parameters.__dict__)
    for each in cbc_iron_parameters:
        each.parameter = forms.CharField(label = each.parameter,max_length = 80,required = True,)

标签: djangodjango-formsdjango-crispy-forms

解决方案


您正在寻找向表单动态添加字段的地方,而这样做的地方是在表单的__init__方法中。像这样:

from django import forms
from django.utils.text import slugify


class BloodReportCBCIronForm(forms.Form):
    def __init__(self, type, *args, **kwargs):
        """
        Initializes a form with a dynamic set of fields, based upon objects fetched from the database.        
        :param type: integer ID of a BloogTestType object 
        :param args: 
        :param kwargs: 
        """
        cbc_iron_parameters = BloodParameters.objects.filter(type__id=type)

        for each in cbc_iron_parameters:
            # Safety-check here, in case the each.parameter value contains spaces or symbols.
            field_name = slugify(each.parameter)
            # Add a field to the self.base_fields dictionary. Note that this doesn't deal 
            # with the scenario where there are multiple parameters with the same name.
            self.base_fields[field_name] = forms.CharField(label=each.parameter, max_length=80, required=True)

        # super() will now create fields based off of whatever you added to the self.base_fields dictionary.
        super().__init__(*args, **kwargs)

然后要初始化和使用表单,您需要执行以下操作:

form = BloodReportCBCIronForm(type=1)

推荐阅读