一、Django概述

Django大而全;

创建Django工程:django-admin startproject sitename

创建django之后生成的目录结构如下:

Project

    Project

        settings

        url

        wsgi

    web

        model

        views

        test

        admin

    administrator

Django工程目录结构

D:\python_scripts\s11day17_Django>python manage.py startapp app01  #创建app;一个app是一个完整的软件或者功能;

app下面的文件:

    models:对数据库操作的;

    views:函数放置的文件;

    test:做测,忽略;

    admin:Django的后台管理平台

app下面的文件

http://127.0.0.1:8000/admin      访问Django的后台管理平台;

可以创建admin后台管理的账户,账户默认存在于数据库下,存放位置在settings中定义如下:

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
} 下面写一个http请求,urls是路由系统:
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^home/',views.home), #一个url对应一个函数,函数存在于app的views中
]

urls

views中的函数如下:
from django.shortcuts import render

# Create your views here.
from django.shortcuts import HttpResponse
def home(request): #此处的request是必须的
return HttpResponse('ok')

views

D:\python_scripts\s11day17_Django>python manage.py runserver 127.0.0.1:8009    #启动Django程序;或者在Django工程的edit下面配置端口http://127.0.0.1:8009/home/    #访问

-----http请求完毕;

Django模板渲染
在app的views中添加的函数返回html文件内容,如下:
#!/usr/bin/env python
#coding:utf-
from django.shortcuts import render # Create your views here.
from django.shortcuts import HttpResponse
def home(request):
#return HttpResponse('ok')
'''render内部找到home.html,读取html返回给用户,render和跨站请求伪造相关'''
return render(request,'home.html')

home.html

可以看到默认到templates模块下找该文件了;那么程序如何知道html文件时在templates下面去找的呢?事实上,是在settings配置文件下面设置的啦;不同版本的Django配置有所不同;
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')]
,


就OK拉~~~~~~~

Django内部也使用jinjia2模板:
views内容如下:
#!/usr/bin/env python
#coding:utf-
# Create your views here.
from django.shortcuts import render
from django.shortcuts import HttpResponse,render_to_response
def home(request):
#return HttpResponse
#return render_to_response(request,'home.html')
'''render内部找到home.html,读取html返回给用户'''
dic ={'name':'Charles','age':}
return render(request,'home.html',dic)

views

home.html文件如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h1>Home</h1>
<h2>{{ name }}</h2>
<h2>{{ age }}</h2>
</body>
</html>

home.html

模板渲染完毕

模板语言和自定义simple_tag
home.html模板语言:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h1>Home</h1>
<h2>{{ name }}</h2>
<h2>{{ age }}</h2>
<ul>
{% for item in user_list %}
<li>{{ item }},{{ forloop.first }}</li>
{% endfor %}
</ul>
</body>
</html>

home.html

views内容如下:
#!/usr/bin/env python
#coding:utf-
# Create your views here.
from django.shortcuts import render
from django.shortcuts import HttpResponse,render_to_response
def home(request):
#return HttpResponse
#return render_to_response(request,'home.html')
'''render内部找到home.html,读取html返回给用户'''
dic ={'name':'Charles','age':,'user_list':{'Charles','wahaha','Rain'}}
return render(request,'home.html',dic)

view

尽管模板语言可以提供部分函数,实现一部分功能,但是有些需要我们自定义区实现:
1、在app中创建templatetags和文件

2、

3、

Django之母版:
什么叫做母版:红色部分在其他页面走不回改变,那么就没有必要再任何页面写这些内容啦~~~,可以创建母版实现啦,类似于类的继承

那么如何实现母版以及继承母版:

master下的m1为母版:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}{% endblock %}</title>
<style>
.header{
height: 48px;
background-color: red;
}
.body{
background-color: #dddddd;
}
.body .menu{
background-color: green;
float: left;
width: %;
}
.body .content{
background-color: darkgoldenrod;
float: left;
width: %;
}
</style>
</head>
<body>
<div class="header">LOGO</div>
<div class="body">
<div class="menu">左侧菜单</div>
<div class="content">
{% block content %}{% endblock %}
</div>
</div>
</body>
</html>

m1.html

son1继承m1:
{% extends "master/m1.html" %}
{% block content %}
<h1></h1> {% include "include/input_group.html" %}
{% include "include/haha.html" %}
{% endblock %} {% block title %}
老男人
{% endblock %}

son1.html

son1同样继承include下的两个html文件内容;include防止在子html的什么位置,内容就显示在什么地方;

母版和include的应用场景:
母版:总体布局使用;include在局部功能上需要别的页面继承的时候使用:

views的内容:
#!/usr/bin/env python
#coding:utf-
# Create your views here.
from django.shortcuts import render
from django.shortcuts import HttpResponse,render_to_response def son(request):
return render(request,'son1.html')
def home(request):
#return HttpResponse
#return render_to_response(request,'home.html')
'''render内部找到home.html,读取html返回给用户'''
dic ={'name':'Charles','age':,'user_list':{'Charles','wahaha','Rain'}}
return render(request,'home.html',dic)

views

urls的内容:
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^home/',views.home),
url(r'^son/',views.son),
]

urls

Django静态文件的配置:
比如上面html母版中的CSs渲染的部分,需要放置到静态文件夹中,然后在母版中导入即可;
创建static静态文件夹

在settings中指明(需要一一对应)文件的路径

这样母版m1的内容就为:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}{% endblock %}</title>
<link rel="stylesheet" href="/static/css/commons.css"/>
{% block css %}{% endblock %} #也可以设置css文件的母版
</head>
<body>
<div class="header">LOGO</div>
<div class="body">
<div class="menu">左侧菜单</div>
<div class="content">
{% block content %}{% endblock %}
</div>
</div>
<script type="text/javascript"> </script>
{% block js %}{% endblock %} #设置js文件的母版
</body>
</html> commons.ss的内容为:
.clearfix:after{
content: ".";
visibility: hidden;
display: block;
height: ;
clear: both;
}
.header{
height: 48px;
background-color: red;
}
.body{
background-color: #dddddd;
}
.body .menu{
background-color: green;
float: left;
width: %;
}
.body .content{
background-color: darkgoldenrod;
float: left;
width: %;
}

m1.html

settings的内容如下:
STATIC_URL = '/static/'
STATICFILES_DIRS=(
os.path.join(BASE_DIR,'static'),
)
整个程序访问流程如下:请求到url-->views-->templates中找html-->数据和html模板渲染-->得到字符串返回给用户

下面开发一个Django用户登录实例:
1、拷贝jQuery和bootstrap插件到静态文件目录下:

2、增加登录模块(html文件),增加表单的name

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}{% endblock %}</title>
<link rel="stylesheet" href="/static/css/commons.css"/>
{% block css %}{% endblock %} #也可以设置css文件的母版
</head>
<body>
<div class="header">LOGO</div>
<div class="body">
<div class="menu">左侧菜单</div>
<div class="content">
{% block content %}{% endblock %}
</div>
</div>
<script type="text/javascript"> </script>
{% block js %}{% endblock %} #设置js文件的母版
</body>
</html> commons.ss的内容为:
.clearfix:after{
content: ".";
visibility: hidden;
display: block;
height: ;
clear: both;
}
.header{
height: 48px;
background-color: red;
}
.body{
background-color: #dddddd;
}
.body .menu{
background-color: green;
float: left;
width: %;
}
.body .content{
background-color: darkgoldenrod;
float: left;
width: %;
}

login.html

3、views增加login函数
def login(request):
#如果是get请求,get请求表示请求页面
#如果是POST,检验用户输入;POST表示向页面提交内容
print request.method
if request.method == 'POST':
input_email=request.POST['email']
input_pwd = request.POST['pwd']
if input_email == 'Charles@qq.com' and input_pwd == "":
from django.shortcuts import redirect
return redirect("https://www.baidu.com") #跳转到别的页面,如果想要跳转到别的函数,比如son,return redirect("/son/")
else:
return render(request,'login.html',{'status':'用户名或密码错误'}) #否则显示错误
return render(request,'login.html')

views

4、urls的内容
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^home/',views.home),
url(r'^son/',views.son),
url(r'^login/',views.login),
]

urls

model基本操作之增删改查
Django提供了ORM,可以使用类来创建数据库表和字段:

命令python manage.py makemigations 和python manage.py migrate可以创建数据表,生成0001.initial.py文件(注意都是在app01中操作的)
2、settings内容:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01', #注册该app
]
3、urls内容
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^home/',views.home),
url(r'^son/',views.son),
url(r'^login/',views.login),
url(r'^index/',views.index),
]

urls

4、views中定义index函数:
#!/usr/bin/env python
#coding:utf-
# Create your views here.
from django.shortcuts import render
from django.shortcuts import HttpResponse,render_to_response def son(request):
return render(request,'son1.html')
def home(request):
#return HttpResponse
#return render_to_response(request,'home.html')
'''render内部找到home.html,读取html返回给用户'''
dic ={'name':'Charles','age':,'user_list':{'Charles','wahaha','Rain'}}
return render(request,'home.html',dic) def login(request):
#如果是get请求
#如果是POST,检验用户输入
print request.method
if request.method == 'POST':
input_email=request.POST['email']
input_pwd = request.POST['pwd']
if input_email == 'Charles@qq.com' and input_pwd == "":
from django.shortcuts import redirect
return redirect("/index/")
else:
return render(request,'login.html',{'status':'用户名或密码错误'})
return render(request,'login.html') def index(request):
#数据库取数据
#数据和HTML渲染
from app01 import models
if request.method =="POST":
input_em = request.POST['em']
input_pw = request.POST['pw']
models.UserInfo.objects.create(email=input_em,pwd=input_pw) #增加数据 #models.UserInfo.objects.filter(email=input_em).delete() #删除数据
#models.UserInfo.objects.filter(email=input_em).update(pwd=) #更新数据
#获取UserInfo表中的所有的数据
user_info_list = models.UserInfo.objects.all() #查收,在模板中循环
#user_info_list列表,列表的元素为一行;email,pwd;
return render(request,'index.html',{'user_info_list':user_info_list})

views

