欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Django中的Form表单

程序员文章站 2022-04-25 16:30:23
...

方式1:

from django.shortcuts import render,HttpResponse,redirect
from django.views import View
from django.core import serializers
import json

# Create your views here.
# class LoginView(View):
#     def dispatch(self, request, *args, **kwargs):
#         print('before')
#         response = super(LoginView,self).dispatch(request,*args,**kwargs)
#         print('after')
#         return response
#
#     def get(self,request,*args,**kwargs):
#         print('GET')
#         return render(request,'login.html')
#
#     def post(self,request,*args,**kwargs):
#         print('POST')
#         user = request.POST.get('user')
#         pwd = request.POST.get('pwd')
#         if user == 'alex' and pwd == '123':
#             request.session['username'] = user
#             return redirect('/index/')
#         else:
#             return render(request,'login.html',{'msg':'登陆失败'})
#
# def auth(func):
#     def inner(request,*args,**kwargs):
#         user =  request.session.get('username')
#         if user:
#             return func(request,*args,**kwargs)
#         else:
#             return redirect('/login/')
#     return inner
#
#
# """
# 在Django的CBV里面引入装饰器需要用到固定的格式
# """
#
# from django.utils.decorators import method_decorator
#
# class IndexView(View):
#     """
#     继承View的原因:要用到as_view等方法
#     """
#     @method_decorator(auth) #这里相当于一个总闸门
#     def dispatch(self, request, *args, **kwargs):
#         response = super(IndexView, self).dispatch(request, *args, **kwargs)
#         return response
#
#
#     # @method_decorator(auth) => 可以直接放在这里加
#     def get(self,request,*args,**kwargs):
#         return HttpResponse(request.session['username'])
from app01 import  models

def users(request):
    return render(request,'users.html')


def get_users(request):
    """
    function:我们需要加上response指定标准
    """
    response = {'status':True,'data':None,'msg':None}
    try:
        user_list = models.UserInfo.objects.values('id','username')
        # user_list = list(user_list),如果正确,则将user_list的数值赋值给data
        response['data'] = list(user_list)
    except Exception as e:
        response['status'] = False
        response['msg'] = str(e)

    data = json.dumps(response)
    return HttpResponse(data)




from django.forms import Form
from django.forms import fields
from django.forms import widgets


class UserForm(Form):
    #通过这个类可以帮我们生成相应的html标签
    user = fields.CharField(required=True)
    email = fields.EmailField(required=True)
    user_type = fields.ChoiceField(choices=[(1,'上海'),(2,'北京',),(3,'广州')])


class AddUserView(View):
    def get(self,request,*args,**kwargs):
        form = UserForm()
        return render(request,'add_user.html',{'form':form})

    def post(self,request,*args,**kwargs):
        form = UserForm(data=request.POST)
        #将用户提交的数据和UserForm中定义的规则进行匹配
        if form.is_valid():
            # 如果用户提交的数据正确,则获取用户所有的数据
            print(form.cleaned_data)
            return redirect('/xxxx.html')
        else:
            #显示相应的错误信息
            print(form.errors)
            # 此时前端自动将错误信息给显示出来了
            return render(request,'add_user.html',{"form":form})

前端页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>添加用户</h1>
    <form method="POST" novalidate>
        {% csrf_token %}
        {{ form.as_p }}
        <input type="submit" value="提交">
    </form>
</body>
</html>

运行结果:
Django中的Form表单
问题:form.as_p不能够定制,虽然通过form.as_p可以生成form中所有的html标签,但是不能够定制,也不能够样式渲染。

   def as_p(self):
       "Returns this form rendered as HTML <p>s."
       return self._html_output(
           normal_row='<p%(html_class_attr)s>%(label)s %(field)s%(help_text)s</p>',
           error_row='%s',
           row_ender='</p>',
           help_text_html=' <span class="helptext">%s</span>',
           errors_on_separate_row=True)

改进1:(后端不做任何的改进,仅仅前端做改进)

