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

Ale*_*Mdg 5 python django django-views

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

模型.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)
Run Code Online (Sandbox Code Playgroud)

形式.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'}),
            }
Run Code Online (Sandbox Code Playgroud)

可悲的是,此代码返回:

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

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

Wil*_*sem 6

您在错误的级别上解决了问题: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'}),
            }
Run Code Online (Sandbox Code Playgroud)

在视图中(或其他要构造表单的地方),然后我们可以通过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
Run Code Online (Sandbox Code Playgroud)

然后 Django 将确保以正确的形式填写这些值(就好像它是initial值一样)。如果您同时提供initial值和 an instance,则initials 优先,如有关 的文档中所述ModelForm

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

  • 我不知道在视图中这样做的方式。实际上看起来比在 forms.py 中更简单,即使我要在多个视图中使用它。谢谢。 (2认同)