Python学习高级篇(四)

概要
一、路由系统
    1、默认处理函数
    2、动态url
    3、分级匹配
    4、基于反射实现的动态路由
二、中间件
    对于所有请求做处理时===》定义中间件
    功能:拿到请求ip后禁用一下
三、Model(*)
    1、创建表
    2、操作表数据
四、Form(*)
    1、用户提交数据验证
    2、生成html标签
五、cookie和session
六、跨站请求伪造,跨站脚本攻击
七、Ajax(*)
八、Admin
九、缓存
十、自定义分页(*)

 

Django学习基础篇

关于python的web框架那点事

Flask基于Werkzeug 和 Jinja2的微型Python框架,它的目的是更快地上手,适合初学者使用。参考果壳网。

Django全能型框架,目的是为了让开发者能够 快速 地开发一个网站,它提供了很多模块,集成了ORM、模型绑定、模板引擎、缓存、Session等诸多功能。咱们接下来的主人公就是这位了。。。

Tornado传说中性能高高的框架,是一个异步网络库,通过使用非阻塞I/O,Tornado可以处理数以万计打开的链接,这使它成为长轮询、WebSocket和其他需要为用户提供长连接的应用的理想选择。参考知乎。

 

基本配置

一、创建django程序

终端命令:django-admin startproject sitename

IDE创建Django程序时,本质上都是自动执行上述命令

其他常用命令

  运行程序:python manage.py runserver

  创建APP:python manage.py startapp appname
  同步数据库:python manage.py syncdb

    python manage.py makemigrations

    python manage.py migrate

  创建超级用户:python manage.py createsuperuser

二、程序目录

三、配置文件settings.py

1、数据库

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

2、模板

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',
            ],
        },
    },
]

3、静态文件

STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
]

  

模板template

1、模版的执行

模版的创建过程,对于模版,其实就是读取模版(其中嵌套着模版标签),然后将 Model 中获取的数据插入到模版中,最后将信息返回给用户。

def current_datetime(request):
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
return HttpResponse(html)
from django import template
t = template.Template('My name is {{ name }}.')
c = template.Context({'name': 'Adrian'})
print t.render(c)
import datetime
from django import template
import DjangoDemo.settings
 
now = datetime.datetime.now()
fp = open(settings.BASE_DIR+'/templates/Home/Index.html')
t = template.Template(fp.read())
fp.close()
html = t.render(template.Context({'current_date': now}))
return HttpResponse(html)
from django.template.loader import get_template
from django.template import Context
from django.http import HttpResponse
import datetime
 
def current_datetime(request):
    now = datetime.datetime.now()

    t = get_template('current_datetime.html')
    html = t.render(Context({'current_date': now}))
    return HttpResponse(html)
return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))

2、模版语言

 模板中也有自己的语言,该语言可以实现数据展示

  • {{ item }}
  • {% for item in item_list %} <a>{{ item }}</a> {% endfor %}
      forloop.counter
      forloop.first
      forloop.last
  • {% if ordered_warranty %} {% else %} {% endif %}
  • 母板:{% block title %}{% endblock %}
    子板:{% extends "base.html" %}
       {% block title %}{% endblock %}
  • 帮助方法:
    {{ item.event_start|date:"Y-m-d H:i:s"}}
    {{ bio|truncatewords:"30" }}
    {{ my_list|first|upper }}
    {{ name|lower }}

3、自定义simple_tag

a、在app中创建templatetags模块

b、创建任意 .py 文件,如:xx.py

#!/usr/bin/env python
#coding:utf-8

from django import template
from django.utils.safestring import mark_safe
from django.template.base import resolve_variable, Node, TemplateSyntaxError

register = template.Library()
@register.simple_tag
def my_simple_time(v1,v2,v3):
    return  v1 + v2 + v3

@register.simple_tag
def my_input(id,arg):
    result = "<input type='text' id='%s' class='%s' />" %(id,arg,)
    return mark_safe(result)

c、在使用自定义simple_tag的html文件中导入之前创建的 xx.py 文件名

{% load xx %}

d、使用simple_tag

{% my_simple_time 1 2 3%}
{% my_input 'id_username' 'hide'%}

e、在settings中配置当前app,不然django无法找到自定义的simple_tag

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

  

路由系统urls.py

1、每个路由规则对应一个view中的函数

