【问题标题】:Django crispy form fields is not savingDjango 酥脆的表单字段没有保存
【发布时间】:2020-06-13 12:20:15
【问题描述】:

我正在尝试使用 Django 清晰表单进行格式化,但无法保存。

首先是一些代码:

forms.py

class CreateForm_test(forms.Form): 
    name = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Name'}))
    street = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Street'}))
    number = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Number'}))
    comment = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Comment'}))
    phone = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Phone'}))
    status = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Status'}))





class CrispyAddressForm(CreateForm_test):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.layout = Layout(
            Row(
                Column('name', css_class='form-group col-md-6 mb-0'),
                css_class='form-row'
            ),
            'street',
            'number',
            Row(
                Column('comment', css_class='form-group col-md-6 mb-0'),

                Column('phone', css_class='form-group col-md-2 mb-0'),
                Column('status', css_class='form-group col-md-2 mb-0'),


                css_class='form-row'
            ),

            Submit('submit', 'Submit')
        )

views.py

class CreateRegisterView(CreateView): 
    model = Register
    message = _("saved")
    form_class = CrispyAddressForm

    template_name = 'register_form.html'
    def form_valid(self, form):
        if self.request.user.is_authenticated:
            form.instance.user = self.request.user
        return super().form_valid(form)

    def get_success_url(self):
        messages.success(self.request, self.message)
        return reverse('home')

register_form.html

{% extends 'base.html' %}

{% load crispy_forms_tags %}

{% block content %}
  {% crispy form %}
{% endblock %}

当我在浏览器中打开表单时,出现此错误

forms.py", line 36, in __init__
    super().__init__(*args, **kwargs)
TypeError: __init__() got an unexpected keyword argument 'instance'
[29/Feb/2020 18:40:13] "GET /Register/create/ HTTP/1.1" 500 115893

我也试过 类 CreateRegisterView(FormView): 但后来我在这一行的视图中遇到了同样的错误form.instance.user = self.request.user

【问题讨论】:

  • 您没有使用ModelForm,因此没有instance
  • 好的,但是当我更改为 forms.ModelForm 时,我可以看到表单但它没有保存。当我点击提交按钮时,网站正在重新加载,但没有保存任何内容
  • 提交表单时是否看到 POST 请求?
  • 是的,当我更改为 ModelForm 时,我可以在浏览器中看到表单,但它没有保存
  • 但是如果你提交表单,它应该登录服务器控制台(不是浏览器)一个POST请求。

标签: django python-3.x python-3.7 django-crispy-forms django-2.2


【解决方案1】:

问题是你使用了Form不是ModelForm。一个简单的Form 没有.instance,也不知道.save(),因为Form 的任务只是处理GETPOST 数据,并进行验证和清理。建立在Form 之上的ModelForm 可以加载、更新和保存模型对象。因此,您应该从ModelForm 继承,并提供Meta

class CreateForm_test(forms.ModelForm): 
    name = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Name'}))
    street = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Street'}))
    number = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Number'}))
    comment = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Comment'}))
    phone = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Phone'}))
    status = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Status'})

    class Meta:
        model = Register
        fields = ['name', 'street', 'number', 'comment', 'phone', 'status']

此外,如documentation 中指定的,您需要在帮助程序中指定操作:

class CrispyAddressForm(CreateForm_test):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_action = 'name_of_createview'
        self.helper.layout = Layout(
            Row(
                Column('name', css_class='form-group col-md-6 mb-0'),
                css_class='form-row'
            ),
            'street',
            'number',
            Row(
                Column('comment', css_class='form-group col-md-6 mb-0'),

                Column('phone', css_class='form-group col-md-2 mb-0'),
                Column('status', css_class='form-group col-md-2 mb-0'),


                css_class='form-row'
            ),

            Submit('submit', 'Submit')
        )

