Django进阶

Posted J_hong

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django进阶相关的知识,希望对你有一定的参考价值。

一、Form

django中的Form一般有两种功能:1、输入html  2、验证用户输入

1、输入html

from django.shortcuts import render
from django import forms

class UserForm(forms.Form):
    host = forms.CharField()
    port = forms.CharField()
    email = forms.EmailField()
    mobile = forms.CharField()


def user_list(request):
    obj = UserForm()
    return render(request,"index.html",{"obj":obj})

  html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/app01/user_list/">
        <!--自动生成input标签-->
        <p>主机:{{ obj.host }}</p>
        <p>端口:{{ obj.port }}</p>
        <p>邮箱:{{ obj.email }}</p>
        <p>手机:{{ obj.mobile }}</p>
        <input type="submit">
    </form>
</body>
</html>

 

2、验证

from django.shortcuts import render
from django import forms

class UserForm(forms.Form):
    host = forms.CharField()
    port = forms.CharField()
    email = forms.EmailField()
    mobile = forms.CharField()

def user_list(request):
    obj = UserForm()
    if request.method == "POST":
        user_input_obj = UserForm(request.POST)#把提交过来的数据封装到UserForm,UserForm会自动把数据封装到user_input_obj
        if user_input_obj.is_valid():   #验证用户输入是否合法
            data = user_input_obj.clean()   #合法,获取数据
        else:
            error_msg = user_input_obj.errors   #不合法,返回错误信息
            return render(request,"index.html",{"obj":user_input_obj,"error":error_msg})
    return render(request,"index.html",{"obj":obj})

优化

def user_list(request):
    obj = UserForm(request.POST)#如果有数据,把提交过来的数据封装到UserForm,UserForm会自动把数据封装到user_input_obj
    if request.method == "POST":
        if obj.is_valid():   #验证用户输入是否合法
            data = obj.clean()   #合法,获取数据
        else:
            error_msg = obj.errors.as_data()   #不合法,返回错误信息
            return render(request,"index.html",{"obj":obj,"error":error_msg})
    return render(request,"index.html",{"obj":obj,})
View Code

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/app01/user_list/" method="post">
        <!--自动生成input标签-->
        <p>主机:{{ obj.host }}<span>{{ error.host }}</span></p>
        <p>端口:{{ obj.port }}<span>{{ error.port }}</span></p>
        <p>邮箱:{{ obj.email }}<span>{{ error.email }}</span></p>
        <p>手机:{{ obj.mobile }}<span>{{ error.mobile }}</span></p>
        <input type="submit">
    </form>
</body>
</html>
View Code

 

3、定制From表单

(1)设置报错信息,添加属性样式

class UserForm(forms.Form):
    host = forms.CharField(error_messages={"required":"主机不能为空"},#设置显示的错误信息
                           widget=forms.TextInput(attrs={"class":"form-control",
                                                         "placeholder": "主机"})#添加属性和样式
                           )
    port = forms.CharField()
    email = forms.EmailField()
    mobile = forms.CharField()

(2)多行文本框

#多行文本框,备注
    memo = forms.CharField(required=False,  #可以为空
                           widget=forms.Textarea(attrs={"class":"form-control",
                                                         "placeholder": "备注"})#添加属性和样式
                           )

(3)下拉框