urlpatterns = [
    url(r'^admin/', admin.site.urls),
]

2、根据app对路由规则进行一次分类

url(r'^web/', include('web.urls')),

django中的路由系统和其他语言的框架有所不同,在django中每一个请求的url都要有一条路由映射,这样才能将请求交给对一个的view中的函数去处理。其他大部分的Web框架则是对一类的url请求做一条路由映射,从而是路由系统变得简洁。

 

Urls.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-

from django.conf.urls import include, url
from django.contrib import admin
from app01 import views

def md():
    pass

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    
# 交给app01/urls.py处理
    url(r'^app01/', include("app01.urls")),
    
    # url(r'^index/$', views.index),
    # url(r'^user_list/(\d+)/(\d+)$', views.user_list), # 基于正则表达式
    # url(r'^user_list/(?P<v1>\d+)/(?P<v2>\d+)$', views.user_list), # 参数设置为v1,v2
    # url(r'^$', views.index),
]

App01/urls.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from django.conf.urls import include, url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'index/$', views.index),
    url(r'cache/$', views.cache_page),
    url(r'login/$', views.login),
    url(r'home/$', views.home),
    url(r'logout/$', views.logout),
]

App01/views.py

# -*- coding:utf-8 -*-
from django.shortcuts import render,HttpResponse,redirect
import time
from django.views.decorators.cache import cache_page

db = {
    'alex': "asdfasdfasdasdfasdf",
    'eirc': '11111111111',
}

def login(request):
    if request.method == "POST":
        username = request.POST.get('username')
        pwd = request.POST.get('pwd')
        if username == 'alex' and pwd == '123':
            request.session['IS_LOGIN'] = True
            request.session['USRNAME'] = 'alex'
            return redirect('/app01/home/')
        elif username == 'eirc' and pwd == '123':
            request.session['IS_LOGIN'] = True
            request.session['USRNAME'] = 'eirc'
            return redirect('/app01/home/')

    return render(request, 'login.html')

def home(request):
    is_login = request.session.get('IS_LOGIN', False)
    if is_login:
        print request.session,type(request.session)

        username = request.session.get('USRNAME', False)
        data = db[username]
        # return HttpResponse(data)
        return render(request, 'home.html', {'username': username})
    else:
        return redirect("/app01/login/")


def logout(request):
    # del request.session['IS_LOGIN']
    # del reques
    from django.contrib.sessions.backends.db import SessionStore
    # print request.session._session_key
    del request.session['IS_LOGIN']
    request.session.delete(request.session._session_key)

    return redirect('/app01/login/')

@cache_page(60 * 15)
def cache_page(request):
    current = str(time.time())
    return HttpResponse(current)


def index(request):
    raise Exception('bb')
    return HttpResponse('ok')
#
# def user_list(request, nid, page):
#     print nid,page
#     return HttpResponse(nid+page)
def user_list(request, v2, v1):
    print v1,v2
    return HttpResponse(v1+v2)  

通过反射机制,为django开发一套动态的路由系统Demo:

  

Readme.txt

该实例通过反射机制实现Django的动态路由

主要代码实现
1、url.py
           配置url映射

2、activator.py
           根据url中获取的参数,通过反射调用指定 app/view.py 中的函数 
如: 
http://127.0.0.1:9000/app01/index/        ==》 执行app01/view.py文件中的index函数
http://127.0.0.1:9000/app02/index/        ==》 执行app02/view.py文件中的index函数
http://127.0.0.1:9000/app01/login/ ==》 执行app01/view.py文件中的login函 

settings.py

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


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

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '%b*ah#)lb500*yzykxe0t_z4pzzs_q06e=!a5$2k^s&%3%@m%('

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

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

MIDDLEWARE_CLASSES = (
    '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',
)

ROOT_URLCONF = 'DynamicRouter.urls'

WSGI_APPLICATION = 'DynamicRouter.wsgi.application'


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

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

# Internationalization
# https://docs.djangoproject.com/en/1.7/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.7/howto/static-files/

STATIC_URL = '/static/'

urls.py

from django.conf.urls import patterns, include, url
from django.contrib import admin
from DynamicRouter.activator import process