4、模板index.html内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/index/" method="post">
<input type="text" name="em"/>
<input type="text" name="pw"/>
<input type="submit" name="添加"/>
</form>
<table border="">
<thead>
<tr>
<th>邮箱</th>
<th>密码</th>
</tr>
</thead>
<tbody>
{% for line in user_info_list %}
<tr>
<td>{{ line.email }}</td>
<td>{{ line.pwd }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>

index.html


--权限登录管理系统
、登录(装饰器判断用户是否已经登录--可选,用户密码MD5)
、注册(检测用户是否已经存在,onblur+ajax光标跳出输入框时)
、注销(忽略)
、用户管理(From表单)
重置密码
创建用户(单条,批量)
修改用户信息
、权限控制(可选)
用户是否可以访问URL

作业

内容:
一、URL路由系统
二、中间件
三、Model:数据库的操作(重点)
1、创建表
2、操作表数据
四、Form(重点)
1、用户提交数据验证
2、生成html标签
五、cookie和session
六、跨站请求伪造和跨站脚本攻击
七、Ajax操作(重点)
八、Admin
九、缓存
十、自定义分页(重点) 下面分开介绍: Django请求生命周期

路由系统详细介绍:

分页的概念:

点击是url发生变化;

那么如何实现分页:路由系统函数传参

1、urls的内容:
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^app01/', include("app01.urls")),
url(r'^index/$', views.index),
#url(r'^user_list/(\d+)$', views.user_list), #django内部默认将url以/为分割线将url分割,传入参数,默认是按照顺序传入参数的
#url(r'^user_list/(\d+)/(\d+)$', views.user_list),
url(r'^user_list/(?P<v1>\d+)/(?P<v2>\d+)$', views.user_list), #要灵活传入参数,设置(?P<v1>\d+),v1表示key,传入的参数为value url(r'^$', views.index), #放置到最后
]

urls

2、views的内容
from django.shortcuts import render,HttpResponse

# Create your views here.
def index(request):
return HttpResponse('OK') def user_list(request,v2,v1): #将key传入
print v1,v2
return HttpResponse(v1+v2)

views

对于不同的app而言,如何实现输入url为app01的请求发送到app01上面:

1、urls的内容
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^app01/', include("app01.urls")), #发送的对应app下的urls中
url(r'^index/$', views.index),
#url(r'^user_list/(\d+)$', views.user_list),
#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), #放置到最后,为路由系统的默认处理函数,类似于404
]

urls

2、在app01下新建urls文件

3、settings
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01'
]
访问:

Django路由系统完毕!!!

 基于反射的路由系统:多有的函数都放置在一个.py文件中;

中间件:

Django提供的中间件如下:

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

自定义中间件来解析中间件工作流程:

1、创建中间件文件夹以及文件

middle文件内容为:

#!/usr/bin/env python
# _*_ coding:utf- _*_
class mmm(object):
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
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):
pass

middle.py

2、注册中间件到settings文件中

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',
'middleware.middle.mmm',
'middleware.middle.xxx',
] 3、views内容如下:
from django.shortcuts import render,HttpResponse

# Create your views here.
def index(request):
print 'index'
return HttpResponse('OK') def user_list(request,v2,v1):
print v1,v2
return HttpResponse(v1+v2) 4、访问如下:

process_expection方法在views.index函数执行出错的时候触发;

总结:
1、客户端发出请求
2、Django自动去settings中找MIDDLEWARE_CLASSES,列表或元组
process_request_list = []
process_view_list = []
process_response_list = []
process_exception_list = []
3、for 类 in MIDDLEWARE_CLASSES:
obj=类()
if obj 里有process_request方法: process_request_list.append(obj.process_request_list)
        if obj 里有process_view方法:

         process_view_list.append(obj.process_request_list)
        views中的函数:
    if obj 里有process_response方法:
         process_response_list .append(obj.process_request_list)
中间件是一个类,类中的方法名必须是固定的

1、 #process_request和process_view没有返回值,是正常的执行过程(蓝色部分)
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):
pass
2、request函数直接返回值,为红色部分
3、灰色部分表示函数执行出错的时候的执行流程; 下面展示process_exception;
settings的内容:
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',
'middleware.middle.mmm',
'middleware.middle.xxx',
] middle.py内容:
#!/usr/bin/env python
# _*_ coding:utf-8 _*_ from django.shortcuts import render,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 'View中出错了返回'
return HttpResponse('View中出错了,返回')
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('View中出错了,不返回') #第二个函数返回,将不会执行第一个函数

直接返回

midele.py第二个函数没有返回值:那么两个函数执行都会执行;
#!/usr/bin/env python
# _*_ coding:utf-8 _*_ from django.shortcuts import render,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 'View中出错了返回'
return HttpResponse('View中出错了,返回')
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中出错了,但是不返回'

总结:process_exception函数根据setting的设置从下往上执行,如果有返回值,就不会执行后面的类中的process_exception函数;

缓存介绍:
将DB和templates中拿到的渲染后的字符串,放置到缓存中,缓存的介质可以为文件、memcached、redis、数据库;

使用缓存步骤:
1、views中添加如下函数:
def cache_page(request):
current = str(time.time())
return HttpResponse(current) app01\urls内容为:
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^index/', views.index),
url(r'^cache/', views.cache_page),
]
每次post请求的时候,其内容都会重新渲染,显示不同的字符串

3、在settings配置文件中添加如下内容:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': os.path.join(BASE_DIR, 'cache'), #缓存内容使用文件,存放在文件里面
'TIMEOUT': 600,
'OPTIONS': {
'MAX_ENTRIES': 1000
}
}
}
4、给views中的函数增加装饰器
from django.shortcuts import render,HttpResponse
import time
from django.views.decorators.cache import cache_page
@cache_page(60 * 15) #表示每15分钟缓存更新一次;
def cache_page(request):
current = str(time.time())
return HttpResponse(current)

下面介绍cookie和session:

1、cookie是一个字符串,保存于本地的电脑上;session保存于服务器

因为http是短连接,第一次访问之后就会断开,那么第二次访问的时候如何知道之前该用户已经访问过了;比如要访问jd的页面,第一次登陆之后,服务器端会向客户端浏览器下发一个字符串,第二次用户访问的时候就可以携带者这个字符串来访问了,这样服务器端就认为已经登陆过了,就可以允许用户点击购物车等其他链接了;那么问题来了,服务器如何根据字符串判断用户已经访问过了?

上述步骤中1和2是web框架自己实现的,第3步中,对用户的session设置对应的任意值是程序员自己设置的,比如,此处可以设置为是否登录is_login;具体实现如下:
a、app01中views增加函数如下:
def login(request):
if request.method=='POST':
username = request.POST.get('username')
pwd = request.POST.get('pwd')
if username == 'Charles' and pwd=='123':
request.session['IS_LOGIN'] = True
return redirect('/app01/home/') return render(request,'login.html') def home(request):
'''
如果用户已经登陆
'''
is_login = request.session.get('IS_LOGIN',False)
if is_login:
return HttpResponse('order')
else:
return redirect('/app01/login/')
b、app01\urls
from django.conf.urls import url,include
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),
]
c、templates中定义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> 注意:session是存在于数据库中的,如果变化session内容(request.session['IS_LOGIN'] = True),那么就需要重新同步数据库:D:\python_scripts\s11day18_Django>python manage.py migrate
d、如果用户名和密码不正确,就会报403错误,需要禁止掉csrf
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',
'middleware.middle.mmm',
'middleware.middle.xxx',
]

注意:默认情况下,Django的session存放在数据库中;


这样我们可以通过自定义session,来根据输入的不同的用户,显示不同的值;
db = {
'Charles':'11111',
'eric':'22222',
}
def login(request):
if request.method=='POST':
username = request.POST.get('username')
pwd = request.POST.get('pwd')
if username == 'Charles' and pwd=='123':
request.session['IS_LOGIN'] = True
request.session['USERNAME']='Charles'
return redirect('/app01/home/')
elif username=='eric' and pwd =='123':
request.session['IS_LOGIN'] = True
request.session['USERNAME']='eric'
return redirect('/app01/home/') return render(request,'login.html') def home(request):
'''
如果用户已经登陆
'''
is_login = request.session.get('IS_LOGIN',False)
if is_login:
username = request.session.get('USERNAME',False)
data = db[username]
return HttpResponse(data)
else:
return redirect('/app01/login/')
如何在右上角设置登录和注销的按钮:在登录之后,将用户名和注销的按钮显示在右上角
a、app01/views增加函数:
views

def login(request):
if request.method=='POST':
username = request.POST.get('username')
pwd = request.POST.get('pwd')
if username == 'Charles' and pwd=='':
request.session['IS_LOGIN'] = True
request.session['USERNAME']='Charles'
return redirect('/app01/home/')
elif username=='eric' and pwd == '':
request.session['IS_LOGIN'] = True
request.session['USERNAME']='eric'
return redirect('/app01/home/') return render(request,'login.html') def home(request):
'''
如果用户已经登陆
'''
is_login = request.session.get('IS_LOGIN',False)
if is_login:
username = request.session.get('USERNAME',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']
return redirect('/app01/login')

b、templates下增加html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>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> </body>
</html>

home.html

c、app01/urls内容:
from django.conf.urls import url,include
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),
]

urls

cookie可是设置超时时间,在settings文件中,增加字段:SESSION_COOKIE_AGE = 5,表示cookie超时时间为5秒,也可以设置关闭会话后,删除cookie;上述页面在cookie删除之后会自动跳转到登录页面(然而我测试没有成功/(ㄒoㄒ)/~~)
cookie和session到此结束,O(∩_∩)O~;

下面介绍Django From;
作用:1、用户提交数据验证;2、生成html标签;
为什么要使用From,看下面:
a、app01/views中定义函数:
def user_list(request):
# host = request.POST.get('host')
# port = request.POST.get('port')
#email = request.POST.get('email')
#mobile = request.POST.get('mobile')
#'''上述字段是由用户输入的,程序员需要判断:1、用户的每一项输入不能为空;2、用户输入的字段是合法的字符按;这样需要做大量的
#工作才能够实现'''
#return render(request,'user_list.html')

views.py

b、定义html文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<form action="/user_list/" method="post"> {% comment %}此处的action必须是以/开头和结尾{% endcomment %}
{% comment %} <input type="text" name="host"/>
<input type="text" name="port"/>
<input type="text" name="email"/>
<input type="text" name="mobile"/>
<input type="submit" value="submit" />{% endcomment %}
</form>
</body>
</html>

user_list.html

上述例子中需要程序员需要解决两个问题:1、严重用户输入的内容各项不能为空;2、验证用户输入的各项内容是否合法;这两项工作都需要做大量的工作;而From不但可以自动实现验证功能,还可以自动生成html标签;  除此以外,前端js验证如果js被客户端浏览器禁用掉的话,无法使用,所有最好前端和后台验证都各写一套;

前端js实现验证功能实例如下:

具体实现如下:

a、views的内容:

