Day19 Django之Form表单验证、CSRF、Cookie、Session和Model操作

一、Form表单验证

用于做用户提交数据的验证
1.自定义规则

a、自定义规则(类,字段名==html中的name值)
b、数据提交-规则进行匹配
代码如下:

"""day19_django URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.10/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
]
urls.py
"""
Django settings for day19_django project.

Generated by 'django-admin startproject' using Django 1.10.2.

For more information on this file, see
https://docs.djangoproject.com/en/1.10/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.10/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'pv#lfw8ywtf=ws8mr%f9b)ihc0s@oj-2$wu^2o@)+(^)$i_9*n'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'day19_django.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'day19_django.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/1.10/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.10/howto/static-files/

STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)
settings.py
from django.shortcuts import render,HttpResponse
from django import forms
from django.forms.utils import ErrorDict
import json
from django.core.exceptions import ValidationError
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=12,
                          error_messages={'required':'密码必须不能为空',
                                          'min_length':'至少6位',
                                          'max_length':'最多12位'})
    num = forms.IntegerField(error_messages={'required':'数字不能为空', 'invalid':'必须输入数字'})
    #url = forms.EmailField()
    phone = forms.CharField(validators=[mobile_validate, ],)

def login(request):
    if request.method == 'POST':
        result = {'status':False, 'message':None}
        obj = LoginForm(request.POST)
        ret = obj.is_valid()
        if ret:
            print(obj.clean())
            result['status'] = True
        else:
            print(type(obj.errors), obj.errors.as_json())
            error_str = obj.errors.as_json()
            result['message'] = json.loads(error_str)
            return HttpResponse(json.dumps(result))
    return render(request, 'login.html')
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .error-msg{
            background-color: red;
        }
    </style>
</head>
<body>
    <div>
        <div>
            <input type="text" name="user" />
        </div>
        <div>
            <input type="text" name="num" />
        </div>
        <div>
            <input type="text" name="phone" />
        </div>
        <div>
            <input type="password" name="pwd" />
        </div>
        <input type="button" value="提交" οnclick="DoSubmit();" />
    </div>
    <script src="/static/jquery-1.12.4.js"></script>
    <script>
        function DoSubmit() {
            var dict_input = {};
            $('input').each(function () {
                var v = $(this).val();
                var n = $(this).attr('name');
                dict_input[n] = v;
            });
            console.log(dict_input);
            $('.error-msg').remove();
            $.ajax({
                url:'/login/',
                type:'POST',
                data:dict_input,
                dataType: 'json',
                success:function (result) {
                    if(result.status){
                        location.href = '/index/';
                    }else{
                        $.each(result.message, function (k, v) {
                            console.log(k, v[0].message);
                            //<sapn class="error-msg">错误信息</span>
                            var tag = document.createElement('span');
                            tag.className = 'error-msg';
                            tag.innerText = v[0].message;
                            //input[name="user"]
                            $('input[name="' + k + '"]').after(tag);
                        })
                    }

                },
                error:function () {
                    
                }
            })
        }
    </script>
</body>
</html>
login.html

2.用于做用户提交数据的验证 + 生成HTML标签

代码如下:

from django.shortcuts import render,HttpResponse
from django import forms
from django.forms.utils import ErrorDict
import json
from django.core.exceptions import ValidationError
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=12,
                          error_messages={'required':'密码必须不能为空',
                                          'min_length':'至少6位',
                                          'max_length':'最多12位'})
    num = forms.IntegerField(error_messages={'required':'数字不能为空', 'invalid':'必须输入数字'})
    #url = forms.EmailField()
    phone = forms.CharField(validators=[mobile_validate, ],)
    #生成input标签,并加属性,设置样式
    #test = forms.CharField(widget=forms.TextInput(attrs={'k1':'123','class':'error-msg'}))
    #生成下拉列表,真正提交数据还是数字
    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:
            #obj1.errors是ErrorDict,ErrorDict继承dict
            # for k,v in objPost.errors.items():
            #     print(k, v)
            # print(objPost.errors['phone'][0])
            # print(objPost.errors['user'][0])
            # print(objPost.errors['num'][0])
            pass
        return render(request, 'login.html', {'obj1': objPost})
    else:
        objGet = LoginForm()
        return render(request, 'login.html', {'obj1':objGet})
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .error-msg{
            background-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 }}
                {% if obj1.errors.pwd %}
                    <span class="error-msg">{{ obj1.errors.pwd.0 }}</span>
                {% endif %}
            </div>
            <div>
               {{ obj1.num }}
                {% if obj1.errors.num %}
                    <span class="error-msg">{{ obj1.errors.num.0 }}</span>
                {% endif %}
            </div>
            <div>
               {{ obj1.phone }}
                {% if obj1.errors.phone %}
                    <span class="error-msg">{{ obj1.errors.phone.0 }}</span>
                {% endif %}
            </div>
            <div>
                {{ obj1.test }}
            </div>
            <input type="submit" value="提交" />
        </div>
    </form>