urlpatterns = patterns('',
    # Examples:
    # url(r'^$', 'DynamicRouter.views.home', name='home'),
    # url(r'^blog/', include('blog.urls')),

    url(r'^admin/', include(admin.site.urls)),
    
    
    ('^(?P<app>(\w+))/(?P<function>(\w+))/(?P<page>(\d+))/(?P<id>(\d+))/$',process),
    ('^(?P<app>(\w+))/(?P<function>(\w+))/(?P<id>(\d+))/$',process),
    ('^(?P<app>(\w+))/(?P<function>(\w+))/$',process),
    ('^(?P<app>(\w+))/$',process,{'function':'index'}),
)

activator.py

#!/usr/bin/env python
#coding:utf-8

from django.shortcuts import render_to_response,HttpResponse,redirect

def process(request,**kwargs):
    '''接收所有匹配url的请求,根据请求url中的参数,通过反射动态指定view中的方法'''
    
    app =  kwargs.get('app',None)
    function = kwargs.get('function',None)
    
    try:
        appObj = __import__("%s.views" %app)
        viewObj = getattr(appObj, 'views')
        funcObj = getattr(viewObj, function)
        
        #执行view.py中的函数,并获取其返回值
        result = funcObj(request,kwargs)
        
    except (ImportError,AttributeError),e:
        #导入失败时,自定义404错误
        return HttpResponse('404 Not Found')
    except Exception,e:
        #代码执行异常时,自动跳转到指定页面
        return redirect('/app01/index/')
    
    return result

App01/views.py

from django.shortcuts import render
from django.http.response import HttpResponse

# Create your views here.

def index(request,kwargs):   
    return HttpResponse('app01.index')

App02/views.py

from django.shortcuts import render
from django.http.response import HttpResponse

# Create your views here.

def index(request,kwargs):    
    return HttpResponse('app02.index')

App03/views.py

from django.shortcuts import render
from django.http.response import HttpResponse

# Create your views here.

def index(request,kwargs):
    return HttpResponse('app03.index')

  

admin

django amdin是django提供的一个后台管理页面,改管理页面提供完善的html和css,使得你在通过Model创建完数据库表之后,就可以对数据进行增删改查,而使用django admin 则需要以下步骤:

创建后台管理员

配置url

注册和配置django admin后台管理页面

1、创建后台管理员

python manage.py createsuperuser

2、配置后台管理url

url(r'^admin/', include(admin.site.urls))  

3、注册和配置django admin 后台管理页面

a、在admin中执行如下配置  

from django.contrib import admin
from app01 import  models

admin.site.register(models.UserType)
admin.site.register(models.UserInfo)
admin.site.register(models.UserGroup)
admin.site.register(models.Asset)

b、设置数据表名称

class UserType(models.Model):
    name = models.CharField(max_length=50)

    class Meta:
        verbose_name = '用户类型'
        verbose_name_plural = '用户类型'

c、打开表之后,设定默认显示,需要在model中作如下配置

class UserType(models.Model):
    name = models.CharField(max_length=50)

    def __unicode__(self):
        return self.name

from django.contrib import admin
from app01 import models

class UserInfoAdmin(admin.ModelAdmin):
    list_display = ('username', 'password', 'email')

admin.site.register(models.UserType)
admin.site.register(models.UserInfo,UserInfoAdmin)
admin.site.register(models.UserGroup)
admin.site.register(models.Asset)

d、为数据表添加搜索功能

from django.contrib import admin
from app01 import  models

class UserInfoAdmin(admin.ModelAdmin):
    list_display = ('username', 'password', 'email')
    search_fields = ('username', 'email')

admin.site.register(models.UserType)
admin.site.register(models.UserInfo,UserInfoAdmin)
admin.site.register(models.UserGroup)
admin.site.register(models.Asset) 

e、添加快速过滤

from django.contrib import admin
from app01 import  models

class UserInfoAdmin(admin.ModelAdmin):
    list_display = ('username', 'password', 'email')
    search_fields = ('username', 'email')
    list_filter = ('username', 'email')

admin.site.register(models.UserType)
admin.site.register(models.UserInfo,UserInfoAdmin)
admin.site.register(models.UserGroup)
admin.site.register(models.Asset)

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

 

Django学习进阶篇

Django请求生命周期原理【面试必备】

实现机制:
    先去执行settings里的middleware的所有类,根据类执行相应的列表;