#!/usr/bin/env python
#coding:utf-
from django.shortcuts import render # Create your views here. from django import forms class UserInfo(forms.Form):
#email = forms.EmailField(required=False)
email = forms.EmailField()
host = forms.CharField()
port = forms.CharField()
mobile=forms.CharField() def user_list(request):
obj = UserInfo()
if request.method=="POST":
user_input_obj = UserInfo(request.POST) #用户输入的各项字段的值
#print user_input_obj.is_valid()
if user_input_obj.is_valid(): #判断各项输入是否合法
data = user_input_obj.clean() #用户输入的各项的值,为字典类型
print data
else:
error_msg = user_input_obj.errors
print error_msg
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')
#'''上述字段是由用户输入的,程序员需要判断:1、用户的每一项输入不能为空;2、用户输入的字段是合法的字符按;这样需要做大量的
#工作才能够实现'''
#return render(request,'user_list.html')

app01/views

b、user_list.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<form action="/user_list/" method="post"> {% comment %}此处的action必须是以/开头和结尾{% endcomment %}
<p>主机: {{ obj.host }}<span>{{ 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>
<input type="submit" value="submit" />
{% comment %} <input type="text" name="host"/>
<input type="text" name="port"/>
<input type="text" name="email"/>
<input type="text" name="mobile"/>
<input type="submit" value="submit" />{% endcomment %}
</form>
</body>
</html>

user_list.html

c、

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

禁止csrf功能

"""s11day18_form URL Configuration

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

urls

输入合法与不合法显示信息如下:

Django From定制化
在上面的例子中,我们只是简单实现了from自动生成html标签和from表单验证的功能,那么对于一些个性化的表单验证和错误信息的展示,该如何实现呢?
1、views的内容:
#!/usr/bin/env python
#coding:utf-
from django.shortcuts import render # Create your views here. from django import forms
from django.core.exceptions import ValidationError
import re def mobile_validate(value):
mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$') #个性化定制验证功能,是否符合手机号码规则
if not mobile_re.match(value):
raise ValidationError('手机号码格式错误') class UserInfo(forms.Form): #通过定义类。实现获取用户输入表单的信息
user_type_choice = (
(, u'普通用户'),
(, u'高级用户'),
)
user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice, #实现select选择功能
attrs={'class': "form-control"})) #email = forms.EmailField(required=False)
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,
max_length=,
widget=forms.Textarea(attrs={'class': "form-control", #attrs表示想input中添加属性
'placeholder': u'备注'})) def user_list(request):
obj = UserInfo()
if request.method=="POST":
user_input_obj = UserInfo(request.POST)
#print user_input_obj.is_valid()
if user_input_obj.is_valid():
data = user_input_obj.clean()
print data
else:
error_msg = user_input_obj.errors
print error_msg
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')
#'''上述字段是由用户输入的,程序员需要判断:1、用户的每一项输入不能为空;2、用户输入的字段是合法的字符按;这样需要做大量的
#工作才能够实现'''
#return render(request,'user_list.html')

views.py

2、html文件内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
.form-control{ {% comment %}通过attr增加的属性,可以在html中加以利用,或者在这里可以自己定义属性,实现渲染页面渲染功能{% endcomment %}
background-color: red;
}
</style>
</head>
<body>
<form action="/user_list/" method="post"> {% comment %}此处的action必须是以/开头和结尾{% endcomment %}
<p>用户类型: {{ obj.user_type }}<span>{{ errors.user_type }}</span></p>
<p>主机: {{ obj.host }}<span>{{ 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.mome }}</span></p>
<input type="submit" value="submit" /> </form>
</body>
</html>

user_list.html

总结:

、创建类from.From
、页面根据类的对象自动创建html标签
、提交数据,request.POST
封装到一个类的对象里 obj=UserInfo(request.POST)
、用户输入是否合法
obj.is_valid()
、全部合法的话,得到用户输入数据 obj.clean()
、只要有一个不合法,产生不合法的错误提示信息 obj.errors 注意:自定义的UserInfo类中可以写入select插件,可以通过attr添加属性,可以通过正则表达式这是输入数据的格式;

总结

Form漂亮的显示错误信息

form默认生成的html错误信息是ul,前面带黑点;使用as_data()来讲ul转换为原生的字符串;
def user_list(request):
obj = UserInfo()
if request.method=="POST":
user_input_obj = UserInfo(request.POST)
#print user_input_obj.is_valid()
if user_input_obj.is_valid():
data = user_input_obj.clean()
print data
else:
error_msg = user_input_obj.errors.as_data() #默认为ul,前面加黑点,使用as_data()将其转换为原生的字符串显示
print error_msg
return render(request,'user_list.html',{'obj':user_input_obj,'errors':error_msg})
return render(request,'user_list.html',{'obj':obj}

views

上述错误信息是包含在字典当中,但是在模板语言中,无法通过索引如host[0][0]来获取到错误信息,这时候就需要借助是、simple_tag来实现通过python的索引类获取错误信息了;
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01',
]

settings

#!/usr/bin/env python
# -*- coding:utf- -*- 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[][] #通过索引取值
else:
return ''

form_tag

{% load form_tag %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
.form-control{ {% comment %}通过attr增加的属性,可以在html中加以利用,或者在这里可以自己定义属性,实现渲染页面渲染功能{% endcomment %}
background-color: red;
}
</style>
</head>
<body>
<form action="/user_list/" method="post"> {% comment %}此处的action必须是以/开头和结尾{% endcomment %}
<p>用户类型: {{ obj.user_type }}
<span>{% error_message errors.user_type %}</span>
</p>
<p>主机: {{ obj.host }}\
{% comment %}{% errors.host[][] %}{% endcomment %} {% comment %} //模板语言不支持索引取值。所以需要构造simple_tag在python中来实现索引取值//{% endcomment %}
<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.mome }}</span></p>
<input type="submit" value="submit" /> </form>
</body>
</html>

user_list.html

具体实现可以参考:

ModelForm:

如果想要将数据库中的数据到前端进行展示;也就是利用model做出类似于django admin类似效果的东西;

下面介绍Ajax:

Ajax发送简单数据类型

可以将数据保存之后发送到后台,后台更新就可以了;

1、导入jQuery

{% load form_tag %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
.form-control{ {% comment %}通过attr增加的属性,可以在html中加以利用,或者在这里可以自己定义属性,实现渲染页面渲染功能{% endcomment %}
background-color: red;
}
</style>
</head>
<body>
<form action="/user_list/" method="post"> {% comment %}此处的action必须是以/开头和结尾{% endcomment %}
<p>用户类型: {{ obj.user_type }}
<span>{% error_message errors.user_type %}</span>
</p>
<p>主机: {{ obj.host }}\
{% comment %}{% errors.host[][] %}{% endcomment %} {% comment %} //模板语言不支持索引取值。所以需要构造simple_tag在python中来实现索引取值//{% endcomment %}
<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.mome }}</span></p>
<input type="submit" value="submit" /> </form>
<input type="button" onclick="AjaxSumbit();" value="Ajax提交" />
<table border="">
<thead>
<tr>
<th>主机名</th>
<th>端口</th>
</tr>
</thead>
<tbody id="tbd">
<tr>
<th>1.1.1.1</th>
<th></th>
</tr>
<tr>
<th>1.1.1.1</th>
<th></th>
</tr>
</tbody>
</table>
<script src="/static/jquery-1.8.2.min.js"></script>
<script>
function AjaxSumbit(){
var host='1.1.1.1';
var port='';
$.ajax({
'url':"/ajax_data/",
type:"POST",
data:{h:host,p:port},
success:function(arg){ }
})
}
</script> </body>
</html>

user_list.html

2、views增加如下内容:

from django.shortcuts import HttpResponse
def ajax_data(request):
print request.POST
return HttpResponse("ok")

3、urls内容:

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

urls

提交的数据内容如下:为字典类型

Ajax发送复杂数据类型(数组、字典)
1、user_list.html
{% load form_tag %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
.form-control{ {% comment %}通过attr增加的属性,可以在html中加以利用,或者在这里可以自己定义属性,实现渲染页面渲染功能{% endcomment %}
background-color: red;
}
</style>
</head>
<body>
<form action="/user_list/" method="post"> {% comment %}此处的action必须是以/开头和结尾{% endcomment %}
<p>用户类型: {{ obj.user_type }}
<span>{% error_message errors.user_type %}</span>
</p>
<p>主机: {{ obj.host }}\
{% comment %}{% errors.host[][] %}{% endcomment %} {% comment %} //模板语言不支持索引取值。所以需要构造simple_tag在python中来实现索引取值//{% endcomment %}
<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.mome }}</span></p>
<input type="submit" value="submit" /> </form>
<input type="button" onclick="AjaxSumbit();" value="Ajax提交" />
<input type="button" onclick="AjaxSubmitSet();" value="Ajax提交集合" />
<table border="">
<thead>
<tr>
<th>主机名</th>
<th>端口</th>
</tr>
</thead>
<tbody id="tbd">
<tr>
<th>1.1.1.1</th>
<th></th>
</tr>
<tr>
<th>1.1.1.1</th>
<th></th>
</tr>
</tbody>
</table>
<script src="/static/jquery-1.8.2.min.js"></script>
<script>
function AjaxSumbit(){
var host='1.1.1.1';
var port='';
$.ajax({
'url':"/ajax_data/",
type:"POST",
data:{h:host,p:port},
success:function(arg){ }
})
} function AjaxSubmitSet(){ #传送字典
var array_users=[
{'username':'alex','age':},
{'username':'Chales','age':},
{'username':'eric','age':}
];
$.ajax({
url:"/ajax_data_set/",
type:'POST',
data:{data:array_users},
success:function(arg){ }
})
}
</script> </body>
</html>
2、views
def ajax_data_set(request):
print request.POST
return HttpResponse("ok")

views

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

urls

但是上述提交的内容,不是原生的字符串,不是我们想要的,看下面:
在原来的基础上添加内容:
        function AjaxSubmitSet(){
var array_users=[
{'username':'alex','age':},
{'username':'Chales','age':},
{'username':'eric','age':}
];
$.ajax({
url:"/ajax_data_set/",
type:'POST',
tradition: true,
data:{data:JSON.stringify(array_users)}, #将上面的字典转换为原生的字符串
success:function(arg){
}
})
}

user_list.html

好,ajax简单数据和复杂数据的提交完成了,下面开始在后台进行更新;
1、views
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)) #成功的话,返回成功,失败,返回错误信息
2、user_list.html
        function AjaxSubmitSet(){
var array_users=[
{'username':'alex','age':},
{'username':'Chales','age':},
{'username':'eric','age':}
];
$.ajax({
url:"/ajax_data_set/",
type:'POST',
tradition: true,
data:{data:JSON.stringify(array_users)},
success:function(arg){
var callback_dict = $.parseJSON(arg); //将字符串转换为对象,类似于json.loads
if (callback_dict.status){
alert('成功')
}else {
alert(callback_dict.error);
}
}
})
}

user_list.html

 
作业:
、登录页面,Form验证,session,登录成功跳转到index redirect跳转
、默认访问index,点击登录跳回登录页面
、列表页面
内容通过model去数据库中获取
model.assert.object.all()绑定到页面上;
、添加页面(From表单,需要显示不合法的信息),添加之后,列表页面增加一条数据;
、对列表页面数据的修改;
使用之前的进入编辑模式,退出编辑模式;
具体实现如下:
使用jQuery,循环所有的数据(表格),点击保存的时候,自动退出编辑模式,将数据放到一个数组中;array_list = [{'hostname':xxx'},'hostname':xxx'];,
使用$.ajax(),将每一条数据发送到后台更新,ajax发送成功之后,表示后台数据已经更新完成,使用window.location.href=window.location.href将页面刷新一次,就OK啦;

作业

#!/usr/bin/env python
# _*_ coding:utf- _*_ from django import forms
class LoginForm(forms.Form):
username = forms.CharField(
widget=forms.widgets.TextInput(attrs={'class': "form-control","placeholder":"用户名"})
)
password = forms.CharField(
widget=forms.widgets.PasswordInput(attrs={'class': "form-control","placeholder":"密码"})
)

forms

"""s11day18_homework URL Configuration

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

cmdb\urls

#!/usr/bin/env python
#coding:utf-
from django.shortcuts import render
from cmdb import forms # Create your views here. def login(request):
obj = forms.LoginForm()
#如果登录成功,写入session,跳转到index页面(home)
return render(request,'account/login.html',{'model':obj}) def index(request):
return render(request,'home/index.html') def lists(request):
return render(request,'asset/lists.html') def add(request):
return render(request,'asset/import_single.html')

cmdb/views

主页:

显示列表:

添加页面:


Django 获取多个数据和上传文件
一般在获取后台前端提交的数据的时候,可以使用request.POST.get('xxx')来获取数据,如果对于input标签,如果是radio就可以这样搞了,但是对于checkbox、select(multiple)这样可以多选值,就只能获取第一个值,
所以可以使用request.POST.getlist('xxx')来获取所有选中并提交的值; 如果input 的type为file,那么使用request.POST.get('xxxx')获取的只有文件的名字,但是文件的内容没有获取;obj = request.FILES.get('xxx')可以获取到
import os
file_path = os.path.join('upload',obj.name) #上传到指定的目录
f = open(file_path,mode="wb")
for i in obj.chunks(): #chunks()返回一个生成器
f.write(i)
f.close()
需要注意的是,如果是上传文件,那么在form的属性必须加 enctype="multiple/form-data"

Django的FBV和CBV

function base view   #之前全部齐FBV
class base view
url.py
url(r'home/',views.Home.as_views()), views.py
from django.views import View class(View):
#在父类Views中有方法dispatch,用于解析request.method,返回method,使用的反射实现的,可以在子类中重写该方法,用于我们定制一些功能,相当于加了装饰器
def dispash(self,request)
#调用父类中的dispatch
print ('before')
result = super(Home,self).dispatch(self,request)
print ('after')
return result #返回get/post def get(self,request):
pass def post(self,request):
pass

源码:

class View(object):
"""
Intentionally simple parent class for all views. Only implements
dispatch-by-method and simple sanity checking.
""" http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] def __init__(self, **kwargs):
"""
Constructor. Called in the URLconf; can contain helpful extra
keyword arguments, and other things.
"""
# Go through keyword arguments, and either save their values to our
# instance, or raise an error.
for key, value in six.iteritems(kwargs):
setattr(self, key, value) @classonlymethod
def as_view(cls, **initkwargs):
"""
Main entry point for a request-response process.
"""
for key in initkwargs:
if key in cls.http_method_names:
raise TypeError("You tried to pass in the %s method name as a "
"keyword argument to %s(). Don't do that."
% (key, cls.__name__))
if not hasattr(cls, key):
raise TypeError("%s() received an invalid keyword %r. as_view "
"only accepts arguments that are already "
"attributes of the class." % (cls.__name__, key)) def view(request, *args, **kwargs):
self = cls(**initkwargs)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.request = request
self.args = args
self.kwargs = kwargs
return self.dispatch(request, *args, **kwargs)
view.view_class = cls
view.view_initkwargs = initkwargs # take name and docstring from class
update_wrapper(view, cls, updated=()) # and possible attributes set by decorators
# like csrf_exempt from dispatch
update_wrapper(view, cls.dispatch, assigned=())
return view def dispatch(self, request, *args, **kwargs):
# Try to dispatch to the right method; if a method doesn't exist,
# defer to the error handler. Also defer to the error handler if the
# request method isn't on the approved list.
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)

  