<body>
    <h1>添加用户</h1>
    <form method="POST" novalidate>
        {% csrf_token %}
        {#  用户自定制相应的内容,form.errors.user实际上包含了很多的错误信息 #}
        <p>用户名:{{ form.user }}{{ form.errors.user }}</p>
        <p>邮箱:{{ form.email }}{{ form.errors.email.0 }}</p>
        <p>用户类型:{{ form.user_type }}{{ form.errors.user_type.0 }}</p>
        <input type="submit" value="提交">
    </form>
</body>

效果展示:
Django中的Form表单
改进2:将错误的提示信息用中文显示出来。
后台:

from django.shortcuts import render,HttpResponse,redirect
from django.views import View
from django.core import serializers
import json

# Create your views here.
# class LoginView(View):
#     def dispatch(self, request, *args, **kwargs):
#         print('before')
#         response = super(LoginView,self).dispatch(request,*args,**kwargs)
#         print('after')
#         return response
#
#     def get(self,request,*args,**kwargs):
#         print('GET')
#         return render(request,'login.html')
#
#     def post(self,request,*args,**kwargs):
#         print('POST')
#         user = request.POST.get('user')
#         pwd = request.POST.get('pwd')
#         if user == 'alex' and pwd == '123':
#             request.session['username'] = user
#             return redirect('/index/')
#         else:
#             return render(request,'login.html',{'msg':'登陆失败'})
#
# def auth(func):
#     def inner(request,*args,**kwargs):
#         user =  request.session.get('username')
#         if user:
#             return func(request,*args,**kwargs)
#         else:
#             return redirect('/login/')
#     return inner
#
#
# """
# 在Django的CBV里面引入装饰器需要用到固定的格式
# """
#
# from django.utils.decorators import method_decorator
#
# class IndexView(View):
#     """
#     继承View的原因:要用到as_view等方法
#     """
#     @method_decorator(auth) #这里相当于一个总闸门
#     def dispatch(self, request, *args, **kwargs):
#         response = super(IndexView, self).dispatch(request, *args, **kwargs)
#         return response
#
#
#     # @method_decorator(auth) => 可以直接放在这里加
#     def get(self,request,*args,**kwargs):
#         return HttpResponse(request.session['username'])
from app01 import  models

def users(request):
    return render(request,'users.html')


def get_users(request):
    """
    function:我们需要加上response指定标准
    """
    response = {'status':True,'data':None,'msg':None}
    try:
        user_list = models.UserInfo.objects.values('id','username')
        # user_list = list(user_list),如果正确,则将user_list的数值赋值给data
        response['data'] = list(user_list)
    except Exception as e:
        response['status'] = False
        response['msg'] = str(e)

    data = json.dumps(response)
    return HttpResponse(data)




from django.forms import Form
from django.forms import fields
from django.forms import widgets


class UserForm(Form):
    #通过这个类可以帮我们生成相应的html标签
    user = fields.CharField(
        required=True,
        #自定义错误信息
        error_messages={'required':'用户名不能为空'}
    )
    email = fields.EmailField(
        required=True,
        #自定义错误信息
        error_messages={'required':'邮箱不能为空','invalid':'邮箱格式错误'}
    )
    ip  = fields.GenericIPAddressField(
        required=True,
        # 自定义错误信息
        error_messages={'required': 'IP不能为空', 'invalid': 'IP格式错误'}
    )
    user_type = fields.ChoiceField(choices=[(1,'上海'),(2,'北京',),(3,'广州')])


class AddUserView(View):
    def get(self,request,*args,**kwargs):
        #创建的类对象自动具有user、email和user_type三个属性
        form = UserForm()
        return render(request,'add_user.html',{'form':form})

    def post(self,request,*args,**kwargs):
        form = UserForm(data=request.POST)
        #将用户提交的数据和UserForm中定义的规则进行匹配
        if form.is_valid():
            # 如果用户提交的数据正确,则获取用户所有的数据
            print(form.cleaned_data)
            #{'user': 'fds', 'user_type': '1', 'email': 'aaa@qq.com', 'ip': '192.168.80.100'}
            return redirect('/xxxx.html')
        else:
            #显示相应的错误信息
            print(form.errors)
            # 此时前端自动将错误信息给显示出来了
            return render(request,'add_user.html',{"form":form})

前端:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>添加用户</h1>
    <form method="POST" novalidate>
        {% csrf_token %}
        {#  用户自定制相应的内容,form.errors.user实际上包含了很多的错误信息 #}
        <p>用户名:{{ form.user }}{{ form.errors.user }}</p>
        <p>邮箱:{{ form.email }}{{ form.errors.email.0 }}</p>
        <p>IP:{{ form.ip }}{{ form.errors.ip.0 }}</p>
        <p>用户类型:{{ form.user_type }}{{ form.errors.user_type.0 }}</p>
        <input type="submit" value="提交">
    </form>
</body>
</html>

效果展示:
Django中的Form表单
到现在为止,我们在加入一个编辑的功能:
Django中的Form表单
Django中的Form表单
Django中的Form表单
Django中的Form表单
但是到现在为止还是有一个bug,这个bug就是当我的用户类型增加之后,在添加当中还是只显示以前的两个类型,只有通过重启之后才可以看到最新的类型:
解决方法:

class UserForm(Form):
    def __init__(self,*args,**kwargs):
        super(UserForm,self).__init__(*args,**kwargs)
        self.fields['ut_id'].choices = \
            models.UserType.objects.values_list('id','title')

    #通过这个类可以帮我们生成相应的html标签
    #字段名应该和数据库的名字一致
    #静态字段加载的时候只有在第一次才会执行
    username = fields.CharField(
        required=True,
        #自定义错误信息
        error_messages={'required':'用户名不能为空'}
    )
    password = fields.EmailField(
        required=True,
        #自定义错误信息
        error_messages={'required':'密码不能为空','invalid':'密码格式错误'}
    )

    # user_type = fields.ChoiceField(choices=[(1,'上海'),(2,'北京',),(3,'广州')])
    ut_id = fields.ChoiceField(choices=models.UserType.objects.values_list('id','title'))

总结:4个步骤1个问题

        总结:
            1. 创建Form类(本质就是正则表达式的集合)


            2. 只是生成HTML标签: 添加页面
                form = MyForm()

                {{form.xx}}

            3. 带默认值的HTML标签: 编辑页面
                form = MyForm(initial={'xx': xxx})

                {{form.xx}}

            4. 提交数据
                form = MyForm(data=request.POST)

                if form.is_valid():
                    print(form.cleaned_data)
                else:
                    print(form.errors)

            问题:下拉框数据无法实时更新
                class UserForm(Form):
                    username = fields.CharField(
                        required=True,
                        error_messages={'required':'用户名不能为空'}
                    )
                    password = fields.CharField(
                        required=True,
                        error_messages={'required': '邮箱不能为空','invalid':'邮箱格式错误'}
                    )

                    ut_id = fields.ChoiceField(choices=[])

                    def __init__(self,*args,**kwargs):
                        super(UserForm,self).__init__(*args,**kwargs)

                        self.fields['ut_id'].choices = models.UserType.objects.values_list('id','title')

到现在为止,我们可以进行一对一,一对多的操作了,我们此时如何进行input的定制操作呢?
下面是不能进行class等修饰的

<form method="POST" novalidate>
    {% csrf_token %}
    {#  编辑的时候应该有默认值  #}
    <p>用户名:{{ form.username }}{{ form.errors.username.0 }}</p>
    <p>邮箱:{{ form.password }}{{ form.errors.password.0 }}</p>
    <p>用户类型:{{ form.ut_id }}{{ form.errors.ut_id.0 }}</p>
    <p>用户角色:{{ form.role_id }}{{ form.errors.role_id.0 }}</p>
    <input type="submit" value="提交">
</form>

通过下面我们就可以将form表单嵌套在bootStrap当中:

class UserForm(Form):
    def __init__(self,*args,**kwargs):
        super(UserForm,self).__init__(*args,**kwargs)
        self.fields['ut_id'].choices = \
            models.UserType.objects.values_list('id','title')
        self.fields['role_id'].choices =\
            models.Role.objects.values_list('id','caption')
    #通过这个类可以帮我们生成相应的html标签
    #字段名应该和数据库的名字一致
    #静态字段加载的时候只有在第一次才会执行
    username = fields.CharField(
        required=True,
        #自定义错误信息
        error_messages={'required':'用户名不能为空'},
        widget=widgets.TextInput(attrs={'class':'form-control'})
    )
    password = fields.EmailField(
        required=True,
        #自定义错误信息
        error_messages={'required':'密码不能为空','invalid':'密码格式错误'},
        widget = widgets.Textarea(attrs={'class': 'form-control'})
    )
    # fields.EmailField()
    # fields.GenericIPAddressField(protocol='ipv4')
    # user_type = fields.ChoiceField(choices=[(1,'上海'),(2,'北京',),(3,'广州')])
    ut_id = fields.ChoiceField(
        choices=[],
        widget=widgets.Select(attrs={'class':'form-control'})
    )

    role_id = fields.MultipleChoiceField(
        choices=[],
        widget=widgets.SelectMultiple(attrs={'class': 'form-control'})
                                         )

综上我们的Form表单实际上有很多的功能,但是下面我们只使用Form表单验证的功能。
示例:只用表单验证的功能(Ajax提交)
Django中的Form表单