1、请求
2、Django自动去 setttings里找 MIDDLEWARE_CLASSES ,元祖
3、
MIDDLEWARE_CLASSES = (
    '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',
    'django.middleware.security.SecurityMiddleware',
    'middleware.middle1.mmm',
    'middleware.middle1.xxx',
)
process_request_list = []
process_view_list = []
process_response_list = []
process_exception_list = []

for 类 in MIDDLEWARE_CLASSES:
   obj = 类()
   if obj里有process_request方法:
      process_request_list.append(obj.process_request)

for i in process_request_list:
   i()
for i in process_view_list:
   i()

views里的函数
for i in process_response_list:
   i()
      obj.process_request

  

中间件

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

在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件,如下图。

与mange.py在同一目录下的文件夹 wxy/middleware下的auth.py文件中的Authentication类

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

  • process_request(self,request)
  • process_view(self, request, callback, callback_args, callback_kwargs)
  • process_exception(self, request, exception)
  • process_response(self, request, response)

以上方法的返回值可以是None和HttpResonse对象,如果是None,则继续按照django定义的规则向下执行,如果是HttpResonse对象,则直接将该对象返回给用户。

  

自定义中间件

1、创建中间件类

class RequestExeute(object):
   
    def process_request(self,request):
        pass

    def process_view(self, request, callback, callback_args, callback_kwargs):
        i =1
        pass

    def process_exception(self, request, exception):
        pass

    def process_response(self, request, response):
        return response

2注册中间件

MIDDLEWARE_CLASSES = (
    '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',
    'wxy.middleware.auth.RequestExeute',
)

  

 

  

DEM0

目录结构如下:

Settings.py

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01',
)

MIDDLEWARE_CLASSES = (
    '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',
    'django.middleware.security.SecurityMiddleware',
    'middleware.middle1.mmm',
    'middleware.middle1.xxx',
)  

urls.py

from django.conf.urls import include, url
from django.contrib import admin
from app01 import views

def md():
    pass

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^app01/', include("app01.urls")),
    # home.py def index
    # /home/index
    # /aa/vv
    # /uu/vwwv
    # 只是基于反射


    url(r'^index/$', views.index),

    url(r'^index1/$', views.index),
    url(r'^home/$', views.index),
    url(r'^sd/$', views.index),
    url(r'^fff/$', views.index),
    url(r'^aa/$', views.index),
    # url(r'^index/$', views.index),
    # url(r'^user_list/(\d+)/(\d+)$', views.user_list),
    # url(r'^user_list/(?P<v1>\d+)/(?P<v2>\d+)$', views.user_list),
    # url(r'^$', views.index),
]

app01/views.py

# -*- coding:utf-8 -*-
from django.shortcuts import render,HttpResponse,redirect
import time
from django.views.decorators.cache import cache_page

db = {
    'alex': "asdfasdfasdasdfasdf",
    'eirc': '11111111111',
}

def login(request):
    if request.method == "POST":
        username = request.POST.get('username')
        pwd = request.POST.get('pwd')
        if username == 'alex' and pwd == '123':
            request.session['IS_LOGIN'] = True
            request.session['USRNAME'] = 'alex'
            return redirect('/app01/home/')
        elif username == 'eirc' and pwd == '123':
            request.session['IS_LOGIN'] = True
            request.session['USRNAME'] = 'eirc'
            return redirect('/app01/home/')

    return render(request, 'login.html')

def home(request):
    is_login = request.session.get('IS_LOGIN', False)
    if is_login:
        print request.session,type(request.session)

        username = request.session.get('USRNAME', False)
        data = db[username]
        # return HttpResponse(data)
        return render(request, 'home.html', {'username': username})
    else:
        return redirect("/app01/login/")


def logout(request):
    # del request.session['IS_LOGIN']
    # del reques
    from django.contrib.sessions.backends.db import SessionStore
    # print request.session._session_key
    del request.session['IS_LOGIN']
    request.session.delete(request.session._session_key)

    return redirect('/app01/login/')

@cache_page(60 * 15)
def cache_page(request):
    current = str(time.time())
    return HttpResponse(current)


def index(request):
    raise Exception('bb')
    return HttpResponse('ok')
#
# def user_list(request, nid, page):
#     print nid,page
#     return HttpResponse(nid+page)
def user_list(request, v2, v1):
    print v1,v2
    return HttpResponse(v1+v2)