django模板语言中循环字典
{% for k,row in user_dict.items %}
<li>{{ k }} {{row}}</li>
{% endfor %}

基于正则表达式的url

urls.py
url(r'detail-(\d+).html'.views.detail,name='index') index.html
{% for k,row in user_dict.items %}
<li><a target="_blank" href="/detail-{{ k }}.html" {{row.name}} </a>></li> //点击查看详情
{% endfor %} views.py
def details(request,nid):
detail_info = USER_DICT[nid]
return render(request,'detail.html' ,{'detail_info':detail_info})

 

Django 路由对应的名称

url(r'detail-(?P<nid>\d+)-(?P<uid>\d+).html',views.detail,name='index1')

def detail(request,*args,**kwargs):
pass

在views.py中获取访问路径使用 request.path_info,也可以在模本语言中使用{{ request.path_info }},不过一般使用name代替.

使用name在模板中传参数{% url  'index' 1 3 %}/{% url 'index'   nid=1 uid 3% };

如果知道name,需要获取url,也可以使用reverse,from django.urls import reverse     v=reverse('index',args=(90,)),这里的v就是实际的url; v=reverse('index',kwargs={'nid':99,'uid':88});

在python3 django中使用mysql,需要注意 

在python3中没有使用mysqldb,需要安装pymysql,然后在project同名文件夹下的__init__中,写入  import pymysql    pymysql.install_as_MySQLdb()

django orm 字段参数含义

   db_index     索引

unique        唯一索引

unique_for_date

unique_for_month

unique_for_year

auto_now           创建时,自动更新时间

auth_now_add    更新时,自动更新当前时间

choices     django admin 中下拉框,避免连表查询

blank    django admin 是否为空

verbose_name   djano_admin 显示为中文

editable     django admin是否可以被编辑

error_messages   错误信息

help_text     django admin 提示

validators    django form,字定义错误信息

视图获取用户请求信息以及请求头

在视图中print request,可以看到request的类,可以看到请求的携带的变量,比如request.environ(全部是由这个环境变量携带进去的),可以使用for k,v in request.environ.items():print k,v,可以打印request的变量的结果,可以看到有HTTP_USER_AGENT,用于显示是那种agent请求的,可以用于对于不同的终端显示不同的内容;

request对于不常用的变量,没有提供方法直接获取(比如request.POST),可以使用request.environ['HTTP_USER_AGENT']获取信息;

自定义simple_tag和模板过滤

基于cookie实现用户登录

#设置cookie,关闭浏览器失效

response.set_cookie('key','value')   #设置cookie

response.set_cookie('key','value',max_age=10)   #设置失效时间

current_data = datatime.datetime.utcnow()+datatime.datetime.timedelta(seconds=5)

response.set_cookie('username','value',expires = current_date)

request.COOKIES.get('key')  #获取cookie

response.set_cookie('key','value',max_age=10)   #设置10s后失效

可以设置7天内免登录的按钮了;

注销就是把cookie清除了;

使用js获取cookie,需要引入 juqery.cookie.js插件;

$.cookie('k1')

$(function(){
var v = $.cookie('per_page_count',{'path':'/user_list/'});
$("#ps").val(v); }); function changePagesize(ths) {
var v = $.(this).val();
$.cookie("per_page_count",v,{'path':'/user_list/'}) //设置cookie的值为当前select选择的值,path表示cookie只有在这个url上才生效,当前页面受影响;
} 在views.py中使用:request.cookie.get('per_page_count',10)获取用户选择的数字;

 

基于cookie实现定制显示数据条数(分页)

<select  onchange="changePage(this)">
$(function(){
var v = $.cookie('per_page_count',{'path',"/user_list/"}); /*获取cooike*/
$('$ps').val(v);
}) function changePage(ths){ /*select的onchange事件*/
var = $(ths).val();
console.log(v);
$.cookie('per_page_count',v,{'path',"/user_list/"}); /*设置cookie值*/
location.reload();
} views.py def user_list(request):
curent_page = request.GET.get('p',1)
current_page = int(curent_page)
val = request.COOKIES.get('per_page_count',10)
page_obj = pagination.Page(current_page,len(LIST),val)

带签名的cookie

response.set_signed_cookie('username','aaaaa',salt='xxx')    #设置加密的cookie

request.get_signed_cookie('username',salt='xxx')   #获取cookie值,salt加盐的值,必须相同

 

 获取表单数据的三种方式

每一个对象就是一行数据,每一个QuerySet就是一个对象;

v = models.Business.objects.all().values('id','caption')  :获取指定的列,也是QuerySet类型,每一个元素字典;

v=models.Business.objects.all().values_list('id','caption')   :获取的每一个元素是元祖;在模板语言中使用  {% for row in v %}   {{ row.0}} {{row.1}} {%endfor%} 来引用;

一对多跨表操作

class Host(models.Model):
nid = models.AutoField(primary_key=True)
hostname = models.CharField(max_length=32,db_index=True)
ip=models.IPAddressField(protocol='ipv4',db_index=True)
port = models.InterField()
b = models.ForeignKey(tp='Business',to_field='id')

row.b.id,row.b.caption;   #使用.跨表

v = models.Host.objects.filter(nid__gt=0).values('nid','hostname','b_id','b__caption')    #这里使用使用'__'双下划线进行跨表,不能使用"."跨表了;

v = models.Host.objects.filter(nid__gt=0).values('nid','hostname','b_id','b__caption')

#也就是从filter后面开始,跨表就只能使用'__'了;

在views.py中打印上面v的各个值: for row in v: print row['nid'],row['hostname'],row['b_id'],row['b_caption'];

           for row in v2: print row[0],row[1]...

在前端模板中使用使用.了;

增加一对多数据

如果在前段使用for循环的时候,需要在表格中展示id,并且使用的是数据库中表的主键,那么该id有可能不是从1开始的。使用counter就可以了,每循环一次,+1;

{% for row in v1 %}
<tr hid="{{row.nid}}" bid="{{row.b_id}}">
<td> {{ forloop.counter}} <t/d> //counter0从0开始
<td>{{row.ip}} </td>
</tr>
{%endfor%}

