Django:我可以在form.py中用模型实例数据预填充表单吗?

时间:2018-09-09 14:24:04

标签: python django

我已经在views.py文件中看到了一种执行我想要的方法的方法,但是由于我可能要在几个不同的地方使用该表单,并且因为我相信它更多地属于forms.py,所以我想知道是否以及如何在不修改视图的情况下用一个特定用户的数据库中已经存储的数据来预填充表单。看到我尝试过的东西会说明一切:

models.py:

class Customers(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='details')
    city = models.CharField(max_length=50, blank=True, null=True)
    dpt = models.IntegerField(blank=True, null=True)
    adress = models.CharField(max_length=100, blank=True, null=True)
    cplt_add = models.CharField(max_length=100, blank=True, null=True)
    phone = models.CharField(max_length=14, blank=True, null=True)

forms.py:

class CustomerForm(ModelForm):

    def __init__(self):

        for field in self.fields:

            user_infos = Customers.objects.get(pk=request.user.details.id)
            initial_value = user_infos.field
            field(initial=initial_value)


    def clean_form(self):

        ...


    class Meta:

        model = Customers
        fields = ['city', 'adress', 'dpt', 'cplt_add', 'phone']
        widgets = {
            'city': TextInput(attrs={
                'class': 'form_input',
                'placeholder': 'Ville'}),
            'dpt': TextInput(attrs={
                'class': 'form_input',
                'placeholder': 'Département'}),
            'adress': TextInput(attrs={
                'class': 'form_input',
                'placeholder': 'Adresse'}),
            'cplt_add': TextInput(attrs={
                'class': 'form_input',
                'placeholder': "Complément d'adresse"}),
            'phone': TextInput(attrs={
                'class': 'form_input',
                'placeholder': 'Téléphone'}),
            }

不幸的是,这段代码返回了:

  

'CustomerForm'对象没有属性'fields'

关于如何通过良好实践方法做到这一点的任何建议?

1 个答案:

答案 0 :(得分:2)

您以错误的级别解决了该问题:Django已经对此提供了支持,并且用__init__自己编写它不是一个好主意(某些特定的除外)边缘拐角案例)。

因此,您可以从__init__中删除ModelForm替代项:

# app/forms.py

class CustomerForm(ModelForm):

    # remove the __init__ override

    class Meta:
        model = Customers
        fields = ['city', 'adress', 'dpt', 'cplt_add', 'phone']
        widgets = {
            'city': TextInput(attrs={
                'class': 'form_input',
                'placeholder': 'Ville'}),
            'dpt': TextInput(attrs={
                'class': 'form_input',
                'placeholder': 'Département'}),
            'adress': TextInput(attrs={
                'class': 'form_input',
                'placeholder': 'Adresse'}),
            'cplt_add': TextInput(attrs={
                'class': 'form_input',
                'placeholder': "Complément d'adresse"}),
            'phone': TextInput(attrs={
                'class': 'form_input',
                'placeholder': 'Téléphone'}),
            }

在视图中(或您要构造表单的其他地方),我们可以通过构造函数的instance=参数传递实例:

# app/views.py

def my_view(request):
    customer=Customers.objects.get(pk=request.user.details.id)
    my_form = CustomerForm(instance=customer)
    # ...
    # return HttpResponse object

然后Django将确保这些值以正确的形式填写(就像它是initial值一样)。如果同时提供initial值和instance,则initial的优先级如documentation on the ModelForm中所述:

  

与常规表单一样,可以在实例化表单时通过指定initial参数来为表单指定初始数据。通过这种方式提供的初始值将覆盖表单字段中的初始值和附加的模型实例中的值