码迷,mamicode.com
首页 > 其他好文 > 详细

Django进阶

时间:2016-05-27 20:19:48      阅读:242      评论:0      收藏:0      [点我收藏+]

标签:

一、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"]]

 

(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">
        <div class="form_group"><input name="password" class="form-control" label=‘密码‘ type="password" placeholder="密码" require=‘true‘></div>
    </div>
    <div class="form_group"><input class="btn btn-info form_btn" type="submit" value="登录"></div>
</form>
html
技术分享
def login(request):
    if request.method == "POST":
        username = request.POST.get("username")
        password = request.POST.get("password")
        if username == "zhangsan" and password == "123456":
            request.session["IS_LOGIN"] = True  #创建session
            return redirect("/app01/home/")
    return render(request,"app01/login.html")

def home(request):
    islogin = request.session.get("IS_LOGIN",False)
    if islogin:#如果用户已登录
        return render(request,"app01/menus.html")
    else:
        return redirect("/app01/login/")

def logout(request):#退出
    try:
        del request.session[IS_LOGIN]
    except KeyError:
        pass
    return redirect("/app01/login/")
views

 

更多:http://docs.30c.org/djangobook2/chapter14/

   https://docs.djangoproject.com/en/1.9/ref/settings/#settings-sessions

 

五、Ajax

1、跨站请求伪造

django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成

GET 请求不需要 CSRF 认证,POST 请求需要正确认证才能得到正确的返回结果。一般在POST请求的表单中加入{% csrf_token %}

<form id="Form" method="post" action="/app01/login/">
    {% csrf_token %}
    <input name=‘username‘  type="text">
    <input name=‘password‘  type="password">
    <input type="submit" value="登录">
</form>

veiw中设置返回值:

return render_to_response("app01/login.html",data,context_instance=RequestContext(request))  
#或者
return render(request, "app01/login.html", data)

 

2、发送简单数据

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <input type="button" onclick="Ajaxsubmit();" value="提交"/>

    <script type="text/javascript" src="../../static/style/js/jquery-2.2.3.js"></script>
    <script>
        function Ajaxsubmit(){
            var host = 127.0.0.1;
            var port = 8000;
            $.ajax({
                url:"/app01/user_list/",
                type:POST,
                data:{h:host,p:port},
                success:function(arg){
                }
            })
        }
    </script>
</body>
</html>

 

2、发送复杂数据类型

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <input type="button" onclick="Ajaxsubmit();" value="提交"/>

    <script type="text/javascript" src="../../static/style/js/jquery-2.2.3.js"></script>
    <script>
        function Ajaxsubmit(){
             var userlist = [
                {username:zhangsan,arg:18},
                {username:lisi,arg:20},
            ];
            $.ajax({
                url:"/app01/user_list/",
                type:POST,
                tradition: true,
                data:{data:JSON.stringify(userlist)},//序列化
                success:function(arg){
                     var callback_dict = $.parseJSON(arg);//这里把字符串转换为对象
                    //然后咱们就可以判断
                    if(callback_dict.status){//如果为True执行失败
                        alert(提交成功)
                    }else{//如果为False执行失败
                        alert(callback_dict.error)
                    }
                }
            });
        }
    </script>
</body>
</html>

views

def user_list(request):
    ret = {status:True,error:‘‘}
    try:
        print request.POST
    except Exception,e:
        ret[status] = False   #如果出错就把ret[status] = False
        ret[error] = str(e)
    return HttpResponse(json.dumps(ret))    #返回ret字典

 

六、静态文件引用优化

在写项目时会导入很多静态文件,而有时要修改静态文件的目录名时就比较麻烦

原来导入方式

<script type="text/javascript" src="/static/style/js/jquery-2.2.3.js"></script>

优化

  在settings的TEMPLATES里添加  ‘django.core.context_processors.static‘

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,
                django.core.context_processors.static,
            ],
        },
    },
]

优化后导入

<script type="text/javascript" src="{{ STATIC_URL }}style/js/jquery-2.2.3.js"></script>

 

这样要修改目录的话只需在配置文件里修改 STATIC_URL 就可以了

 

 

Django进阶

标签:

原文地址:http://www.cnblogs.com/melonjiang/p/5510943.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!