Django进阶

Form表单认证

作用:

  - 验证用户提交的数据
  - 生成HTML标签

在实际的生产环境中比如登录和验证的时候,我们一般都使用Jquery+ajax来判断用户的输入是否为空,假如JS被禁用的话,咱们这个认证屏障是不是就消失了呢?(虽然一般不会禁用掉但是还是存在风险)。所以我们一般做两种认证一种是前端做一遍认证,在后端做一遍认证。

#/usr/bin/env python
#-*- coding:utf-8 -*-
from django.shortcuts import render

# Create your views here.


def user_list(request):
host = request.POST.get('host')
port = request.POST.get('port')
mail = request.POST.get('mail')
mobile = request.POST.get('mobile')
#这里有个问题,如果,这个from表单有20个input,你在这里是不是的取20次?

#验证:
#输入不能为空,并且有的可以为空有的不可以为空
#如果email = 11123123 这样合法吗?
#如果mobile = 11123123 这样合法吗?
#如果ip = 11123123 这样合法吗?
'''
你在这里是不是需要做一大堆的输入验证啊?并且有很多这种页面会存在这种情况,如果每个函数都这样做估计就累死了
'''
return render(request,'user_list.html')

用form就可以解决这个问题,其他语言也叫作模型绑定。

from django import forms
import re
#自定义正则来增加判断规则
def mobile_validate(value):
    mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
    if not mobile_re.match(value):
        raise ValidationError('手机号码格式错误')

class LoginForm(forms.Form):
    user = forms.CharField(required=True, error_messages={'required': '用户名不能为空.'})
    pwd = forms.CharField(required=True,
                          min_length=6,
                          max_length=10,
                          error_messages={'required': '密码不能为空.', 'min_length': "至少6位"})

    num = forms.IntegerField(error_messages={'required': '数字不能空.','invalid': '必须输入数字'})

  #上面函数中的规则
    phone = forms.CharField(validators=[mobile_validate, ],)
    test_choices = (
        (0, '上海'),
        (1, '背景'),
    )
    test = forms.IntegerField(widget=forms.Select(choices=test_choices))

def login(request):
    if request.POST:
        objPost = LoginForm(request.POST)
        ret = objPost.is_valid()   #判断用户的输入是否合法
        if ret:
            print(objPost.clean())
        else:
            from django.forms.utils import ErrorDict
            print('aaaaaaaaaaaaaaaaaaaa')
        return render(request, 'login.html',{'obj1': objPost})
    else:
        objGet = LoginForm()
        return render(request, 'login.html',{'obj1': objGet})
login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .error-msg{
            color: red;
        }
    </style>
</head>
<body>
    <form action="/login/" method="POST">
        <div>
            <div>
               {{ obj1.user }}
                {% if  obj1.errors.user %}
                    <span class="error-msg">{{ obj1.errors.user.0 }}</span>
                {% endif %}
            </div>
            <div>
                {{ obj1.pwd }}
                <span class="error-msg">{{ obj1.errors.pwd.0 }}</span>
            </div>
            <div>
                {{ obj1.num }}
                <span class="error-msg">{{ obj1.errors.num.0 }}</span>
            </div>
            <div>
                {{ obj1.phone }}
                <span class="error-msg">{{ obj1.errors.phone.0 }}</span>
            </div>
            <div>
                {{ obj1.test }}
                <span class="error-msg">{{ obj1.errors.test.0 }}</span>
            </div>
            <input type="submit" value="提交" />
        </div>
    </form>
</body>
</html>

效果:

跨站请求伪造

一、简介

django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。

全局:

  中间件 django.middleware.csrf.CsrfViewMiddleware

局部:

  • @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
  • @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

注:from django.views.decorators.csrf import csrf_exempt,csrf_protect

二、应用

1、普通表单

2、Ajax

对于传统的form,可以通过表单的方式将token再次发送到服务端,而对于ajax的话,使用如下方式。

view.py

text.html

 

Session&Cookie

Cookie就是一段字符串,保存于本机电脑上。