【讨论】:

    【解决方案2】:

    我认为,主要问题是我定义了两次字段。一次在模型中,一次在我的表单中。

    现在这正在工作: 表格

    class CreateForm_test(forms.ModelForm):
        class Meta:
            model = Register
            fields = ['name', 'street', 'number', 'comment', 'phone', 'status']
    
    
    
    class CrispyAddressForm(CreateForm_test):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.helper = FormHelper()
            self.helper.layout = Layout(
                 Row(
                     Column('name', css_class='form-group col-md-7 mb-0'),
                    css_class='form-row'
                ),
                Row(
                    Column('street', css_class='form-group col-md-6 mb-0'),
                    Column('number', css_class='form-group col-md-1 mb-0'),
                    css_class='form-row'
                ),
    
                Row(
                    Column('comment', css_class='form-group col-md-6 mb-0'),
                    css_class='form-row'
                ),
                Row(
                    Column('phone', css_class='form-group col-md-6 mb-0'),
                    css_class='form-row'
                ),
                Submit('submit', 'Submit')
            )
    

    观看次数

    class CreateRegisterView(CreateView):
        model = Register
        message = _("saved")
        form_class = CreateForm
        template_name = 'register_form.html'
        def form_valid(self, form):
            if self.request.user.is_authenticated:
                form.instance.user = self.request.user
            return super().form_valid(form)
    
        def get_success_url(self):
            messages.success(self.request, self.message)
            return reverse('home')
    

    型号

    class Register(models.Model):
        CREATED = "C"
        DELETED = "D"
        STATUS = (
            (CREATED, _("Created")),
            (DELETED, _("Deleted")),
        )
        user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, related_name="author", on_delete=models.SET_NULL, default=1)
        timestamp = models.DateTimeField(auto_now=True)
        created_at = models.DateTimeField(default=datetime.now)
        status = models.CharField(max_length=1, choices=STATUS, default=CREATED)
        comment = models.CharField(max_length=42, null=True, unique=False, blank=True)
        edited = models.BooleanField(default=False)
        objects = ArticleQuerySet.as_manager()
        name = models.CharField(max_length=35, null=True, unique=False)
        street = models.CharField(max_length=42, null=True, unique=False, blank=True)
        number = models.CharField(blank=True, null=True, max_length=6)
        phone = models.CharField(max_length=15, blank=True, null=True)
        zip = models.CharField(max_length=42, null=True, unique=False, blank=True)
        city = models.CharField(max_length=42, null=True, unique=False, blank=True)
        class Meta:
            verbose_name = _("Register")
            verbose_name_plural = _("Register")
            ordering = ("-timestamp",)
    
        def __str__(self):
            return self.name
    
        def save(self, *args, **kwargs):
            super().save(*args, **kwargs)
    

    html

    {% extends 'base.html' %}
    
    {% load crispy_forms_tags %}
    
    {% block content %}
      {% crispy form %}
    {% endblock %}
    

    为了理解,对于crispyforms,我有两个选项来格式化表单。第一个是表单,第二个是直接在 html 中。

    当我将视图更改为 form_class = CreateForm_test 和 html 时

    {% extends 'base.html' %}
    
    {% load crispy_forms_tags %}
    
    {% block content %}
      <form method="post" novalidate>
        {% csrf_token %}
        <div class="form-row">
          <div class="form-group col-md-6 mb-0">
            {{ form.name|as_crispy_field }}
          </div>
        </div>
        <button type="submit" class="btn btn-primary">Submit</button>
      </form>
    {% endblock %}
    

    然后不再起作用,表单中的第一个示例格式正在起作用。在第二个 html 中,我只添加了字段name,因为只有这是一个必填字段。

    html-formatting 不起作用的区别是什么?表单在浏览器中可见,但没有保存,没有错误。

    【讨论】:

      猜你喜欢
      • 2021-07-07
      • 2013-04-23
      • 2019-12-21
      • 2016-01-26
      • 1970-01-01
      • 2022-07-01
      • 2018-11-22
      • 2016-01-29
      • 2021-06-16
      相关资源
      最近更新 更多