使用模态对话框添加数据

.hide {
display: none
} .shade{
position: fixed:
top :0;
right: 0;
left: 0;
bottom: 0;
backgrand: blank;
opacity: 0.6: /*透明度*/
z-index 100;
} .add-model{
positon: fixed:
height: 300px;
width: 400px;
top :100%;
left: 50%
z-index: 101;
boder: 1px solid red;
backgrand: white:
margin-left: -200px;
}
<input type="button" id="add_host" name="添加"> <div class="shade"> form表单</div> //背景层
<div class="add-model hide"> </div> //遮罩层 <sctipt>
$(function(){
$('#add_host').click(function(){
$('.shade',.add-model).removeclass('hide'); })
}) </script> views.py
def host(request):
if request.method =='GET':
pass
elif: request.method == 'POST':
h = request.POST.get('hostname')
i = request.POST.get('ip')
p = request.POST.get('port')
b = request.POST.get('b_id')
#model.HOST.objects.create(hostname=h,ip=i,port=p,b=model.Business.objects.get(id=b))
model.HOST.objects.create(hostname=h,ip=i,port=p,b_id = b)
return redirect('/host') #get请求

Ajax基本内容整理

$.ajax   $.post    $.get     $.getJson

后台添加数据的时候,做异常处理;

ret = {'status':True,'error':None,'data':None}

return HttpResponse(json.dumps(ret))

success: function(data){
var obj = JSON.parse(data); //反序列化
if obj.status {
location.reload();
}
else {
$('#error_msg').text(obj.error)
}
}

在编辑删除表格中的一行数据的时候,删除数据时候,为了不刷新页面,可以将含有该行数据的id remove掉就可以了;

data: $('edit_form').serialize();获取真整个form的数据;

编辑的时候,应该在模态对话框中看到点击的哪一行的数据,使用id获取

#获取编辑框的值
$('.edit').click(function(){
$(.shade,.edit-model).renveclass('hide');
var bid = $(this).parent().parent().attr('nid');
var nid = $(this).parent().patent().attr('nid');
$('#deit_form').find('select').val(bid);
$('#edit'_form).find('input[name='nid']').val(nid); $.ajax({
data: $('#edit-form').serialize(); //获取表单的数据填写的数据
}) })

创建多对多示例

方式一、自定义关系表
class HostToApp(models.Model):
hobj = models.ForeighKey(to='Host',to_field='nid')
abj = modes.ForeignKey(to='Appication',to_field='id') 方式二、ManyToManyField class Application(models.Model):
r = ManyToManyField('HOST')
def app(request):
app_list = models.Application.objects.all()
for row in app_list:
print row.name,row.r.all() #这里的row.r.all()是一个Host的QuerySet; obj.r.add(1) #增加
obj.r.add(2)
obj.r.add(2,3,4)
obj.r.add(*[1,2,3,4])
obj.r.remove(1) 类似add
obj.r.clear()
obj.r.set([3,5,7]) {% for app in app_list %}
{{app.name}}
{% for host in app.r.all %}
{{ host.hostname}}
{% endfor %}
{% endfor %} host_list = request.POST.getlist('host_list')
obj = models.Application.objects.create(name=app_name) #这里的obj和get获取的一样
obj.r.add(*host_list) #这是针对m2m表host做的操作; #使用ajax添加数据
def ajax_add_app(request):
ret = {'status':True,'error':None,'data':None}
print request.POST.get('user')
print request.POST.getlist('host_list')
return Httpresponse(json.dumps(ret)) $("#add_submit_ajax").click(function(){
$.ajax({
url: '/ajax_add_app',
data: {'user':123,''host_list':[1,2,3,4]},
type:POST,
dataType: 'jSON',
traditional: true, /*如果需要post的数据中有列表,一定要加该参数;如果提交的数据包含在form中,也可以使用 data: $('#data-form').serialize(),这样就不用自己写data了,提交的字典的name是click的input标签的name*/
success: function(obj){
console.log(obj);
},
})
})
#编辑数据
$.('.edit').click(function(){
$('.edit-model',.shaed).removeclass('hide');
var hid_list = [];
$(this).parent().prev().children().each(function(){
var hid = $(this).attr(hid);
hid_list.push(hid);
})
$('#edit-form').find('select').val(hid_list);
//如果发送到后台
}) 数据发送到后台:
obj= models.Application.objects.get(id=1)
obj.name = "new name"
obj.save()
obj.r.set([1,2,3,4])

Models操作(原声SQL) 

models.TB.objects.create()
models.TB.objects.create(**{})
obj = models.TB(**)
obj.save() models.TB.objects.all()[7:10] models.TB.objects.all()
models.TB.objects.update(..) models.TB.objects.filter(id__in=[1,2,3]) models.TB.objects.filter(单下划线id)
models.TB.objects.filter(...).delete models.TB.objects.filter.values()
models.TB.objects.values_list
models.TB.objects.get()
models.TB.objects.filter().update()
models.TB.objects.filter().first()
models.TB.objects.filter(**{})
models.TB.objects.filter(**{})count()
models.TB.objects.filter(双下划线跨表) moels.TB.objects.all().order_by('')
models.TB.objects.distinct()

Session 

基于cookie做用于验证的时候,不要将敏感信息放置到cookie中;

cookie的优点:将存储的压力放到客户端了;

a、session的原理

cookie是保存在用户浏览器端的键值对;

session是保存在服务器端的键值对;

session = {
随机字符串1: {
'is_login':True,
'user':'',
'nid':
}
} 发送到客户端的只有随机字符串,客户端请求时只需要将随机字符串带着,拿着这个字符串,就可以查看session的内容了;
#在views中设置session
def login(request):
if request.method =='GET':
return render
elif request.method == 'POST':
user ==...
pwd ==...
if user == 'root' and pwd == '123':
#生成随机字符串
#写到用户浏览器cookie
#保存到session
#在随机字符串对应的字典中设置相关内容
request.session['username']=user
request.session['is_login'] = True def index(request):
#获取当前用户的随机字符串
#根据随机字符串获取对应信息
if request.session['is_login']: #拿到随机字符串,在数据库中找到字典的对应信息;
return Httpresponse(request.session['username'])
else:
.... 注意:如果要设置新的session,一定要注意新生成一下数据库,python manage.py makemigrations ...

CSRF

使用form提交,会在页面生成一个隐藏的input标签;   

#使用ajax提交,可以在请求为get的时候,不将csrftokn加载请求头上;
{% 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)); /*.test表示判断是否正则表达式*/
}
$.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);
}
}); }

如果不讲csrf的中间件注释掉,那么会在全部的接口生效;

全局:

  中间件 django.middleware.csrf.CsrfViewMiddleware

局部:

  • @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
  • @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

注:from django.views.decorators.csrf import csrf_exempt,csrf_protect

缓存 

python的web框架,只有django有缓存;

Django中提供了6种缓存方式:

  • 开发调试
  • 内存
  • 文件
  • 数据库
  • Memcache缓存(python-memcached模块)
  • Memcache缓存(pylibmc模块)
# 此缓存使用python-memcached模块连接memcache

    CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211',
}
} CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': 'unix:/tmp/memcached.sock',
}
} CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': [
('172.19.26.240:11211,10'), #加权重
('172.19.26.242:11211',11),
]
}
}
from django.views.decorators.cache import cache_page

@cache_page(10)     #10s生效
def cache(request):
import time
ctime = time.time()
return render(request,'cache.html',{'ctime':ctime}) cache.html
{% load cache %} //对某一个值进行缓存必须load cache
<h1>{{ ctime}}</h1>
{% cache 10 k1%} //k1是缓存的key,前缀
<h1>{{ ctime }}</h1>
{% endcache %}

  

#如果不想要在views中设置,可以通过中间件进行全局设置; 

MIDDLEWARE = [
'django.middleware.cache.UpdateCacheMiddleware', #只有process response ,请求走的时候执行
# 其他中间件...
'django.middleware.cache.FetchFromCacheMiddleware', #只有process request ,请求来的时候执行
] #在django中缓存有5种配置,3种应用:全局、视图函数、模板;

如果中间件、views、模板都设置了缓存,那么会先在全局生效,其次views、再次模板;

 信号

如果想在数据库创建的时候,创建一条记录(操作日志);在数据保存之前或者保存之后,生成一条记录;(我们最先想到的就是装饰器了,然后不仅要看别人的代码,还有可能修改源码);

def single(request):
from app01 import moels
obj = models.TB(user='root')
obj.save()

Django的全部信号

Model signals
pre_init # django的modal执行其构造方法前,自动触发
post_init # django的modal执行其构造方法后,自动触发
pre_save # django的modal对象保存前,自动触发
post_save # django的modal对象保存后,自动触发
pre_delete # django的modal对象删除前,自动触发
post_delete # django的modal对象删除后,自动触发
m2m_changed # django的modal中使用m2m字段操作第三张表(add,remove,clear)前后,自动触发
class_prepared # 程序启动时,检测已注册的app中modal类,对于每一个类,自动触发
Management signals
pre_migrate # 执行migrate命令前,自动触发
post_migrate # 执行migrate命令后,自动触发
Request/response signals
request_started # 请求到来前,自动触发
request_finished # 请求结束后,自动触发
got_request_exception # 请求异常后,自动触发
Test signals
setting_changed # 使用test测试修改配置文件时,自动触发
template_rendered # 使用test测试渲染模板时,自动触发
Database Wrappers
connection_created # 创建数据库连接时,自动触发

要注册信号,需要先导入

 # sg.py
from django.core.signals import request_finished
from django.core.signals import request_started
from django.core.signals import got_request_exception from django.db.models.signals import class_prepared
from django.db.models.signals import pre_init, post_init
from django.db.models.signals import pre_save, post_save
from django.db.models.signals import pre_delete, post_delete
from django.db.models.signals import m2m_changed
from django.db.models.signals import pre_migrate, post_migrate from django.test.signals import setting_changed
from django.test.signals import template_rendered from django.db.backends.signals import connection_created
def f1(sender, **kwargs):
print("xxoo_callback")
print(sender,kwargs)
def f2(sender, **kwargs):
print("xxoo_callback")
print(sender,kwargs)
pre_init.connect(f1)
pre_init.connect(f2)
# xxoo指上述导入的内容

需要将上述注册的页面导入到project的app下面的__init__.py(这里也可以加数据库的链接)下面,在工程运行的时候,就执行了;

会在触发views的single函数的创建数据的语句之前,执行上面的f1、f2函数;

除了上面内置的信号之外,还可以自定义信号

