Django 通过Ajax提交表单

urls.py

    # 任务管理
    path('task/list/', task.task_list),
    path('task/add/', task.task_add),

models.py

class Admin(models.Model):
    username = models.CharField(verbose_name='用户名', max_length=32)
    password = models.CharField(verbose_name='密码', max_length=64)

    def __str__(self):
        return self.username


class Task(models.Model):
    """ 任务 """
    leval_choices = (
        (1, '紧急'),
        (2, '重要'),
        (3, '临时'),
    )
    leval = models.SmallIntegerField(choices=leval_choices, default=1, verbose_name='级别')
    title = models.CharField(verbose_name='标题', max_length=64)
    detail = models.TextField(verbose_name='详细信息')
    user = models.ForeignKey(verbose_name='负责人', to='Admin', on_delete=models.CASCADE)

views.py

from django.shortcuts import render, HttpResponse, redirect
from django.http import JsonResponse
import json
# 免CSRF认证
from django.views.decorators.csrf import csrf_exempt
from django import forms
from sainfo import models


# 使用 forms.ModelForm 生成前端的 表单
class TaskModelForm(forms.ModelForm):
    class Meta:
        model = models.Task
        # 所有字段
        fields = "__all__"
        widgets = {
            # 'detail': forms.TextInput,
            'detail': forms.Textarea,
        }

    # 该方法是通过修改内部代码,对样式进行修改,样式的值可根据需求随意修改
    # 重新定义 init 方法
    def __init__(self, *args, **kwargs):
        # 重新定义 它 父类的 init 方法
        super().__init__(*args, **kwargs)
        # 循环ModelForm中的所有字段,给每个字段设置插件 field.widget.attrs
        for name, field in self.fields.items():
            print(name, field)
            # 判断,给某个字段不加插件
            # if name == 'password':
            #     continue
            # 字段的插件
            field.widget.attrs = {
                "class": "form-control",
                # "placeholder": field.label
            }


def task_list(request):
    """任务列表"""
    form = TaskModelForm()
    return render(request, 'task_list.html', {'form': form})


# 免csrf认证
@csrf_exempt
def task_add(request):
    if request.method == 'GET':
        print(request.GET)
    if request.method == 'POST':
        print(request.POST)

        # 1.前端提效数据需要进行校验(ModelForm进行校验)
        # 创建对象
        form = TaskModelForm(data=request.POST)
        if form.is_valid():     # 校验数据
            # 校验成功,保存到数据库
            form.save()
            # 返回数据到前端, 因为是Ajax提交,不能使用 return redirect(.....)
            # HttpResponse 返回前端数据字典,要使用 json.dumps()
            data_dict = {'status': '正常'}
            return HttpResponse(json.dumps(data_dict))
        else:
            # 验证失败 ,错误信息都在 创建的 form 对象里
            print(type(form.errors))    # <class 'django.forms.utils.ErrorDict'>
            print(form.errors)
            data_dict = {'status': '失败', 'error': form.errors}
            return HttpResponse(json.dumps(data_dict))

task_list.html

{% extends 'layout.html' %}
{% block content %}
    <div class="container">
        <div class="panel panel-default">
            <div class="panel-heading">表单</div>
            <div class="panel-body">

                <form id="formAdd" novalidate>
                {#    class="clearfix" 清除内部的浮动#}
                    <div class="clearfix">
                        {# form 是 views传过来的对象,也是ModelForm自动生成的html内容#}
                        {% for field in form %}
                            {#  栅格 #}
                            <div class="col-xs-6">
                                {#    position: relative 显示相对定位  #}
                                <div class="form-group" style="position: relative; margin-bottom: 20px">
                                    {#  filed.label 就是 字段的 verbose_name#}
                                    {#  field  是循环后得到的每一个字段的 input框#}
                                    <label>{{ field.label }}:</label>
                                    {{ field }}
                                    {#  position: absolute 显示绝对定位 漂浮在上面 #}
                                    {#  class="error-msg" 创建类,ajax 类选择器会使用 #}
                                    <span class="error-msg" style="color:red; position: absolute"></span>
                                </div>
                            </div>
                        {% endfor %}
                    </div>

                    <div class="col-xs-12">
                        <button type="reset" class="btn btn-primary btn-sm">
                            <span class="glyphicon glyphicon-remove-circle" aria-hidden="true"></span>
                            重置
                        </button>
                        {#    用Ajax提交表单,不能使用 type="submit" #}
                        <button id='btnAdd' type="button" class="btn btn-primary btn-sm" onclick="clickform()">
                            <span class="glyphicon glyphicon-ok-circle" aria-hidden="true"></span>
                            提交
                        </button>
                    </div>
                </form>
            </div>
        </div>
    </div>

{% endblock %}

{% block js %}

    <script>
        function clickform() {
            // ".error-msg"  类选择器,每次执行时先把 span 标签清空
            $(".error-msg").empty();

            $.ajax({
                url: '/task/add/',
                type: 'post',
                // 接收前端字典数据
                dataType: 'JSON',
                // serialize() 对选中的form表单内容进行序列化,返回给后端
                // 不用分别对每个input框使用 val() 取值
                data: $('#formAdd').serialize(),
                // res 接收的后端回传数据, 这里就是后端 json.dumps(data_dict)
                success: function (res) {
                    if (res.status === '正常') {
                        alert('数据添加成功');
                    } else {
                        console.log(res.error);
                        // {title: Array(1), detail: Array(1), user: Array(1)}
                        // each 遍历字典 在span标签输出错误信息
                        $.each(res.error, function (name, value) {
                            // value 的值是数组
                            console.log(name+'......'+value);
                            // 字符串拼接
                            // ModelForm 在生成 input 框时会自动增加 id_,格式是: id_属性名
                            // 比如这里的input框会自动生成: id="id_title",  id="id_detail", id="id_user"
                            // '#id_'+ name, 拼接字符串,并选中标签。 name是遍历的字典key.
                            // next() 选中当前标签的下一个标签,这里就是input标签的下一个是span标签
                            // text(value[0]), value是数组,取第0个元素,text()写入内容
                            $('#id_'+ name).next().text(value[0]);      // #id选择器
                        })
                    }
                }
            })
        }
    </script>

{% endblock %}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值