关键词

详解Django的 form_valid_json() 函数:返回表单验证成功后的 JSON 数据

表单(Form) 在Web开发中是一个必不可少的组件,它允许用户填写信息并把这些信息提交给服务器进行处理。通过 Django 自带的 Form 组件,可以轻松地创建表单及表单处理逻辑。其中,form_valid_json 是一个特别实用的函数。

1. form_valid_json()函数的作用

form_valid_json() 函数是 Django 中用于处理表单数据的一个函数。所谓表单数据,就是用户通过表单提交给服务器的数据。经过 Django 的数据处理,表单数据将被打包成一个字典对象,并传递给 form_valid_json() 函数进行处理。

form_valid_json() 函数的作用是将请求提交的表单数据经过有效性验证之后,将数据以及验证结果以 JSON 格式输出。

2. form_valid_json()函数的使用方法

2.1 重写form_valid()函数

form_valid_json() 是一个被定义在 FormView 中的函数,因此在使用时需要对该 View 进行继承。具体而言,我们需要继承 FormView,并在该 View 中重写 form_valid() 函数。在重写 form_valid() 函数时,我们需要调用 form_valid_json() 函数,并将返回结果进行输出。

下面是一个示例代码:

from django.views.generic.edit import FormView
from django.http import JsonResponse
from myapp.forms import MyForm

class MyFormView(FormView):
    form_class = MyForm
    template_name = 'my_form.html'
    success_url = '/thanks/'

    def form_valid(self, form):
        response = super(MyFormView, self).form_valid(form)
        if self.request.is_ajax():
            return JsonResponse(form.cleaned_data)
        else:
            return response

其中,MyFormView 继承自 FormView,它指定了表单类 MyForm 以及模板 my_form.html。当表单提交成功时,会跳转到 thanks 页面。form_valid 函数首先调用父类实现的 form_valid 函数来处理表单,然后判断请求是否是 Ajax 提交,如果是则调用 form_valid_json() 函数将表单数据打包成Json格式输出。若不是 Ajax 提交,则直接返回父类的函数处理结果。

2.2 实例1

假设有个网站需要用户填写一份调查表,并将调查表的数据记录在数据库中。这里我们来实现连同数据库入库的表单预处理。

模型类:

# myapp/models.py
from django.db import models

class Survey(models.Model):
    name = models.CharField(max_length=200)
    gender = models.CharField(max_length=10)
    age = models.IntegerField(default=0)
    occupation = models.CharField(max_length=100)

    def __str__(self):
        return self.name

表单类:

# myapp/forms.py
from django import forms
from django.forms import ModelForm
from myapp.models import Survey

class SurveyForm(ModelForm):
    class Meta:
        model = Survey
        fields = ['name', 'gender', 'age', 'occupation']

视图函数:

# myapp/views.py
from django.views.generic.edit import FormView
from django.http import JsonResponse

class SurveyFormView(FormView):
    template_name = 'survey_form.html'
    form_class = SurveyForm
    success_url = '/thanks/'

    def form_valid(self, form):
        response = super(SurveyFormView, self).form_valid(form)
        if self.request.is_ajax():
            survey = form.save()
            return JsonResponse(form.cleaned_data)
        else:
            return response

在表单提交成功后,将表单数据保存到Survey模型类对应的数据库中。如果请求为Ajax 请求,那么Json 化输出表单数据,否则跳转到 success_url 页面。

2.3 实例2

我们接下来结合一个CSS框架—Bootstrap,来展示在通过一个模态框表单作为一个Post表单提交数据的Ajax/Json化输出。

模型:

# myapp/models.py
from django.db import models

class Contact(models.Model):
    name = models.CharField(max_length=50)
    age = models.IntegerField()
    email = models.EmailField()
    content = models.TextField()

    def __str__(self):
        return self.name

表单:

# myapp/forms.py
from django import forms
from myapp.models import Contact

class ContactForm(forms.ModelForm):
    class Meta:
        model = Contact
        fields = ('name', 'email', 'age', 'content')
        widgets = {'content': forms.Textarea({'cols': 20, 'rows': 5})} # 优化content的text区域

模板:

<!-- myapp/index.html -->
{% extends "base.html" %}
{% load static %}
{% block content %}
    <div class="container">
        <h1>Contact Us</h1>
        <hr>
        <button type="button" id="btn_contact" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#ContactModal">Contact Us</button>
        <br><br><br><br><br><br><br><br>
    </div>
    <!-- Modal -->
    <div class="modal fade" id="ContactModal" tabindex="-1" role="dialog" aria-labelledby="ContactModalLabel" aria-hidden="true">
        <div class="modal-dialog modal-lg" role="document">
            <div class="modal-content">
                <div class="modal-header bg-primary text-white">
                    <h5 class="modal-title" id="ContactModalLabel">Contact us </h5>
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                        <span aria-hidden="true">&times;</span>
                    </button>
                </div>
                <form method="post" nctype="multipart/form-data" id="contact_form">
                    {% csrf_token %}
                    <div class="modal-body">
                        <div class="form-group row">
                            <div class="col-md-2">
                                <label for="{{ form.name.id_for_label }}" class="col-form-label">{{ form.name.label }}:</label>
                            </div>
                            <div class="col-md-10">
                                {{ form.name }}
                                <div class="invalid-feedback"></div>
                            </div>
                        </div>
                        <div class="form-group row">
                            <div class="col-md-2">
                                <label for="{{ form.email.id_for_label }}" class="col-form-label">{{ form.email.label }}:</label>
                            </div>
                            <div class="col-md-10">
                                {{ form.email }}
                                <div class="invalid-feedback"></div>
                            </div>
                        </div>
                        <div class="form-group row">
                            <div class="col-md-2">
                                <label for="{{ form.age.id_for_label }}" class="col-form-label">{{ form.age.label }}:</label>
                            </div>
                            <div class="col-md-10">
                                {{ form.age }}
                                <div class="invalid-feedback"></div>
                            </div>
                        </div>
                        <div class="form-group row">
                            <div class="col-md-2">
                                <label for="{{ form.content.id_for_label }}" class="col-form-label">{{ form.content.label }}:</label>
                            </div>
                            <div class="col-md-10">
                                {{ form.content }}
                                <div class="invalid-feedback"></div>
                            </div>
                        </div>
                    </div>
                    <div class="modal-footer">
                        <button type="submit" class="btn btn-primary btn-lg">Submit</button>
                        <button type="button" class="btn btn-secondary btn-lg" data-dismiss="modal">Close</button>
                    </div>
                </form>
            </div>
        </div>
    </div>

<script>
    $(function () {
        $("#contact_form").submit(function (e) {
            e.preventDefault();
            $('#btn_contact').text('Submitting...').prop('disabled', true); // 从提交按钮变为提交中...
            $('.invalid-feedback').remove(); //...并且删除所有可能的错误信息
            $.ajax({
                url: "{% url 'ajax_contact_us' %}",
                type: "POST",
                data: $('#contact_form').serialize(),
                dataType: "json",
                success: function (response) {
                    console.log(response);
                    $('#ContactModal').modal('hide'); // 关闭模态框
                    $('#btn_contact').text('Submitted').prop('disabled', false); //提交按钮重置
                    alert('Your message has been sent!'); // 发送完毕,提示用户信息已发送。
                },
                error: function (response) {
                    $('button[type="submit"]').text('Submit').prop('disabled', false); //还原提交按钮状态
                    console.log(response);
                    var errors = response.responseJSON.errors;
                    $.each(errors, function (key, value) {
                        $("#" + key).addClass("is-invalid").after("<div class='invalid-feedback'>" + value + "</div>");
                    });
                }
            });
        });
    });
</script>
{% endblock %}

视图函数:

# myapp/views.py
def ajax_contact_us(request):
    if request.method == 'POST' and request.is_ajax():
        form = ContactForm(request.POST)
        if form.is_valid():
            response = {
                'message': 'Your message has been sent!',
                'status': 'success'
            }
            return HttpResponse(json.dumps(response), content_type='application/json')
        else:
            response = {
                'status': 'error',
                'errors': json.loads(form.errors.as_json()),
            }
            return JsonResponse(response, status=400)

在模板中创建模态框,通过Ajax提交表单,并输出Json串。如果Ajax请求为非法请求,则返回状态码400以及错误信息。

3. 其他

form_valid_json() 内部使用的是 Django 内置的 JsonResponse 类。JsonResponse 类允许我们将 Python 对象(如字典)转换成 Json 的格式,并自动设置响应类型等元数据。当 JsonResponse 类接收到一个字典对象时,它默认使用 application/json 类型进行响应。

最后,需要注意的是,使用 form_valid_json() 函数前,我们需要确保表单数据已经通过有效性验证。这通常通过调用表单类的 is_valid() 方法实现。有效性验证确保了表单数据的准确性和安全性,避免了因数据不完整或者不合法造成的安全隐患。

本文链接:http://task.lmcjl.com/news/16153.html

展开阅读全文