sg.py
import django.dispatch
pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"]) def callback(sender, **kwargs):
print("callback")
print(sender,kwargs) pizza_done.connect(callback)
views.py

  from sg import piazza_done
piazza_done.send(sender='aaaa',topping=123,size=456) #自定义信号的触发可以由我们自己决定;在运维的时候,可以当某一个阈值超过某一个值的时候,触发信号;
Form
http://www.cnblogs.com/wupeiqi/articles/6144178.html form操作
from django.forms import forms
from django.forms import fields
from django.forms import widget
class FM(forms.Form):
user = fields.Charfield(
error_messages = {'required':"用户名不能为空"},
widget = widget.Textarea(attrs = {'class':'c1'})
) pwd = fields.CharField(
max_length = 12,
min_length = 6,
error_messages = {'required':"密码不能为空",'min_length':'密码长度不能小于6','min_length':'密码长度不能大于12'},
widget = widget.PasswordInput(attrs = {'class':'c2'})
) email = fields.EmailField(error_messages = {'required':'邮箱不能为空','invalid':'邮箱格式错误'}) fm.html
<form action='/fm/' method='POST'>
{% csrf_token %}
<p>{{obj.user}} {{obj.error.user.0}} </p>
<p>{{obj.pwd}} {{obj.error.pwd.0}} </p>
<p>{{obj.email}} {{obj.error.email.0}} </p>
<input type='submit' value='提交'>
</form>

 
完成:
-验证用户请求
- 生成HTML
(保留上一次提交的数据) 自定义:
- 类
- 字段(校验)
- 插件(生成HTML) 初始化操作: def fm(request):
if request.method == 'GET':
dic = {
"user":"r1",
"pwd":"123123",
"email":'123@123'
"city1":1,
"city":2
}
obj = FM(initial=dic)
return render(request,'fm.html',{'obj':obj})
elif request.method == 'POST':
obj = FM(request.POST)
r1 = obj.is_valid()
if r1:
models.UserInfo.objects.create(**obj.cleaned_data)
else:
return render(request,'fm.html',{'obj':obj})
return render(request,'fm.html')

  

一大波model操作
http://www.cnblogs.com/wupeiqi/articles/6216618.html #model操作
1、创建数据库表
class User(models.Model):
name = models.CharField(max_length=32,db_index=True)
email = models.CharField(max_length=32,db_index=True)
class Meta:
db_table = "tb1" #数据库表名
index_togeher = [('name','email')] #联合索引,只生产一个索引文件,可以不再上面的两个字段加索引了,但是这样是有代价的,原因:最左前缀的模式
#select * from where name=xx
#select * from name='xx' and email='xx'
#select * from where email ='xx' #无法命中索引
unique_together = (('name','email')) #是索引,并且是联合唯一的 verbose_name = "hahah" #admin中显示hahahs
verbose_name_plural = 'haha' #admin中显示haha class UserType(modes.Model):
name = models.CharField(max_length=32)
pwd = models.CharField(max_length=32)
... ForeignKey(to="UserType",to_field = 'id',on_delete=CASCADE) #删除UserType的数据,将会把User中的关联数据删除
#delete from user where id =1
# delete from UserType where id =1 报错
#UserType.objects.filter(id=1).delete() 使用orm可以删除
存在Foreignkey的时候,关于正向操作和反向操作
class UserType(models.Model):
name = models.CharField(max_length=32) def __str__(self):
return self.name class User(models.Model):
user = models.CharField(max_length=32)
pwd = models.CharField(max_length=64)
ut = models.ForeignKey(to='UserType',
to_field='id',
related_name='b',
limit_choices_to={'id__gt':5}) #如果这里是b,那么item.user_set.all()就变成item.b.all()
#ut = models.ForeignKey(to='UserType',to_field='id',related_query_name='a') #如果这里是b,那么item.user_set.all()就变成item.a_set.all() #正向查找
# v = User.objects.all()
# for item in v:
# item.user
# item.pwd
#
# User.objects.all().values('user','ut__name')
# #反向查找
# v = UserType.objects.all()
# for item in v:
# item.name
# item.id
# item.user_set.all() # UserType.objects.all().values('name','user__pwd')

多对多

a.django 创建第三张表
m2m.remove
m2m.add
m2m.set
m2m.clear
m2m.filter b.自定义第三张表(无m2m字段)
自己链表查询 c.自定义第三张表,(有m2m字段)#推荐
m2m.filter class Bolg(models.Model):
slte = models.CharField(max_length=10)
m = models.ManyToManyField('Tag',through='B2T',through_fields=['b','t']) class Tag(models.Model):
name = models.CharField(max_length=32) class B2T(models.Model):
b = models.ForeignKey('Blog')
t = models.ForeignKey('Tag')

  

2、操作数据库表
django可以配置多个数据库,实现读写分离等一些操作,使用models.object.using(xxx)实现; django 读写分离 dbrouter; QuerySet方法详细操作:
-返回QuerySet
-extra方法:
对于一些复杂的sql操作,orm没有提供操作方法,可以使用extra,构建子查询
select
id,
name,
1,
func(id),
select name from tb2 where nid=id;
from
tb1; Entry.objects.extra(select={'cid':"1"})
select
*
1 as cid
from tb1 Entry.objects.extra(select={'new_id':"select col from sometable where othercol = '%s'"},select_params=(1,))
select
* (select name from tb2 where nid=id) as new_id
from
tb1;
...

-和性能相关的两个:select_related和prefetch_related

def index(request):
models.UserType.objects.all().values('name', 'user__pwd')
users = models.User.objects.all()
for row in users:
print(row.user,row.pwd,row.ut_id) #第一次sql请求
print(row.ut.name) #再次发起一次sql请求,
#如果涉及到跨表,就会再次发起sql请求,如果想要仅仅发起一次sql请求,可以使用values('user','pwd','ut__name') #select_related
users = models.User.objects.all().select_related('ut') #会将所有跨表关联的数据进行一次查询出来.可以加多个参数,注意参数只能是关联的字段,表示也会查询与ut关联的表的数据;
#连表查询查询数据是快的,浪费存储资源,但是查询速度快了;数据库范式:foreignkey,onetoone,m2m #prefetch_related
users = models.User.objects.filter(id__gt=30).prefetch_related('ut')
#select * from users where id>30 --->第一次
#获取上一步骤中所有的ut_id=[1,2....]
#select * from user_type where id in [1,2] -->第二次
for row in users:
print(row.user,row.pwd,row.ut_id)
print(row.ut.name) return HttpResponse('index')

--日期相关

dates:获取年、年月、年月日

datetimes:

--row:原生的sql语句

obj = models.tb.objects.row('select * from tb')
obj = models.tb.objects.row('select nid as id,username as name,email as pwd from tb2') #这样就会把tb2的对象赋值给tb了; 或者:
dic = {'id':'nid','name':'username'}
obj = models.tb.objects.row('select nid ,username,email from tb2',dic)  
-aggregate
from django.db.models. import Count,Avg,Max,Min,Sum

result = models.UserInfo.objects.aggregate(n=Count('nid'))
#select count(nid) as n from userinfo
result = models.UserInfo.objects.aggregate(n=Count('nid',distinct=True)) #先去重再聚合

3、数据验证(非常弱)
full_clean进行验证
- 每个字段正则
- clean 事件钩子
def index(request):
# models.UserInfo.objects.create(name='root',email='root')
obj = models.UserInfo(name='charles',email='1111')
obj.full_clean() #这里会做验证(对所有的字段),如果失败,直接报错
obj.save() return HttpResponse('index') class UserInfo(models.Model):
name = models.CharField(max_length=32)
email = models.EmailField() def clean(self):
from django.core.exceptions import ValidationError
c = UserInfo.objects.filter(name=self.name).count()
if c:
raise ValidationError(message='用户名已经存在')

ModelForm(耦合非常强)
1、数据库验证
2、数据验证
对于都行的公司,数据库操作和业务操作是分离的,直接通过接口或者RPC进行调用;如果数据库操作和业务操作在一起的时候,可以使用modelForm,所以在小型项目或者django admin的时候会使用得到modelForm; Form操作
http://www.cnblogs.com/wupeiqi/articles/6144178.html #参考博客
1、数据验证(强大)
from django.forms import fields
from django.forms import widgets
from django.forms import forms class UserInfoForm(forms.Form):
user = fields.CharField(
required=False,
widget=widgets.Textarea(attrs={'class':'c1'})
) pwd = fields.CharField(
max_length=12,
widget=widgets.PasswordInput(attrs={'class':'c1'})
) form的作用:1、数据验证;2、生成html(在新url,保留上一次提交的数据) 使用新URL操作,用form提交,那么数据验证和生成html都会使用; 如果使用Ajax提交,(可以不使用生成html的功能,也可以使用)
2、form操作动态select数据
如果form的类型是ChoiceField的时候,如果select下拉框的选项比较简单,不需要动态生成,那么就可以直接使用元组写死就可以了,如果下拉框的数据有可能变化,那么就需要借助数据操作.values('id','name')进行动态获取数据了;
但是对于choice中的数据,是Form的类第一次实例化的时候就生成了,如果需要重新加载数据,就要重启web服务了,这个在生成是不能忍受的。所以,解决方式有两种:直接在form的类实例化的时候,再重新赋值实例化的对象中关于choice
的数据内容(为最新的数据库中的数据),或者将该赋值操作放置到Form的类的__init__方法下面,让每一次刷新页面,实例化类的时候,重新加载数据,这个是推荐的方式;
forms.py

from app01 import models
from django.forms import fields
from django.forms import widgets
from django.forms import forms class UserInfoForm(forms.Form):
user = fields.CharField(
required=False,
widget=widgets.Textarea(attrs={'class':'c1'})
) pwd = fields.CharField(
max_length=12,
widget=widgets.PasswordInput(attrs={'class':'c1'})
) user_type=fields.ChoiceField(
# choices=[(1,'普通用户'),(2,'超级用户'),],
# choices=models.UserType.objects.values_list('id','name'),
choices=[],
widget=widgets.Select,
) user_type2 = fields.CharField(
widget=widgets.Select(choices=[])
)
def __init__(self,*args,**kwargs):
super(UserInfoForm,self).__init__(*args,**kwargs)
self.fields['user_type'].choices = models.UserType.objects.values_list('id', 'name')
self.fields['user_type2'].widget.choices = models.UserType.objects.values_list('id', 'name') views.py
from django.shortcuts import render,HttpResponse
from app01 import models def index(request):
from app01.forms import UserInfoForm
obj = UserInfoForm() #每次刷新的时候,会执行这个操作,将全部的数据封装在obj中
return render(request,'index.html',{'obj':obj})