app01/urls.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from django.conf.urls import include, url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'index/$', views.index),
    url(r'cache/$', views.cache_page),
    url(r'login/$', views.login),
    url(r'home/$', views.home),
    url(r'logout/$', views.logout),
]

Middleware/middle1.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from django.shortcuts import HttpResponse
class mmm(object):
    def process_request(self,request):
        print "mmm.process_request"
    def process_view(self, request, callback, callback_args, callback_kwargs):
        print "mmm.process_view"
    def process_response(self, request, response):
        print "mmm.process_response"
        return response
    def process_exception(self, request, exception):
        print "擦了,下面那个中间件不管,那就我管吧"
        return HttpResponse("擦了,下面那个中间件不管,那就我管吧")


class xxx(object):
    def process_request(self,request):
        print "xxx.process_request"
    def process_view(self, request, callback, callback_args, callback_kwargs):
        print "xxx.process_view"
    def process_response(self, request, response):
        print "xxx.process_response"
        return response
    def process_exception(self, request, exception):
        print "View中出错了,但是我就不管"
        return HttpResponse('ooooo')

Template/login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <form action="/app01/login/" method="post">
        <input type="text" name="username" />
        <input type="password" name="pwd" />
        <input type="submit" value="submit"/>
    </form>

</body>
</html>

Template/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .header{
            height: 48px;
        }
    </style>
</head>
<body>
    <div class="header">

        <div style="float: right">{{ username }}</div>
        <div style="float: right"><a href="/app01/logout/">注销</a></div>
    </div>
    <div style="height: 500px;background-color: #ddd"></div>
</body>
</html>

 

缓存

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

一、配置settings.py

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
        'LOCATION': os.path.join(BASE_DIR, 'cache'),
        'TIMEOUT': 600,
        'OPTIONS': {
            'MAX_ENTRIES': 1000
        }
    }
}

2、应用

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

@cache_page(60 * 15)
def func(request):
    return HttpResponse('xxx')

更多:

  https://docs.djangoproject.com/en/1.9/topics/cache/
  http://djangobook.py3k.cn/2.0/chapter15/

 

cookie和session >>> 用户登录验证、注销

一、操作Cookie

  获取cookie:request.COOKIES[key]

  设置cookie:response.set_cookie(key,value)

由于cookie保存在客户端的电脑上,所以,jquery也可以操作cookie。

<script src='/static/js/jquery.cookie.js'></script>
$.cookie("list_pager_num", 30,{ path: '/' }); 

二、操作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失效策略。

更多见:

  https://docs.djangoproject.com/en/1.9/topics/http/sessions/

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

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

三、应用

def login(func):
    def wrap(request, *args, **kwargs):
        # 如果未登陆,跳转到指定页面
        if request.path == '/test/':
            return redirect('http://www.baidu.com')
        return func(request, *args, **kwargs)
    return wrap

   

PS:
cookie: 保存于本机  ===》 本地某个目录下的文件
session: 保存于服务器


数据库同步:
python manage.py makemigrations
python manage.py migrate

request.session.get('k1')
request.session['k1'] = 'v1'

默认过期时间:2周
    自定义设置:settings.py

总结:
session
    用来保存用户会话信息,依赖于cookie
    超时时间:写入cookie时,设置一个超时时间

  

 

Form(*)

django中的Form一般有两种功能:

  1、用户提交数据验证
  2、生成html标签
前端JS表单验证+后端验证 ====》 两套结合使用

Form

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import re
from django import forms
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 PublishForm(forms.Form):

    user_type_choice = (
        (0, u'普通用户'),
        (1, u'高级用户'),
    )

    user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,
                                                                  attrs={'class': "form-control"}))

    title = forms.CharField(max_length=20,
                            min_length=5,
                            error_messages={'required': u'标题不能为空',
                                            'min_length': u'标题最少为5个字符',
                                            'max_length': u'标题最多为20个字符'},
                            widget=forms.TextInput(attrs={'class': "form-control",
                                                          'placeholder': u'标题5-20个字符'}))

    memo = forms.CharField(required=False,
                           max_length=256,
                           widget=forms.widgets.Textarea(attrs={'class': "form-control no-radius", 'placeholder': u'详细描述', 'rows': 3}))

    phone = forms.CharField(validators=[mobile_validate, ],
                            error_messages={'required': u'手机不能为空'},
                            widget=forms.TextInput(attrs={'class': "form-control",
                                                          'placeholder': u'手机号码'}))

    email = forms.EmailField(required=False,
                            error_messages={'required': u'邮箱不能为空','invalid': u'邮箱格式错误'},
                            widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'邮箱'}))

