python自动化开发-[第二十天]-form表单,CBV和FBV,序列化

本文详细介绍了Django中的两种视图处理方式:基于类的视图(CBV)和基于函数的视图(FBV),并通过具体示例展示了如何使用这两种方式实现登录认证、表单验证等功能。

1、CBV和FBV的用法

2、序列化用法

3、form表单

一、CBV和FBV

  1、cbv是 class based view(基于类),fbv是function based view(基于函数)

  2、cbv基于dispatch进行反射,get获取,post提交

  3、应用场景:登录认证(继承dispatch,在dispatch里做session验证)

   CBV第一种方式继承

  1、单继承

     扫盲:(继承的时候,一定要清楚self是哪个类实例化出来的对象,下例,self为B实例化的对象,任何属性优先从自己里面找,找不到在去父类里找)

class A(object):
    def aaa(self):
        print('from A')
    def bbb(self):
        self.aaa()

class B(A):
    def aaa(self):
        print('from B')

c = B()
c.aaa()

  

from django.views import View
class BaseView(View):
    def dispatch(self, request, *args, **kwargs):  # 继承父类的dispatch,因为父类里有返回值,所以也要有return
        if request.session.get('username'):
            response = super(BaseView, self).dispatch(request, *args, **kwargs)
            return response
        else:
            return redirect('/login.html')

class IndexView(BaseView):

    def get(self, request, *args, **kwargs):
        return HttpResponse(request.session['username'])

  2、多继承(继承顺序从左到右)

class BaseView(object):
    def dispatch(self, request, *args, **kwargs):
        if request.session.get('username'):
            response = super(BaseView,self).dispatch(request, *args, **kwargs)
            return response
        else:
            return redirect('/login.html')

class IndexView(BaseView,View):#先去找BaseView,BaseView中未定义在去找View

    def get(self,request,*args,**kwargs):
        return HttpResponse(request.session['username'])

  CBV第二种方式装饰器

from django.utils.decorators import method_decorator

def auth(func): #定义装饰器
    def inner(request,*args,**kwargs):
        if request.session.get('username'):
            obj = func(request,*args,**kwargs)
            return obj
        else:
            return redirect('/login.html')
    return inner

@method_decorator(auth,name='get')  #放在类顶部就需要method_decorator这个装饰器
class IndexView(View):

    @method_decorator(auth) #放在dispatch上就相当于全局都需要经过认证
    def dispatch(self, request, *args, **kwargs):
        if request.session.get('username'):
            response = super(IndexView,self).dispatch(request, *args, **kwargs)
            return response
        else:
            return redirect('/login.html')

    @method_decorator(auth)
    def get(self,request,*args,**kwargs):
        return HttpResponse(request.session['username'])

    @method_decorator(csrf_exempt)  # 无效 csrf 放到post函数上的装饰器,是无效的,需要放到dispath上或者类上
    def post(self,request,*args,**kwargs):
        return HttpResponse(request.session['username'])

  特殊csrf

特殊:CSRF
	class IndexView(View):
	
		@method_decorator(csrf_exempt) #不能放属性上,只能放在全局
		def dispatch(self, request, *args, **kwargs):
			return super(LoginView,self).dispatch(request, *args, **kwargs)


		def get(self,request,*args,**kwargs):
			return HttpResponse(request.session['username'])
			
		
		def post(self,request,*args,**kwargs):
			return HttpResponse(request.session['username'])

 二、序列化

  方式一 serialize,可以序列化对象

user_list = models.UserInfo.objects.all()
data = serializers.serialize("json", user_list)
[
	{"model": "app01.userinfo", "pk": 1, "fields": {"username": "\u5174\u666e", "password": "123123"}}, 
	{"model": "app01.userinfo", "pk": 2, "fields": {"username": "\u94f6\u79cb\u826f", "password": "666"}}
]

  方式二 json dumps(只能序列化python支持的数据类型)