除了上面我们可以写动态加载Select数据之外,还django还为我们实现了一种比较简单的方式用于加载Select数据,这不过这种数据加载的时候,被加载的model必须实现__str__方法(这就是代价)

from django.forms.models import ModelChoiceField,ModelMultipleChoiceField
class UserInfoForm(forms.Form):
user_type3 = ModelChoiceField(
empty_label='请选择用户',
queryset=models.UserType.objects.all(),
to_field_name='name',
)

Form内置钩子(允许自定义form返回给model的数据)
form内置钩子查找顺序:is_valid()-->self.errors-->self.full_clean(可以看到form钩子)
在form数据提交之后,django form会先通过正则表达式验证提交的数据,然后会执行每一个字段对应的钩子,最后执行整体的钩子
from django.core.exceptions import ValidationError
class RegisterForm(forms.Form):
user = fields.CharField()
email = fields.EmailField() def clean_user(self): #如果user的正则表达式通过之后,执行user_clean方法
c = models.UserInfo.objects.filter(name=self.cleaned_data['user']).count()
if not c:
return self.cleaned_data['user']
else:
raise ValidationError('用户名已经存在',code='xxxx') def clean_email(self):
return self.cleaned_data['email'] class LoginForm(forms.Form):
user = fields.CharField()
pwd = fields.CharField(validators=[]) def clean_user(self): # 如果user的正则表达式通过之后,执行user_clean方法
c = models.UserInfo.objects.filter(name=self.cleaned_data['user']).count()
if not c:
return self.cleaned_data['user']
else:
raise ValidationError('用户名已经存在', code='xxxx') def clean_pwd(self):
return self.cleaned_data['pwd'] def clean(self): #整体的钩子,会联合user和pwd另个字段进行钩子验证
c = models.UserInfo.filter(name=self.cleaned_data['user'],pwd=self.cleaned_data['pwd']).count()
if c:
return self.cleaned_data
else:
raise ValidationError('用户名或者密码错误') def _post_clean(self):
pass
 