View

def publish(request):
    ret = {'status': False, 'data': '', 'error': '', 'summary': ''}
    if request.method == 'POST':
        request_form = PublishForm(request.POST)
        if request_form.is_valid():
            request_dict = request_form.clean()
            print request_dict
            ret['status'] = True
        else:
            error_msg = request_form.errors.as_json()
            ret['error'] = json.loads(error_msg)
    return HttpResponse(json.dumps(ret))

扩展:ModelForm

在使用Model和Form时,都需要对字段进行定义并指定类型,通过ModelForm则可以省去From中字段的定义

class AdminModelForm(forms.ModelForm):
      
    class Meta:
        model = models.Admin
        #fields = '__all__'
        fields = ('username', 'email')
          
        widgets = {
            'email' : forms.PasswordInput(attrs={'class':"alex"}),
        }

总结:
    1、创建类(forms.Form)
    2、页面根据类的对象自动创建html标签
    3、提交,request.POST
        封装到一个类的对象里 obj = UserInfo(request.POST)
    4、用户输入是否合法
        obj.is_valid
    5、 只要有不合法
        obj.errors

  

DEMO

Settings.py

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os

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.8/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'dgwet1wf#!wo)cr1_y0tpxx5txvxug-upi2$&@n_ojq66pyl2a'

# 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_CLASSES = (
    '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',
    'django.middleware.security.SecurityMiddleware',
)

ROOT_URLCONF = 's11day18_form.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 = 's11day18_form.wsgi.application'

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

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

# Internationalization
# https://docs.djangoproject.com/en/1.8/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.8/howto/static-files/

STATIC_URL = '/static/'
STATICFILES_DIRS =(
    os.path.join(BASE_DIR, "static"),
)
TEMPLATE_DIRS = (
    os.path.join(BASE_DIR, 'templates'),

Urls.py
from django.conf.urls import include, url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^user_list/$', views.user_list),
    url(r'^ajax_data/$', views.ajax_data),
    url(r'^ajax_data_set/$', views.ajax_data_set),
]

app01/views.py

#coding:utf-8
from django.shortcuts import render
# Create your views here.
from django import forms
from django.core.exceptions import ValidationError
import re
from django.shortcuts import HttpResponse

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 UserInfo(forms.Form):
    user_type_choice = (
        (0, u'普通用户'),
        (1, u'高级用户'),
    )
    user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,
                                                               attrs={'class': "form-control"}))
    email = forms.EmailField(error_messages={'required': u'邮箱不能为空'})
    host = forms.CharField(error_messages={'required': u'主机不能为空'})
    port = forms.CharField(error_messages={'required': u'端口不能为空'})
    mobile = forms.CharField(validators=[mobile_validate, ],
                             error_messages={'required': u'手机不能为空'},
                             widget=forms.TextInput(attrs={'class': "form-control",
                                                          'placeholder': u'手机号码'}))
    memo = forms.CharField(required=False,
                           widget=forms.Textarea(attrs={'class': "form-control",
                                                        'placeholder': u'备注'})
                           )

def user_list(request):
    obj = UserInfo()
    if request.method == "POST":
        user_input_obj = UserInfo(request.POST)
        if user_input_obj.is_valid():
            data = user_input_obj.clean()
            print data
        else:
            error_msg = user_input_obj.errors.as_data()
            return render(request, 'user_list.html', {'obj': user_input_obj, 'errors': error_msg})
    return render(request, 'user_list.html', {'obj': obj})
    #
    # host = request.POST.get('host')
    # port = request.POST.get('port')
    # email = request.POST.get('email')
    # mobile = request.POST.get('mobile')

    # 输入不能为空,()
    # email = 7676767675765
    # mobile = 7676767675765
    # ip = 7676767675765


def ajax_data(request):
    print request.POST
    return HttpResponse('ok')