session 保存于服务器,用来保存用户的会话信息,依赖于Cookies

1、流程

举个例子,咱们在登录一个网站后,拿JD举例,如果我登录进去之后,在想点击订单的时候。server断怎么判断我是“我”,而不是其他人呢?

Http是短连接,那么Server端肯定有一个保存我登录状态的地方(session),那server怎么判断是我发送过来的请求呢?就是通过Cookie!

当客户端访问过来后,server端会在IE里生成一个Cookie,当访问过来的时候就可以通过Cookie进行判断

2、结构

1、自动生成一段字符串

2、将字符串发送到客户端的浏览器,同时把字符串当做key放在session里。(可以理解为session就是一个字典)

3、在用户的session对应的value里设置任意值

3、操作

3.1、操作session

  • 获取session:request.session[key]
  • 设置session:reqeust.session[key] = value
  • 删除session:del request[key]
request.session.set_expiry(value)
* 如果value是个整数,session会在些秒数后失效。
* 如果value是个datatime或timedelta,session就会在这个时间后失效。
* 如果value是0,用户关闭浏览器session就会失效。
* 如果value是None,session会依赖全局session失效策略。

实例:

复制代码
def login(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        if username == 'shuai' and password == '123':
            result = request.session.get('IS_LOGIN', None)
            print result
            request.session['IS_LOGIN'] = True
            return redirect('/index/')
    obj = forms.LoginForm()
    # 如果登录成功,写入session,跳转index
    return render(request, 'account/login.html', {'model': obj})


def index(request):
    '''
    如果用户已经登录
    '''
    is_login = request.session.get('IS_LOGIN',False)
    if is_login:
        return render(request, 'home/index.html')
    else:
        return redirect('/login/')
复制代码

注:这里需要注意在session中,我们可以设置多个key:value的值,方便我们做很多事情,比如判断哪个用户:

  如果用户登录后,那么他肯定有一个cookie那么他在访问购物车的时候,怎么判断是哪个用户呢?我们可以在session设置,当用户登录的时候,我们把的用户名,增加到session中,那么用户携带cookie访问的时候,我们就能判断是哪个一用来访问的!

比如下面的对应关系:

user1

cookie :aaaa 

server session(举例格式)

{session:aaaa{'IS_LOGIN':'True',username:'shuaige'}}

 4、Session和Cookie好处

使用Session和Cookie的好处:Cookie可以理解为一个身份证ID,你只能拿着他去和Server端进行通信,如果你没有这个ID那么server端也不知道你是谁!

实例:(0 0 !)

我在写博客的时候在做Cookie和Session的实验,把Cookie删掉了!当我保存的时候直接给我提出来了,为什么呢?就是因为,server端不知道我是谁了,我已经没有密钥了。

 

所以,只要Session和Cookie任意一方失效,就可以理解为:

Cookie失效就相当于身份证ID过期,需要重新认证才可以继续使用。Session失效就相当于银行里的数据标识此ID无效,也需要重新申请。'

实例:

views.py

USER_LIST = ['abc','def']
def session_login(request):
    if request.method == 'POST':
        u = request.POST.get('user')
        p = request.POST.get('pwd')
        if p == '123' and u in USER_LIST:
            request.session['user'] = u
            return redirect('/session_index/')
    return render(request,'session_login.html')


def session_index(request):
    user = request.session.get('user',None)
    return render(request,'session_index.html',{'user':user})


session_login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <form action="/session_login/"  method="POST">
        <input type="text" name="user">
        <input type="text" name="pwd">
        <input type="submit" value="提交" />
    </form>
</body>
</html>
session_index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>欢迎:{{ user }}登录</h1>

    <a href="/session_logout/">注销</a>
</body>
</html>

效果:

model操作

a. 基本操作
b. 进阶
c. 双下滑线
__ 大小于操作
__ 可以跨表

class UserInfo(models.Model):

user = models.CharField(max_length=32)
pwd = models.CharField(max_length=32)

queryset = UserInfo.objects.all() 
【UserInfo对象,UserInfo对象,UserInfo对象,】
print(queryset.query) -- 查看UserInfo.objects.all() 的SQL语句

queryset = UserInfo.objects.all().values('user')
【{‘user’: 'alex'},{‘user’: 'eirc'}】

queryset = UserInfo.objects.all().value_list('user')
【('alex'),('eirc')】

=======================
一对多
class UserType(models.Model):
catption = models.CharField(max_length=32)
# 超级管理员,普通用户,游客,黑河

class UserInfo(models.Model):

user = models.CharField(max_length=32)
pwd = models.CharField(max_length=32)
user_type = models.ForignKey('UserType')
# user_type_id

# 创建UserInfo
1、 UserInfo.objects.create(user='alex',pwd='123',user_type=UserType.objects.get(id=2)) 
2、 UserInfo.objects.create(user='alex',pwd='123',user_type_id=2)

# 查询:
UserInfo.objects.filter(user='alex')
1、查询所有用户类型等于 普通用户 的所有用户名和密码
uid = UserType.objects.get(caption='普通用户').id 
UserInfo.objects.filter(user_type_id=uid)

querset = UserInfo.objects.filter(user_type__caption='普通用户')
querset = UserInfo.objects.filter(user_type__id__gt=2)
【UserInfo对象,UserInfo对象,UserInfo对象,】
row = querset[0]
row.user
row.pwd
row.user_type.id
row.user_type.caption
###### objects __
###### row.外键字段.外键表的字段

querset = UserInfo.objects.filter(user_type__caption='普通用户').values('user','user_type__caption')
【{'user': 'alex','user_type__caption': '普通用户'},{'user': 'eric','user_type__caption': '普通用户'},】
row = querset[0]
row['user']
row['user_type__caption']

2、三张表跨表操作
class Somthing(models.Model):
name = models.CharField(max_length=32)

class UserType(models.Model):
catption = models.CharField(max_length=32)
s = models.ForignKey('Somthing')

# 超级管理员,普通用户,游客,黑河

class UserInfo(models.Model):

user = models.CharField(max_length=32)
pwd = models.CharField(max_length=32)
user_type = models.ForignKey('UserType')

UserInfo.objects.filter(user_type__s__name='xx')

model多对多操作
- 创建
a. 方式一:
class B2G(models.Model):
b_id = models.ForeignKey('Boy')
g_id = models.ForeignKey('Girl')

class Boy(models.Model):

username = models.CharField(max_length=16)

class Girl(models.Model):

name = models.CharField(max_length=16)

b. 方式二:
class Boy(models.Model):

username = models.CharField(max_length=16)
# girl_set
class Girl(models.Model):

name = models.CharField(max_length=16)

b = models.ManyToManyField('Boy')


- 操作:
添加:
正向
g1 = models.Girl.objects.get(id=1)

g1.b.add(models.Boy.objects.get(id=1))
g1.b.add(1)

bs = models.Boy.objects.all()
g1.b.add(*bs)
g1.b.add(*[1,2,3])

反向
b1 = models.Boy.objects.get(id=1)
b1.girl_set.add(1)
b1.girl_set.add(models.Girl.objects.all())

b1.girl_set.add(*[1,2,3,4])
...
删除:
g1 = models.Girl.objects.get(id=1)
g1.b.clear() # 清空和girl ID=1所关联的所有数据

g1.b.remove(2) 
g1.b.remove(*[1,2])

查询:
g1 = models.Girl.objects.get(id=1) # SQL
g1.b.all()	# SQL
g1.b.filter().count()

b1 = models.Boy.objects.get(id=1)
b1.girl_set.all()

models.Girl.objects.all().values('id','name', 'b__username')
models.Boy.objects.all().values('id','username', 'girl__name')
更新:
ORM:
python操作数据库模块:
MySQLdb
pymysql

原生SQL
# from django.db import connection
# cursor = connection.cursor()
# cursor.execute("""SELECT * from tb where name = %s""", ['Lennon'])
# row = cursor.fetchone()

 

model操作 F/Q

F:
temp = salary+500
models.UserInfo.objects.filter().update(salary=temp)
update userinfo set salary=salary+500 

from django.db.models import F
models.UserInfo.objects.filter().update(salary=F('salary')+500)

Q:
构造搜索条件
1、传参
models.UserInfo.objects.filter(id=123,name='alex')

2、传字典
d = {'id': 123, 'name':'alex'}
models.UserInfo.objects.filter(**d)

<input name='id' />
<input name='name' />
获取用户输入,并构造成字典:
models.UserInfo.objects.filter(**c)
3、传Q对象
models.UserInfo.objects.filter(Q对象)

from django.db.models import Q

# q1 = Q()
# q1.connector = 'OR'
# q1.children.append(('id', 1))
# q1.children.append(('id', 2))
# q1.children.append(('id', 3))

# models.Tb1.objects.filter(q1)


# con = Q()
#
# q1 = Q()
# q1.connector = 'OR'
# q1.children.append(('id', 1))
# q1.children.append(('id', 2))
# q1.children.append(('id', 3))
#
# q2 = Q()
# q2.connector = 'OR'
# q2.children.append(('status', '在线'))
#
# con.add(q1, 'AND')
# con.add(q2, 'AND')
#
# models.Tb1.objects.filter(con)

实例:

models.py

from django.db import models

# Create your models here.


class UserType(models.Model):
     caption = models.CharField(max_length=32)

views.py
from django.shortcuts import render,HttpResponse

# Create your views here.

from app01 import models
from django import forms


class indexForm(forms.Form):

    c = models.UserType.objects.all().values_list('id','caption')
    user_type_id = forms.IntegerField(widget=forms.Select(choices=c))

    def __init__(self, *args, **kwargs):
        super(indexForm, self).__init__(*args,**kwargs)
        self.fields['user_type_id'].widget.choices = models.UserType.objects.all().values_list('id','caption')

def index(request):
    # for i in range(10):
    #     models.UserType.objects.create(caption='CE' + str(i))
    form = indexForm()
    from django.db.models import Q

    # q1 = Q()
    # q1.connector = 'OR'
    # q1.children.append(('id', 1))
    # q1.children.append(('id', 2))
    # q1.children.append(('id', 3))
    # obj = models.UserType.objects.filter(q1)
    # for item in obj:
    #     print(item.id,item.caption)

    con = Q()

    q1 = Q()
    q1.connector = 'OR'
    q1.children.append(('id', 1))
    q1.children.append(('id', 2))
    q1.children.append(('id', 3))


    q2 = Q()
    q2.connector = 'OR'
    q2.children.append(('caption', 'CE1'))
    q2.children.append(('caption', 'CE2'))

    con.add(q1, 'AND')
    con.add(q2, 'AND')

    obj = models.UserType.objects.filter(con)
    for item in obj:
        print(item.id,item.caption)


    return render(request, 'index.html',{'form':form})

index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
        <h1>ABC</h1>
        {{ form }}
</body>
</html>

效果:

 

缓存

由于Django是动态网站,所有每次请求均会去数据进行相应的操作,当程序访问量大时,耗时必然会更加明显,最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者memcache中,5分钟内再有人来访问时,则不再去执行view中的操作,而是直接从内存或者Redis中之前缓存的内容拿到,并返回。

Django中提供了6种缓存方式:

  • 开发调试
  • 内存
  • 文件
  • 数据库
  • Memcache缓存(python-memcached模块)
  • Memcache缓存(pylibmc模块)

1、配置

a、开发调试

 View Code

b、内存

 View Code

c、文件

 View Code

d、数据库

 View Code

e、Memcache缓存(python-memcached模块)

 View Code

f、Memcache缓存(pylibmc模块)

 View Code

2、应用

a. 全站使用

 View Code

b. 单独视图缓存

 View Code

c、局部视图使用

 View Code

 

posted @ 2016-09-22 00:47  (KeeP)  阅读(216)  评论(0)    收藏  举报