#下拉框
    user_type_choice=(
        (0,"普通用户"),
        (1,"高级用户")
    )
    user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,
                                                                  attrs={\'class\': "form-control"}))

(4)动态生成select标签

文件中取数据

#动态下拉框
   u_type = forms.IntegerField(widget=forms.widgets.Select( attrs={\'class\': "form-control"}))

    def __init__(self, *args, **kwargs):
        super(UserForm, self).__init__(*args, **kwargs)
        import json
        f=open("u_type_db")
        data = f.read()
        data_tuple = json.loads(data)
        self.fields[\'u_type\'].widget.choices = data_tuple
#u_type_db
[[0, "AAA"], [1, "BBB"],[2,"CCC"]]

 数据库中取数据

def __init__(self, *args, **kwargs):
    super(UserForm, self).__init__(*args, **kwargs)
    data_tuple=models.UserInfo.objects.all().values_list(\'id\',\'username\')
    self.fields[\'u_type\'].widget.choices = data_tuple

 

(5)自定义验证条件

#自定义验证
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 UserForm(forms.Form):
    mobile = forms.CharField(validators=[mobile_validate, ])#添加自定义手机号验证

4、漂亮显示错误信息

def user_list(request):
    obj = UserForm()
    if request.method == "POST":
        user_input_obj = UserForm(request.POST)#把提交过来的数据封装到UserForm,UserForm会自动把数据封装到user_input_obj
        if user_input_obj.is_valid():   #验证用户输入是否合法
            data = user_input_obj.clean()   #合法,获取数据
        else:
            error_msg = user_input_obj.errors   #不合法,返回错误信息
            return render(request,"index.html",{"obj":user_input_obj,"error":error_msg})
    return render(request,"index.html",{"obj":obj,})

默认显示ul样式as_ul(),不美观

error_msg = user_input_obj.errors   #不合法,返回错误信息

 

改成as_data()后只显示一个字符串格式

error_msg = user_input_obj.errors.as_data()   #不合法,返回错误信息

方法:

  定义

  在html顶部调用

{% load  form_tag %}

  引用

<p>主机:{{ obj.host }}<span>{% error_message error.host %}</span></p>

 

as_json()  用于ajax返回

error_msg = user_input_obj.errors.as_json()#不合法,返回错误信息
return HttpResponse(error_msg )

 

实例:

html

{% load  form_tag %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/app01/user_list/" method="post">
        <!--自动生成input标签,也可以自己写html标签-->
        <p>主机:{{ obj.host }}<span>{% error_message error.host %}</span></p><!--引用-->
        <p>端口:{{ obj.port }}<span>{{ error.port }}</span></p>
        <p>邮箱:{{ obj.email }}<span>{{ error.email }}</span></p>
        <p>手机:{{ obj.mobile }}<span>{{ error.mobile }}</span></p>
        <p>备注:{{ obj.memo }}<span>{{ error.memo }}</span></p>
        <p>用户类型:{{ obj.user_type }}<span>{{ error.user_type }}</span></p>
        <input type="submit">
    </form>
</body>
</html>
View Code

views

from django.shortcuts import render
from django import forms
import re
from django.core.exceptions import ValidationError

#自定义验证
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 UserForm(forms.Form):
    host = forms.CharField(error_messages={"required":"主机不能为空"},#设置显示的错误信息
                           widget=forms.TextInput(attrs={"class":"form-control",
                                                         "placeholder": "主机"})#添加属性和样式
                           )
    port = forms.CharField(error_messages={"required":"端口不能为空"})
    email = forms.EmailField(error_messages={"required":"邮箱不能为空"})
    mobile = forms.CharField(error_messages={"required":"手机不能为空"},
                             validators=[mobile_validate, ])#添加自定义验证

    #多行文本框,备注
    memo = forms.CharField(required=False,  #可以为空
                           widget=forms.Textarea(attrs={"class":"form-control",
                                                         "placeholder": "备注"})#添加属性和样式
                           )
    #下拉框
    user_type_choice=(
        (0,"普通用户"),
        (1,"高级用户")
    )
    user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,
                                                                  attrs={\'class\': "form-control"}))

def user_list(request):
    obj = UserForm()
    if request.method == "POST":
        user_input_obj = UserForm(request.POST)#把提交过来的数据封装到UserForm,UserForm会自动把数据封装到user_input_obj
        if user_input_obj.is_valid():   #验证用户输入是否合法
            data = user_input_obj.clean()   #合法,获取数据
        else:
            error_msg = user_input_obj.errors.as_data()   #不合法,返回错误信息
            return render(request,"index.html",{"obj":user_input_obj,"error":error_msg})
    return render(request,"index.html",{"obj":obj,})
View Code

 

二、中间件

1、django 中的中间件(middleware),其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。

  settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件

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

 

中间件中可以定义四个方法,分别是:

  process_request(self,request)

  process_view(self, request, callback, callback_args, callback_kwargs)

  process_exception(self, request, exception)

  process_response(self, request, response)

 

每一个请求都是先通过中间件中的 process_request 函数,这个函数返回 None 或者 HttpResponse 对象,如果返回None ,继续处理其它中间件,如果返回一个 HttpResponse,就处理中止,返回到网页上

Django 会从 MIDDLEWARE_CLASSES 中按照从上到下的顺序一个个执行中间件中的 process_request 函数,而其中 process_response 函数则是最前面的最后执行。

 

2、自定义中间件

创建中间件

 

class RequestMiddleware(object):
    def process_request(self,request):
        print("process_request")
    def process_view(self, request, callback, callback_args, callback_kwargs):
        print("process_view")
    def process_exception(self, request, exception):
        print("process_exception")
    def process_response(self, request, response):
        print("process_response")
        return response

class RequestMiddleware2(object):
    def process_request(self,request):
        print("process_request2")
    def process_view(self, request, callback, callback_args, callback_kwargs):
        print("process_view2")
    def process_exception(self, request, exception):
        print("process_exception2")
    def process_response(self, request, response):
        print("process_response2")
        return response

注册中间件

settings.py

MIDDLEWARE_CLASSES = [
    #\'django.middleware.security.SecurityMiddleware\',
    \'django.contrib.sessions.middleware.SessionMiddleware\',
    \'django.middleware.common.CommonMiddleware\',
    #\'django.middleware.csrf.CsrfViewMiddleware\',
    \'django.contrib.auth.middleware.AuthenticationMiddleware\',
    \'django.contrib.auth.middleware.SessionAuthenticationMiddleware\',
    \'django.contrib.messages.middleware.MessageMiddleware\',
    \'django.middleware.clickjacking.XFrameOptionsMiddleware\',
    \'app01.middleware.middle.RequestMiddleware\',
    \'app01.middleware.middle.RequestMiddleware2\',
]

路由执行的函数

def index(request):
    print("index")
    return HttpResponse("index")

执行结果

上面是中间没有HttpResponse返回时的执行流程顺序,先执行process_request和process_view方法,在执行路由定义的函数,最后从最后一个process_response 开始执行,process_exception只会在出现异常时执行

 

三、缓存

1、由于Django是动态网站,一般来说需要实时地生成访问的网页,展示给访问者,这样,内容可以随时变化,但是从数据库读多次把所需要的数据取出来,要比从内存或者硬盘等一次读出来 付出的成本大很多。最简单解决方式是使用:缓存,缓存将一个某个views的返回值保存至内存或者Redis中,一定时间内再有人来访问时,则不再去执行view中的操作,而是直接从内存或者Redis中之前缓存的内容拿到,并返回。

 settings配置

CACHES = {
    \'default\': {
        \'BACKEND\': \'django.core.cache.backends.filebased.FileBasedCache\',#表示利用文件系统缓存
        \'LOCATION\': os.path.join(BASE_DIR, \'cache\'),#文件路径
        \'TIMEOUT\': 600,
        \'OPTIONS\': {
            \'MAX_ENTRIES\': 1000
        }
    }
}

views

import time
from django.shortcuts import HttpResponse,render
from django.views.decorators.cache import cache_page

@cache_page(60 * 15)#表示缓存15分钟
def index(request):
    data=time.time()
    return HttpResponse(data)

其它的一些内建可用的 Backends

\'django.core.cache.backends.db.DatabaseCache\'
\'django.core.cache.backends.dummy.DummyCache\'
\'django.core.cache.backends.filebased.FileBasedCache\'
\'django.core.cache.backends.locmem.LocMemCache\'
\'django.core.cache.backends.memcached.MemcachedCache\'
\'django.core.cache.backends.memcached.PyLibMCCache\'
View Code

更多相关:http://djangobook.py3k.cn/2.0/chapter15/

 

四、Session和Cookie

cookie保存在客户端的电脑上,session保存与服务器

session用来在服务器端保存用户会话状态信息,依赖于cookies

操作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失效策略。
 
 
登录认证实例:
<form class="common_form" id="Form" method="post" action="/app01/login/">
    <div><h1 class="login_title">登录</h1></div>
    <div style="width: 600px">
        <div class="form_group"><input name="username" class="form-control" label=\'用户名\' type="text" placeholder="用户名" require=\'true\'></div>
    </div>
    <div style="width: 600px">
        <以上是关于Django进阶的主要内容,如果未能解决你的问题,请参考以下文章

Django进阶之Form

Django-form进阶+详细版

Django 第十二篇Form组件进阶

python3-开发进阶Django-form组件中model form组件

Python入门自学进阶-Web框架——15Django的Form验证2

Python入门自学进阶-Web框架——14Django的Form验证