</body>
</html>
login.html

二、CSRF

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

"""day19_django URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.10/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
    url(r'^csrf/', views.csrf),
]
urls.py
from django.shortcuts import render,HttpResponse
from django import forms
from django.forms.utils import ErrorDict
import json
from django.core.exceptions import ValidationError
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=12,
                          error_messages={'required':'密码必须不能为空',
                                          'min_length':'至少6位',
                                          'max_length':'最多12位'})
    num = forms.IntegerField(error_messages={'required':'数字不能为空', 'invalid':'必须输入数字'})
    #url = forms.EmailField()
    phone = forms.CharField(validators=[mobile_validate, ],)
    #生成input标签,并加属性,设置样式
    #test = forms.CharField(widget=forms.TextInput(attrs={'k1':'123','class':'error-msg'}))
    #生成下拉列表,真正提交数据还是数字
    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:
            #obj1.errors是ErrorDict,ErrorDict继承dict
            # for k,v in objPost.errors.items():
            #     print(k, v)
            # print(objPost.errors['phone'][0])
            # print(objPost.errors['user'][0])
            # print(objPost.errors['num'][0])
            pass
        return render(request, 'login.html', {'obj1': objPost})
    else:
        objGet = LoginForm()
        return render(request, 'login.html', {'obj1':objGet})

def csrf(request):
    return render(request, 'csrf.html')
views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
        <!--form提交-->
        <form action="/csrf/" method="POST">
            {% csrf_token %}
            <input type="text" name="v" />
            <input type="submit" value="提交" />
        </form>

    <input type="button" value="Ajax提交" οnclick="DoAjax();" />
    <!--ajax提交-->
    <script src="/static/jquery-2.1.4.min.js"></script>
    <script src="/static/jquery.cookie.js"></script>
    <script>
        //获取cookie
        var csrftoken = $.cookie('csrftoken');

        function csrfSafeMethod(method) {
            // these HTTP methods do not require CSRF protection
            return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
        }
        $.ajaxSetup({
            beforeSend: function(xhr, settings) {
                if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                    xhr.setRequestHeader("X-CSRFToken", csrftoken);
                }
            }
        });

        function DoAjax() {
            $.ajax({
                url:'/csrf/',
                type:'POST',
                data:{'k1':'v1'},
                success: function (data) {
                    console.log(data);
                }
            })
        }
    </script>
</body>
</html>
csrf.html

三、Cookie和Session

Cookie保存在客户端浏览器上的一个容器,独立存在
服务器上保存的是session(内存或数据库或缓存),依赖Cookie

 

"""day19_django URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.10/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
    url(r'^csrf/', views.csrf),
    url(r'^cookie/', views.cookie),
    url(r'^cookie1/', views.cookie),
    url(r'^log/', views.log),
    url(r'^index/', views.index),
    url(r'^session_login/', views.session_login),
    url(r'^session_index/', views.session_index),
    url(r'^session_logout/', views.session_logout),
]
urls.py
from django.shortcuts import render,HttpResponse,redirect
from django import forms
from django.forms.utils import ErrorDict
import json
from django.core.exceptions import ValidationError
import re
from django.views.decorators.csrf import csrf_exempt,csrf_protect
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=12,
                          error_messages={'required':'密码必须不能为空',
                                          'min_length':'至少6位',
                                          'max_length':'最多12位'})
    num = forms.IntegerField(error_messages={'required':'数字不能为空', 'invalid':'必须输入数字'})
    #url = forms.EmailField()
    phone = forms.CharField(validators=[mobile_validate, ],)
    #生成input标签,并加属性,设置样式
    #test = forms.CharField(widget=forms.TextInput(attrs={'k1':'123','class':'error-msg'}))
    #生成下拉列表,真正提交数据还是数字
    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:
            #obj1.errors是ErrorDict,ErrorDict继承dict
            # for k,v in objPost.errors.items():
            #     print(k, v)
            # print(objPost.errors['phone'][0])
            # print(objPost.errors['user'][0])
            # print(objPost.errors['num'][0])
            pass
        return render(request, 'login.html', {'obj1': objPost})
    else:
        objGet = LoginForm()
        return render(request, 'login.html', {'obj1':objGet})