import json
def ajax_data_set(request):
    ret = {'status': True, 'error':""}
    try:
        print request.POST
    except Exception,e:
        ret['status'] = False
        ret['error'] = str(e)

    return HttpResponse(json.dumps(ret))

app01/templatetags/form_tag.py

#!/usr/bin/env python
# -*- coding:utf-8 -*-

from django import template
from django.utils.safestring import mark_safe
from django.template.base import resolve_variable, Node, TemplateSyntaxError

register = template.Library()

from django import template
from django.utils.safestring import mark_safe
from django.template.base import resolve_variable, Node, TemplateSyntaxError

register = template.Library()

@register.simple_tag
def error_message(arg):
    if arg:
        return arg[0][0]
    else:
        return ''

Templates/user_list.html

{% load form_tag %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>

    <style>
        .form-control{
            background-color: red;
        }
    </style>
</head>
<body>

    <form action="/user_list/" method="post">
        <p>用户类型:{{ obj.user_type }}
            <span>{% error_message errors.user_type %}</span>
        </p>
        <p>主机:{{ obj.host }}
            <span>{% error_message errors.host %}</span>
        </p>
        <p>端口:{{ obj.port }} <span>{{ errors.port }}</span></p>
        <p>邮箱:{{ obj.email }} <span>{{ errors.email }}</span></p>
        <p>手机:{{ obj.mobile }} <span>{{ errors.mobile }}</span></p>
        <p>备注:{{ obj.memo }} <span>{{ errors.memo }}</span></p>

        <input type="submit"  value="submit" />

    </form>

    <input type="button" onclick="AjaxSubmit();" value="Ajax提交" />
    <input type="button" onclick="AjaxSubmitSet();" value="Ajax提交集合" />
    <table border="1">
        <thead>
            <tr>
                <th>主机名</th>
                <th>端口</th>
            </tr>
        </thead>
        <tbody id="tbd">
            <tr>
                <td>1.1.1.1</td>
                <td>9999</td>
            </tr>
            <tr>
                <td>1.1.1.2</td>
                <td>9998</td>
            </tr>
        </tbody>
    </table>

    <script src="/static/jquery-1.8.2.min.js"></script>
    <script>
        function AjaxSubmit(){
            var host = "1.1.1.1";
            var port = "9999";
            $.ajax({
                url: "/ajax_data/",
                type: 'POST',
                data: {h:host, p:port},
                success: function(arg){
                }
            });
        }

        function AjaxSubmitSet(){
            var array_users= [
                {'username': 'alex', 'age': 18},
                {'username': 'rain', 'age': 16},
                {'username': 'eric', 'age': 17}
            ];
            $.ajax({
                url: "/ajax_data_set/",
                type: 'POST',
                tradition: true,
                data: {data: JSON.stringify(array_users)},
                success: function(arg){
                    // json.loads
                    var callback_dict = $.parseJSON(arg);
                    if(callback_dict.status){
                        alert('成功');
                    }else{
                        alert(callback_dict.error);
                    }
                }
            });
        }
    </script>
</body>
</html>

  

Ajax(*)

一、简介

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、普通表单

veiw中设置返回值:
  return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))  
     或者
     return render(request, 'xxx.html', data)
html中设置Token:
  {% csrf_token %}

2、Ajax

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

view.py

from django.template.context import RequestContext

# Create your views here.

def test(request):

    if request.method == 'POST':
        print request.POST
        return HttpResponse('ok')

    return  render_to_response('app01/test.html',context_instance=RequestContext(request))

text.html

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>

<body>

    {% csrf_token %}

    <input type="button" onclick="Do();"  value="Do it"/>

    <script src="/static/plugin/jquery/jquery-1.8.0.js"></script>
    <script src="/static/plugin/jquery/jquery.cookie.js"></script>
    <script type="text/javascript">
        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 Do(){

            $.ajax({
                url:"/app01/test/",
                data:{id:1},
                type:'POST',
                success:function(data){
                    console.log(data);
                }
            });
        }

    </script>

</body>
</html>

更多:https://docs.djangoproject.com/en/dev/ref/csrf/#ajax

 

参考博客:

http://www.cnblogs.com/wupeiqi/articles/5237704.html

http://www.cnblogs.com/wupeiqi/articles/5246483.html

 

posted @ 2016-03-14 15:21  korala!  阅读(785)  评论(0)    收藏  举报