user_list = models.UserInfo.objects.values('id','username')
user_list = list(user_list)
data = json.dumps(user_list)
[
	{"username": "\u5174\u666e", "id": 1}, 
	{"username": "\u94f6\u79cb\u826f", "id": 2}
]

  json dumps不能序列化时间,通过自定义来支持序列化时间

import json
from datetime import date
from datetime import datetime

class JsonCustomEncoder(json.JSONEncoder):
	def default(self, field):
		if isinstance(field, datetime):
			return field.strftime('%Y-%m-%d %H:%M:%S')
		elif isinstance(field, date):
			return field.strftime('%Y-%m-%d')
		else:
			return json.JSONEncoder.default(self, field)


user_list = [
	{'id':1,'name':'alex','ctime': datetime.now()},
	{'id':2,'name':'eric','ctime': datetime.now()}
]

data = json.dumps(user_list,cls=JsonCustomEncoder)
print(data)


'''
[{"ctime": "2017-09-15 06:47:53", "id": 1, "name": "alex"}, {"ctime": "2017-09-15 06:47:53", "id": 2, "name": "eric"}]

'''

 三、Form表单验证

  1、form表单的功能

      表单验证和生成表单

  示例:用户管理
    a. 添加用户页面
      - 显示HTML标签
      - 提交:数据验证
      - 成功之后保存
      - 错误显示错误信息

  创建Form类(本质就是正则表达式的集合) 

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

class UserForm(Form):
	username = fields.CharField(
		required=True, #默认就为true,可以不填
		error_messages={'required':'用户名不能为空'}, #自定义错误信息
		widget=widgets.TextInput(attrs={'class':'form-control'}) #额外自定义样式
	)
	password = fields.CharField(
		required=True,
		error_messages={'required': '邮箱不能为空','invalid':'邮箱格式错误'}, #邮箱的错误提示需要写在invalid里
		widget = widgets.TextInput(attrs={'class': 'form-control'})
	)
	# fields.EmailField()
	# fields.GenericIPAddressField(protocol='ipv4')

	ut_id = fields.ChoiceField( #单选和多选会有个下拉框内容填充的问题,默认类的属性只加载一次,需要通过构造方法,使得每次调用都更新一次
		choices=[],
		widget=widgets.Select(attrs={'class':'form-control'})
	)

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

	def __init__(self,*args,**kwargs):
		super(UserForm,self).__init__(*args,**kwargs)
		# self.fields已经有所有拷贝的字段
		self.fields['ut_id'].choices = models.UserType.objects.values_list('id','title')
		self.fields['role_id'].choices = models.Role.objects.values_list('id','caption')

 例子添加用户:

view里 

from django.forms import Form,fields,widgets
class UserForm(Form):
    '''用户表单'''
    username = fields.CharField(required=True,error_messages={'required':'用户名不能为空'})

    password = fields.CharField(required=True,error_messages={'required':'密码不能为空'})

    # ip = fields.GenericIPAddressField(required=True,error_messages={'required':'IP不能为空','invalid':'IP格式错误'})

    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')

 

class AddUserView(AuthView,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(request.POST) 
        if form.is_valid():
            print(form.cleaned_data)
            models.UserInfo.objects.create(**form.cleaned_data)
            return redirect('/users.html')
        else:
            print(form.errors)
            return render(request,'add_user.html',{"form":form})

 tempelate:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>添加用户</h1>
    <form method="POST" novalidate>
        {% csrf_token %}
        <p>
            用户名: {{ form.username }} {{ form.errors.username.0 }}
        </p>
        <p>
            密码: {{ form.password }}  {{ form.errors.password.0 }}
        </p>
{#        <p>#}
{#            ip: {{ form.ip }}  {{ form.errors.ip.0 }}#}
{#        </p>#}
        <p>
            用户类型: {{ form.ut_id }} {{ form.errors.ut_id.0 }}
        </p>
        <input type="submit" value="提交">
    </form>
</body>
</html>

   知识点:form(request.POST),将request内的数据传递给from表单,form表单会进行正则验证,通过obj.is_valid(), 如果正常, 返回值就是obj.cleaned_data,如果出现异常,异常信息会以字典形式存放在obj.errors 。一个输入框多条错误信息 一般只取第一条错误信息,处理完这一条在去处理其他

带默认值的添加标签:

  

class EditUserView(AuthView,View):
    def get(self,request,pk):
        obj = models.UserInfo.objects.filter(id=pk).first()
        role_id_list = obj.rl.values_list('id')
        v = list(zip(*role_id_list))[0] if role_id_list else []
        form = UserForm(initial={'username': obj.username, 'password': obj.password, 'ut_id': obj.ut_id,'role_id':v})
        return render(request,'edit_user.html',{'form':form})

    def post(self,request,pk):
        form = UserForm(data=request.POST)
        if form.is_valid():
            # # {'username': 'xxxxx', 'password': 'xxxxx', 'ut_id': '1',role_id:}
            role_id = form.cleaned_data.pop('role_id')
            # 用户表更新
            query = models.UserInfo.objects.filter(id=pk)
            query.update(**form.cleaned_data)
            obj = query.first()
            obj.rl.set(role_id)

            return redirect('/users.html')
        else:
            print(form.errors)
            return render(request, 'edit_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 %}
        <p>
            用户名: {{ form.username }} {{ form.errors.username.0 }}
        </p>
        <p>
            密码: {{ form.password }}  {{ form.errors.password.0 }}
        </p>
{#        <p>#}
{#            ip: {{ form.ip }}  {{ form.errors.ip.0 }}#}
{#        </p>#}
        <p>
            用户类型: {{ form.ut_id }} {{ form.errors.ut_id.0 }}
        </p>
        <input type="submit" value="提交">
    </form>
</body>
</html>

 

通过ajax+form表单验证,实现注册功能

  view:

class RegisterForm(Form):
    user = fields.CharField(required=True,min_length=6,max_length=18)
    email = fields.EmailField(required=True,min_length=6,max_length=18)
    password = fields.CharField(min_length=12)
import json

def register(request):
    if request.method == 'GET':
        form = RegisterForm()
        return render(request,'register.html',{'form':form})
    else:
        response = {'status': True,'data': None,'msg':None}
        form = RegisterForm(request.POST)
        if form.is_valid():
            print(form.cleaned_data)
            # 数据库中添加一条数据
            # return redirect('/login.html') # ajax跳转,错错错
        else:
            response['status'] = False
            response['msg'] = form.errors
        return HttpResponse(json.dumps(response))

 tempelate

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form id="f1">
        {% csrf_token %}
        <p>用户名:{{ form.user }}</p>
        <p>密码:{{ form.password }}</p>
        <p>邮箱:{{ form.email }}</p>
        <input type="button" value="提交" onclick="submitForm();" />
    </form>
    <script src="/static/jquery-3.2.1.js"></script>
    <script>
        function submitForm() {
            $('#f1 .error').remove();

            $.ajax({
                url: '/register.html',
                type: 'POST',
                data: $('#f1').serialize(),
                dataType: 'JSON',
                success:function (arg) {
                    if(arg.status){
                        location.href = "/login.html";
                    }else{
                        /*
                        arg.msg = {
                            email: ['xxxxx',]
                            password: ['xxxxx',]
                            user: ['xxxxx',]
                        }
                         */
                        $.each(arg.msg,function (k,v) {
                            var tag = document.createElement('span');
                            tag.innerHTML = v[0];
                            tag.className = "error";
                            // <span class='error'>v[0]</span>
                            $('#f1 input[name="'+k+'"]').after(tag);
                        })
                    }
                }
            })
        }
    </script>

</body>
</html>

转载于:https://www.cnblogs.com/liujiliang/p/7513102.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值