#@csrf_protect 强制给函数加csrf验证

@csrf_exempt
#不用做csrf验证
def csrf(request):

    return render(request, 'csrf.html')

#使用Cookie做登录认证
def cookie(request):
    print(request.COOKIES)
    obj =  render(request, 'cookie.html')
    #path='/cookie/',Cookie存放路径
    obj.set_cookie('k3','v3',path='/cookie/')
    return obj

def cookie1(request):
    print(request.COOKIES)
    obj =  render(request, 'cookie.html')
    #path='/',Cookie全局生效
    obj.set_cookie('k1','v1',path='/')
    return obj

def log(request):
    if request.method == 'POST':
        u = request.POST.get('user')
        p = request.POST.get('pwd')
        if u == 'alex' and p == '123':
            print(u)
            red = redirect('/index/')
            red.set_cookie('username', u)
            return red
        else:
            return render(request, 'log.html')
    else:
        return render(request, 'log.html')

def index(request):
    user = request.COOKIES.get('username')
    if user:
        return render(request, 'index.html', {'user':user})
    else:
        return redirect('/log/')

#使用session做登录认证
USER_LIST = ['alex','eric','wang','liu']
def session_login(request):
    if request.method == 'POST':
        u = request.POST.get('user')
        p = request.POST.get('pwd')
        if u in USER_LIST and p == '123':
            request.session['user'] = u
            return redirect('/session_index/')
    return render(request, 'session_login.html')

"""
def session_index(request):
    user = request.session.get('user', None)
    if not user:
        return redirect('/session_login/')
    else:
        return render(request, 'session_index.html', {'user':user})
"""
def auth(func):
    def inner(request, *args, **kwargs):
        #print(request, args, kwargs)
        user = request.session.get('user', None)
        if not user:
            return redirect('/session_login/')
        return func(request, *args, **kwargs)
    return inner

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

@auth
def session_logout(request):
    del request.session['user']
    return redirect('/session_login/')
views.py
<!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_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>
    <form action="/log/"  method="POST">
        <input type="text" name="user">
        <input type="text" name="pwd">
        <input type="submit" value="提交" />
    </form>
</body>
</html>
log.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()

    print(queryset.query)       --SQL语句
    [UserInfo对象,UserInfo对象,UserInfo对象,]

    queryset = UserInfo.objects.all().values('user')
    [{'user':'alex'},{'user':'eric'}]

    queryset = UserInfo.objects.all().value_list('user')
    [('alex'),('eric')]

    =======================================================
    一对多
     class UserType(models.Model):
        caption = models.CharField(max_length=32)
    #超级管理员、普通用户、访客、黑客

     class UserInfo(models.Model):
        user = models.CharField(max_length=32)
        pwd = models.CharField(max_length=32)
        user_type = models.ForeignKey('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)
        或:
        queryset = UserInfo.objects.filter(user_type__caption='普通用户')     --  跨表使用双下划线
        [UserInfo对象,UserInfo对象,UserInfo对象,]
        row = queryset[0]
        row.user
        row.pwd
        row.user_type   -- user_type对象
        row.user_type.id
        row.user_type.caption
        ###### objects __
        ###### row.外键字段.外键表的字段

        queryset = UserInfo.objects.filter(user_type__caption='普通用户').values('user', 'user_type__caption')     --  跨表使用双下划线
        [{'user':'alex','user_type__caption':'普通用户'},{'user':'eric','user_type__caption':'普通用户'}]
        row = queryset[0]
        row['user']
        row['user_type__caption']

    多张表
    class Something(models.Model):
        name = models.CharField(max_length=32)

    class UserType(models.Model):
        caption = models.CharField(max_length=32)
        st = models.ForeignKey('Something')
    #超级管理员、普通用户、访客、黑客

     class UserInfo(models.Model):
        user = models.CharField(max_length=32)
        pwd = models.CharField(max_length=32)
        user_type = models.ForeignKey('UserType')
        #user_type_id

     UserInfo.objects.filter(user_type__st__name='xx')
View Code

 

转载于:https://www.cnblogs.com/icsnow/p/6024449.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值