对于错误信息:每一个errors中保存的是每一个字段的错误信息,格式如下:
obj.errors = {
'__all__':[], #整体错误信息,也就是 clean方法返回的错误信息
'user':[{'code':'required','message':'xxx'}], #clean_user返回的错误信息
'pwd':[{'code':'required','message':'xxxx'}], #clean_pwd 返回的错误信息
} form表单提交数据之后,执行的顺序是:验证每一个form的正则表达式-->clean_user钩子-->整钩子clean-->整体钩子__post_clean
def index(request):
from app01.forms import UserInfoForm
if request.method == 'GET':
obj = UserInfoForm({'user':"charles"}) #每次刷新的时候,会执行这个操作,将全部的数据封装在obj中;可以加参数,用户设置form的默认值;
return render(request,'index.html',{'obj':obj})
elif request.method == 'POST':
obj = UserInfoForm(request.POST,request.FILES)
obj.is_valid() def register(request):
from app01.forms import RegisterForm
obj = RegisterForm(request.POST)
if obj.is_valid():
obj.cleaned_data
else:
obj.errors
Form内置序列化错误信息
对于form错误信息,使用form实例化对象的.errors方法获取的,form的所有错误信息都会封装在这个对象中,django提供了.errors()对象的两个常用的序列化操作方法:as_json和as_data;
使用as_json: 缺点是在前端获取.errors对象的元素,显示在指定的位置,需要方序列化两次
import json
from django.shortcuts import render,HttpResponse from django.forms import fields
from django.forms import widgets
from django.forms import forms class LoginForm(forms.Form):
username = fields.CharField()
password = fields.CharField(
max_length=64,
min_length=12,
) from django.core.exceptions import ValidationError
def login(request):
if request.method == 'GET':
return render(request,'login.html')
elif request.method == "POST":
ret = {'status':True,'error':None,'data':None}
obj = LoginForm(request.POST)
if obj.is_valid():
print(obj.cleaned_data)
else:
print(type(obj.errors)) # <class'django.forms.utils.ErrorDict'>
#from django.forms.utils import ErrorDict print(obj.errors.as_json())
"""
在前端分序列化输出结果:
Object {data: null, error: "{"password": [{"message": "Ensure this value has a…characters (it has 10).", "code": "min_length"}]}", status: true}
data
:
null
error
:
"{"password": [{"message": "Ensure this value has at least 12 characters (it has 10).", "code": "min_length"}]}"
status
:
true
__proto__
:
Object
ret['error'] = obj.errors.as_json() #在前端需要loads两次
return HttpResponse(json.dumps(ret))

使用as_data: password [ValidationError(['Ensure this value has at least 12 characters (it has 10).'])]  ValidationError无法序列化的,需要单独做处理(自定义encoder实现)

import json
from django.shortcuts import render,HttpResponse from django.forms import fields
from django.forms import widgets
from django.forms import forms class LoginForm(forms.Form):
username = fields.CharField()
password = fields.CharField(
max_length=64,
min_length=12,
) from django.core.exceptions import ValidationError
class JsonCustomEncoder(json.JSONEncoder):
def default(self, o):
if isinstance(o,ValidationError):
return {'code':o.code,'messages':o.messages} #可以查看源码
else:
return json.JSONEncoder.default(self,o) def login(request):
if request.method == 'GET':
return render(request,'login.html')
elif request.method == "POST":
ret = {'status':True,'error':None,'data':None}
obj = LoginForm(request.POST)
if obj.is_valid():
print(obj.cleaned_data)
else:
print(type(obj.errors.as_data())) #<class 'dict'>
for k,v in obj.errors.as_data().items():
print(k,v) #password [ValidationError(['Ensure this value has at least 12 characters (it has 10).'])]
ret['error'] = obj.errors.as_data()
result = json.dumps(ret,cls=JsonCustomEncoder) #cls指定通过哪个类进行序列化操作
return HttpResponse(json.dumps(result))

前端代码展示:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
login.html
<form id="fm">
{% csrf_token %}
<p><input type="text" name="username"></p>
<p><input type="password" name="password"></p>
<a id="submit">提交</a>
</form> <script src="/static/jquery-3.2.1.min.js"></script>
<script>
$(function () {
$('#submit').click(function () {
$.ajax({
url: '/login.html',
type:'POST',
data:$('#fm').serialize(),
success:function (arg) {
console.log(arg);
arg = JSON.parse(arg);
console.log(arg);
}
})
})
})
</script>
</body>
</html>
ValidationError代码如下:
"""
Global Django exception and warning classes.
"""
from django.utils import six
from django.utils.encoding import force_text class FieldDoesNotExist(Exception):
"""The requested model field does not exist"""
pass class DjangoRuntimeWarning(RuntimeWarning):
pass class AppRegistryNotReady(Exception):
"""The django.apps registry is not populated yet"""
pass class ObjectDoesNotExist(Exception):
"""The requested object does not exist"""
silent_variable_failure = True class MultipleObjectsReturned(Exception):
"""The query returned multiple objects when only one was expected."""
pass class SuspiciousOperation(Exception):
"""The user did something suspicious""" class SuspiciousMultipartForm(SuspiciousOperation):
"""Suspect MIME request in multipart form data"""
pass class SuspiciousFileOperation(SuspiciousOperation):
"""A Suspicious filesystem operation was attempted"""
pass class DisallowedHost(SuspiciousOperation):
"""HTTP_HOST header contains invalid value"""
pass class DisallowedRedirect(SuspiciousOperation):
"""Redirect to scheme not in allowed list"""
pass class TooManyFieldsSent(SuspiciousOperation):
"""
The number of fields in a POST request exceeded
settings.DATA_UPLOAD_MAX_NUMBER_FIELDS.
"""
pass class RequestDataTooBig(SuspiciousOperation):
"""
The size of the request (excluding any file uploads) exceeded
settings.DATA_UPLOAD_MAX_MEMORY_SIZE.
"""
pass class PermissionDenied(Exception):
"""The user did not have permission to do that"""
pass class ViewDoesNotExist(Exception):
"""The requested view does not exist"""
pass class MiddlewareNotUsed(Exception):
"""This middleware is not used in this server configuration"""
pass class ImproperlyConfigured(Exception):
"""Django is somehow improperly configured"""
pass class FieldError(Exception):
"""Some kind of problem with a model field."""
pass NON_FIELD_ERRORS = '__all__' class ValidationError(Exception):
"""An error while validating data."""
def __init__(self, message, code=None, params=None):
"""
The `message` argument can be a single error, a list of errors, or a
dictionary that maps field names to lists of errors. What we define as
an "error" can be either a simple string or an instance of
ValidationError with its message attribute set, and what we define as
list or dictionary can be an actual `list` or `dict` or an instance
of ValidationError with its `error_list` or `error_dict` attribute set.
""" # PY2 can't pickle naive exception: http://bugs.python.org/issue1692335.
super(ValidationError, self).__init__(message, code, params) if isinstance(message, ValidationError):
if hasattr(message, 'error_dict'):
message = message.error_dict
# PY2 has a `message` property which is always there so we can't
# duck-type on it. It was introduced in Python 2.5 and already
# deprecated in Python 2.6.
elif not hasattr(message, 'message' if six.PY3 else 'code'):
message = message.error_list
else:
message, code, params = message.message, message.code, message.params if isinstance(message, dict):
self.error_dict = {}
for field, messages in message.items():
if not isinstance(messages, ValidationError):
messages = ValidationError(messages)
self.error_dict[field] = messages.error_list elif isinstance(message, list):
self.error_list = []
for message in message:
# Normalize plain strings to instances of ValidationError.
if not isinstance(message, ValidationError):
message = ValidationError(message)
if hasattr(message, 'error_dict'):
self.error_list.extend(sum(message.error_dict.values(), []))
else:
self.error_list.extend(message.error_list) else:
self.message = message
self.code = code
self.params = params
self.error_list = [self] @property
def message_dict(self):
# Trigger an AttributeError if this ValidationError
# doesn't have an error_dict.
getattr(self, 'error_dict') return dict(self) @property
def messages(self):
if hasattr(self, 'error_dict'):
return sum(dict(self).values(), [])
return list(self) def update_error_dict(self, error_dict):
if hasattr(self, 'error_dict'):
for field, error_list in self.error_dict.items():
error_dict.setdefault(field, []).extend(error_list)
else:
error_dict.setdefault(NON_FIELD_ERRORS, []).extend(self.error_list)
return error_dict def __iter__(self):
if hasattr(self, 'error_dict'):
for field, errors in self.error_dict.items():
yield field, list(ValidationError(errors))
else:
for error in self.error_list:
message = error.message
if error.params:
message %= error.params
yield force_text(message) def __str__(self):
if hasattr(self, 'error_dict'):
return repr(dict(self))
return repr(list(self)) def __repr__(self):
return 'ValidationError(%s)' % self

Django序列化操作

#使用django内置的序列化工具
def register(request):
from django.core import serializers
v = models.UserType.objects.all()
data = serializers.serialize("json",v) #序列化成json的对象
return HttpResponse(data) #序列化的结果
"""
[{"model": "app01.usertype", "pk": 1, "fields": {"name": "\u666e\u901a\u7528\u6237"}}, {"model": "app01.usertype", "pk": 2, "fields": {"name": "\u8d85\u7ea7\u7528\u6237"}}, {"model": "app01.usertype", "pk": 3, "fields": {"name": "\u53ea\u8bfb"}}, {"model": "app01.usertype", "pk": 4, "fields": {"name": "\u6d4b\u8bd5"}}, {"model": "app01.usertype", "pk": 5, "fields": {"name": "\u54c7\u54c8"}}]
""" #json.dumps
def register(request):
import json
v = models.UserType.objects.values('id','name')
v = list(v)
return HttpResponse(json.dumps(v))
#序列化结果
"""
[{"name": "\u666e\u901a\u7528\u6237", "id": 1}, {"name": "\u8d85\u7ea7\u7528\u6237", "id": 2}, {"name": "\u53ea\u8bfb", "id": 3}, {"name": "\u6d4b\u8bd5", "id": 4}, {"name": "\u54c7\u54c8", "id": 5}]
"""

小结:

ErrorDict
- 自定义encoder
QuerySet
第一种:
from django.core import serializera
v = models.tb.objects.all()
data = serializera.serializera("json",v)
第二种:
import json
from datetime import date
from datetime import datetime class JsonCustomEncoder(json.JSONEncoder):
pass v = models.TB.objects.values('id','name','ctime')
v = list(v)
v = json.dumps(v,cls=JsonCustomEncoder)

ModelForm

http://www.cnblogs.com/wupeiqi/articles/6229414.html   #modelForm参考博客

内容回顾:

Model
- 数据库操作
- 验证 Form
- class LoginForm(Form)
email = fields.EmailField()
- is_valid ->每一个字段正则(字段内置的正则)+clean_字段 -> clean(__all__) ->post_clean
- cleand_data
- errors

Model +Form=>验证 + 数据库操作

1、生成html标签:class Meta: ...

2、生成默认值:mf = xxxModelForm(instance=Modelobj)

3、额外的标签:is_rmb = Ffield.CharField(widget=Fwidgets.CheckboxInput())

4、各种验证:is_valid() -->各种钩子

5、mf.save()== instance = ms.save(False) instance.save() mf.save_m2m()

Ajax

http://www.cnblogs.com/wupeiqi/articles/5703697.html    #ajax全套参考博客

原声生ajax:是由XMLhttpRequest对象创建的;

POST请求的时候需要加特殊的请求头;

    <input type="text" />
<input type="button" value="Ajax1" onclick="Ajax1();" />
<script>
function Ajax1() {
var xhr = new XMLHttpRequest();
//xhr.open('GET','/ajax_json/',true); /*true表示是否异步*/
xhr.open('POST','/ajax_json/',true); /*true表示是否异步*/
xhr.onreadystatechange = function () {
if(xhr.readyState == 4){
//数据接收完毕
console.log(xhr.responseText); //接收到的数据
var obj = JSON.parse(xhr.responseText);
console.log(obj);
}
};
xhr.setRequestHeader('k1','v1'); //加任意的请求头
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded;charset-UTF-8'); //如果是POST请求,必须加这个加这个请求头
xhr.send("name=root;pwd=123"); /*发送的数据*/
}
</script>

伪造ajax请求:form+iframe实现

    <form action="/ajax_json/" method="POST" target="ifm1">
<iframe name="ifm1"></iframe>
<input type="text" name="username" />
<input type="text" name="email" />
<input type="submit" value="form提交" />
</form>
时机:
如果发送的是普通的数据-->jquery,xmlhttprequest,iframe

  

#iframe发送数据,并且获取发送的数据

    <form action="/ajax_json/" method="POST" target="ifm1">
<iframe id="ifm1" name="ifm1"></iframe>
<input type="text" name="username" />
<input type="text" name="email" />
<input type="submit" onclick="submitForm();" value="form提交" />
</form> function submitForm() {
$('#ifm1').load(function () {
var test = $('#ifm1').content().find('body').text();
var obj = JSON.parse(test);
console.log(obj);
})
}

偷偷发请求的三种方式:

1、jquery ajax
2、xmlhttprequest
2、form+iframe

ajax上传文件的三种方式: 1、使用xhr提交;2、使用jquery提交(依赖FormData);3、使用iframe提交(优先);

图片预览:

#图片提交上传之后,就可以预览到图片内容   

<form id="fm1" action="/upload_file/" method="POST" enctype="multipart/form-data" target="ifm1">
<iframe id="ifm1" name="ifm1" style="display: none;"></iframe>
<input type="file" name="fa" onchange="changeUpload();"/> //使用js提交
{# <input type="submit" onclick="iframeSubmit();" value="form提交" />#} //使用form提交
</form>
<div id="preview"></div> function changeUpload() {
$('#ifm1').load(function () {
var test = $('#ifm1').content().find('body').text();
var obj = JSON.parse(test);
$('#preview').empty();
var imgTag = document.createElement('img');
imgTag.src = "/"+ obj.data;
$("#preview").append(imgTag);
});
$('#fm1').submit();
} function iframeSubmit() {
$('#ifm1').load(function () {
var test = $('#ifm1').content().find('body').text();
var obj = JSON.parse(test);
$('#preview').empty();
var imgTag = document.createElement('img');
imgTag.src = "/"+ obj.data;
$("#preview").append(imgTag);
})
}

图片验证码 

- session

- check_code.py (依赖:pillow,字体文件)

- src属性后面加? :用于重新发送请求,生成图片

http://www.cnblogs.com/wupeiqi/articles/6307554.html   #kindEditor参看博客

http://kindeditor.net/docs/   #官网

组合搜索组件

     分为:搜索类型存在数据库和内存中两种;

Django web 基础的更多相关文章

  1. Python开发【第二十一篇】:Web框架之Django【基础】

    Python开发[第二十一篇]:Web框架之Django[基础]   猛击这里:http://www.cnblogs.com/wupeiqi/articles/5237704.html Python之 ...

  2. Django---Http协议简述和原理,HTTP请求码,HTTP请求格式和响应格式(重点),Django的安装与使用,Django项目的创建和运行(cmd和pycharm两种模式),Django的基础文件配置,Web框架的本质,服务器程序和应用程序(wsgiref服务端模块,jinja2模板渲染模块)的使用

    Django---Http协议简述和原理,HTTP请求码,HTTP请求格式和响应格式(重点),Django的安装与使用,Django项目的创建和运行(cmd和pycharm两种模式),Django的基 ...

  3. Python之路【第十六篇】:Django【基础篇】

    Python之路[第十六篇]:Django[基础篇]   Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了O ...

  4. Python Django(WEB电商项目构建)

    (坚持每一天,就是成功) Python Django Web框架,Django是一个开放源代码的Web应用框架,由Python写成.采用了MTV的框架模式,即模型M,模板T和视图V组成. 安装Pyth ...

  5. django 的基础设计

    一.web程序工作流程 二.django  的基础介绍 目的:了解Django框架的作用和特点 作用: 简便.快速的开发数据库驱动的网站 Django的优势 快速开发 MVT 功能齐全 Django学 ...

  6. Golang友团无闻Go语言Web基础视频教程

    教程内容:GO语言资料Golang友团无闻Go语言编程基础Golang友团无闻Go语言Web基础教程 Go语言Web基础教程列表:[Go Web基础]12Go Web 扩展学习.mp4[Go Web基 ...

  7. HT for Web基础动画介绍

    在上一篇<基于HT for Web矢量实现3D叶轮旋转>一文中,我略微提了下HT for Web基础动画的相关用法,但是讲得不深入,今天就来和大家分享下HT for Web基础动画的相关介 ...

  8. Web基础开发最核心要解决的问题

    Web基础开发要解决的问题,往往也就是那些框架出现的目的 - 要解决问题. 1. 便捷的Db操作: 2. 高效的表单处理: 3. 灵活的Url路由: 4. 合理的代码组织结构: 5. 架构延伸 缓存. ...

  9. Django web 开发指南 no such table:

    在学习django web开发指南时,发布新博客点击save后会有error提示:no such table balabalabala... 百度了一下说重新运行manage.py syncdb 就可 ...

随机推荐

  1. javascript 封装(给自己看)

    HTML <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3 ...

  2. 数据获取以及处理系统 --- 功能规格说明书V2.0

    产品规格说明书: 版本号: V2.0 版本说明: Version 1.0 简单得需求分析以及构思,初稿形成 Version 2.0 细化beta阶段设计,增加典型用户尝尽以及功能罗列 1. 引言 1. ...

  3. Base64编码解码

    一. Base64编码由来 为什么会有Base64编码呢?因为有些网络传送渠道并不支持所有的字节,例如传统的邮件只支持可见字符的传送,像ASCII码的控制字符就不能通过邮件传送.这样用途就受到了很大的 ...

  4. ruby&mongo_mapper

    mongo_mapper&ruby Mongomapper 用户mongo数据库配置,以及其提供了很多mongo的方法,可以很好地用来 对mongo相关封装和操作. 环境准备:gem inst ...

  5. Eclipse 配置Activiti插件

    Eclipse 配置Activiti插件 我使用的是Eclipse LUNA 4.4.0 点击Eclipse上方工具栏[Help]选择[Install New Software] 在弹出的窗口点击[A ...

  6. 【uTenux实验】集合点端口

    这个是头一次接触的概念.比较不好理解.内核规范中的说明就要20页! 看了王总写的uTenux内核规范之后,有那么一点明白了但理解不深. 集合点端口就像每次工作前的收集情况会.首长下达收集情况指令,各个 ...

  7. redmine 配置邮件发送为async后,不能发送邮件(转载)

    通过参考:http://www.oschina.net/question/2005703_16688 之前configuration.yaml文件中email的相关配置如下: production: ...

  8. REST风格URL

    以前就是觉得 /nowamagic/article/article_id 这样的地址非常的漂亮,但是那只是表象罢了,了解深入以后,发现必须有一个客户端的Ajax Engine和Server端的服务配合 ...

  9. web.config

    参数上传和文件上传大小限制调整,参数上传最大2097151 <system.web> <httpRuntime requestValidationMode="2.0&quo ...

  10. ChartControl

    <dxc:ChartControl Name="chartControl1">            <dxc:ChartControl.Diagram>  ...