概要
一、路由系统
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 = "
It is now %s." % nowreturn 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 %} {{ item }} {% 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 = "" %(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\d+)/(?P\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(\w+))/(?P(\w+))/(?P(\d+))/(?P(\d+))/$',process),
('^(?P(\w+))/(?P(\w+))/(?P(\d+))/$',process),
('^(?P(\w+))/(?P(\w+))/$',process),
('^(?P(\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)
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\d+)/(?P\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
Template/index.html
.header{
height: 48px;
}
缓存
由于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。
$.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 %}
.form-control{
background-color: red;
}
用户类型:{{ obj.user_type }}
{% error_message errors.user_type %}
主机:{{ obj.host }}
{% error_message errors.host %}
端口:{{ obj.port }} {{ errors.port }}
邮箱:{{ obj.email }} {{ errors.email }}
手机:{{ obj.mobile }} {{ errors.mobile }}
备注:{{ obj.memo }} {{ errors.memo }}
主机名端口
1.1.1.199991.1.1.29998function 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);
}
}
});
}
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中设置返回值:
returnrender_to_response('Account/Login.html',data,context_instance=RequestContext(request))
或者
returnrender(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
{% csrf_token %}
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);
}
});
}
更多:https://docs.djangoproject.com/en/dev/ref/csrf/#ajax
参考博客: