Python的WEB框架有Django、Tornado、Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM、模型绑定、模板引擎、缓存、Session等诸多功能。
基本配置
一、创建django程序
终端命令:django-admin startproject projectname
IED创建django程序时本质上都是自动执行上述命令
其他常用命令:
python manage.py runserver 0.0.0.0
python manage.py startapp appname
python manage.py syncdb
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
二、配置文件
1、数据库
1
2
3
4
5
6
7
8
9
10
11
|
DATABASES
=
{
'default'
: {
'ENGINE'
:
'django.db.backends.mysql'
,
'NAME'
:
'dbname'
,
'USER'
:
'root'
,
'PASSWORD'
:
'xxx'
,
'HOST'
: '',
'PORT'
: '',
}
}
|
# 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替
# 如下设置放置的与project同名的配置的 __init__.py文件中
import pymysql
pymysql.install_as_MySQLdb()
2、模版
TEMPLATE_DIRS = (
os.path.join(BASE_DIR,'templates'),
)
3、静态文件
STATICFILES_DIRS = (
os.path.join(BASE_DIR,'static'),
)
路由系统
1、每个路由规则对应一个view中的函数
url(r'^index/(\d*)', views.index),
url(r'^manage/(?P<name>\w*)/(?P<id>\d*)', views.manage),
url(r'^manage/(?P<name>\w*)', views.manage,{'id':333}),
2、根据app对路由规则进行一次分类
url(r'^web/',include('web.urls')),
django中的路由系统和其他语言的框架有所不同,在django中每一个请求的url都要有一条路由映射,这样才能将请求交给对一个的view中的函数去处理。其他大部分的Web框架则是对一类的url请求做一条路由映射,从而是路由系统变得简洁。
模板
1、模板的执行
模板的创建过程,对于模板,其实就是读取模板(其中嵌套这模板标签),然后将Model中获取的数据插入到模板中,最后将信息返回给用户
1
2
3
4
|
def
current_datetime(request):
now
=
datetime.datetime.now()
html
=
"<html><body>It is now %s.</body></html>"
%
now
return
HttpResponse(html)
|
1
2
3
4
|
from
django
import
template
t
=
template.Template(
'My name is {{ name }}.'
)
c
=
template.Context({
'name'
:
'Adrian'
})
print
t.render(c)
|
1
2
3
4
5
6
7
8
9
10
|
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
|
1
2
3
4
5
6
7
8
9
10
|
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)
|
1
|
return
render_to_response(
'Account/Login.html'
,data,context_instance
=
RequestContext(request))
|
2、模版语言
模板中也有自己的语言,该语言可以实现数据展示
` item `
{% for item in item_list %} <a>` item `</a> {% endfor %}
forloop.counter
forloop.first
forloop.last
{% if ordered_warranty %} {% else %} {% endif %}
母板:{% block title %}{% endblock %}
子板:{% extends "base.html" %}
{% block title %}{% endblock %}
帮助方法:
{{ item.event_start|date:"Y-m-d H:i:s"}}
{{ bio|truncatewords:"30" }}
{{ my_list|first|upper }}
{{ name|lower }}
3、自定义simple_tag
a、在app中创建templatetags模块
b、创建任意 .py 文件,如:xx.py
#!/usr/bin/env python
#coding:utf-8
from django import template
from django.utils.safestring import mark_safe
from django.template.base import resolve_variable, Node, TemplateSyntaxError
register = template.Library()
@register.simple_tag
def my_simple_time(v1,v2,v3):
return v1 + v2 + v3
@register.simple_tag
def my_input(id,arg):
result = "<input type='text' id='%s' class='%s' />" %(id,arg,)
return mark_safe(result)
c、在使用自定义simple_tag的html文件中导入之前创建的 xx.py 文件名
{% load xx %}
d、使用simple_tag
{% my_simple_time 1 2 3%}
{% my_input 'id_username' 'hide'%}
e、在settings中配置当前app,不然django无法找到自定义的simple_tag
1
2
3
4
5
6
7
8
9
|
INSTALLED_APPS
=
(
'django.contrib.admin'
,
'django.contrib.auth'
,
'django.contrib.contenttypes'
,
'django.contrib.sessions'
,
'django.contrib.messages'
,
'django.contrib.staticfiles'
,
'app01'
,
)
|
From表单
django的Form一般由两种功能:
-
输入html
-
验证用户的输入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
#!/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
'邮箱'
}))
def
__init__(
self
,
*
args,
*
*
kwargs):
super
(SampleImportForm,
self
).__init__(
*
args,
*
*
kwargs)
self
.fields[
'idc'
].widget.choices
=
models.IDC.objects.
all
().order_by(
'id'
).values_list(
'id'
,
'display'
)
self
.fields[
'business_unit'
].widget.choices
=
models.BusinessUnit.objects.
all
().order_by(
'id'
).values_list(
'id'
,
'name'
)
|
1
2
3
4
5
6
7
8
9
10
11
12
|
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中字段的定义
1
2
3
4
5
6
7
8
9
10
|
class
AdminModelForm(forms.ModelForm):
class
Meta:
model
=
models.Admin
#fields = '__all__'
fields
=
(
'username'
,
'email'
)
widgets
=
{
'email'
: forms.PasswordInput(attrs
=
{
'class'
:
"alex"
}),
}
|
Model
到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞:
创建数据库,设计表结构和字段
使用 MySQLdb 来连接数据库,并编写数据访问层代码
业务逻辑层去调用数据访问层执行数据库操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import
MySQLdb
def
GetList(sql):
db
=
MySQLdb.connect(user
=
'root'
, db
=
'ucodedb'
, passwd
=
'1234'
, host
=
'localhost'
)
cursor
=
db.cursor()
cursor.execute(sql)
data
=
cursor.fetchall()
db.close()
return
data
def
GetSingle(sql):
db
=
MySQLdb.connect(user
=
'root'
, db
=
'ucodedb'
, passwd
=
'1234'
, host
=
'localhost'
)
cursor
=
db.cursor()
cursor.execute(sql)
data
=
cursor.fetchone()
db.close()
return
data
|
django为使用一种新的方式,即:关系对象映射(Object Relational Mapping,简称ORM)。
PHP:activerecord
Java:Hibernate
C#:Entity Framework
django中遵循 Code Frist 的原则,即:根据代码中定义的类来自动生成数据库表。
1、创建Model,之后可以根据Model来创建数据库表
from django.db import models
class userinfo(models.Model):
name = models.CharField(max_length=30)
email = models.EmailField()
memo = models.TextField()
常用字段:
1、models.AutoField 自增列 = int(11)
如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。
2、models.CharField 字符串字段
必须 max_length 参数
3、models.BooleanField 布尔类型=tinyint(1)
不能为空,Blank=True
4、models.ComaSeparatedIntegerField 用逗号分割的数字=varchar
继承CharField,所以必须 max_lenght 参数
5、models.DateField 日期类型 date
对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。
6、models.DateTimeField 日期类型 datetime
同DateField的参数
7、models.Decimal 十进制小数类型 = decimal
必须指定整数位max_digits和小数位decimal_places
8、models.EmailField 字符串类型(正则表达式邮箱) =varchar
对字符串进行正则表达式
9、models.FloatField 浮点类型 = double
10、models.IntegerField 整形
11、models.BigIntegerField 长整形
integer_field_ranges = {
'SmallIntegerField': (-32768, 32767),
'IntegerField': (-2147483648, 2147483647),
'BigIntegerField': (-9223372036854775808, 9223372036854775807),
'PositiveSmallIntegerField': (0, 32767),
'PositiveIntegerField': (0, 2147483647),
}
12、models.IPAddressField 字符串类型(ip4正则表达式)
13、models.GenericIPAddressField 字符串类型(ip4和ip6是可选的)
参数protocol可以是:both、ipv4、ipv6
验证时,会根据设置报错
14、models.NullBooleanField 允许为空的布尔类型
15、models.PositiveIntegerFiel 正Integer
16、models.PositiveSmallIntegerField 正smallInteger
17、models.SlugField 减号、下划线、字母、数字
18、models.SmallIntegerField 数字
数据库中的字段有:tinyint、smallint、int、bigint
19、models.TextField 字符串=longtext
20、models.TimeField 时间 HH:MM[:ss[.uuuuuu]]
21、models.URLField 字符串,地址正则表达式
22、models.BinaryField 二进制
23、models.ImageField 图片
24、models.FilePathField 文件
常用字段的参数
1、null=True
数据库中字段是否可以为空
2、blank=True
django的 Admin 中添加数据时是否可允许空值
3、primary_key = False
主键,对AutoField设置主键后,就会代替原来的自增 id 列
4、auto_now 和 auto_now_add
auto_now 自动创建---无论添加或修改,都是当前操作的时间
auto_now_add 自动创建---永远是创建时的时间
5、choices
GENDER_CHOICE = (
(u'M', u'Male'),
(u'F', u'Female'),
)
gender = models.CharField(max_length=2,choices = GENDER_CHOICE)
6、max_length
7、default 默认值
8、verbose_name Admin中字段的显示名称
9、name|db_column 数据库中的字段名称
10、unique=True 不允许重复
11、db_index = True 数据库索引
12、editable=True 在Admin里是否可编辑
13、error_messages=None 错误提示
14、auto_created=False 自动创建
15、help_text 在Admin中提示帮助信息
16、validators=[]
17、upload-to
实现功能
①实现文件上传
home.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
def
upload(request):
if
request.method
=
=
"POST"
:
inp_post
=
request.POST
#POST提交时上传者自定义的文件名
print
inp_post
inp_files
=
request.FILES
#获取提交的文件
print
inp_files
file_obj
=
inp_files.get(
"file_name1"
)
#获取上传文件的名字
f
=
open
(file_obj.name,
'wb'
)
for
line
in
file_obj.chunks():
f.write(line)
f.close()
return
render(request,
'home/upload.html'
)
|
upload.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<!DOCTYPE html>
<
html
lang
=
"en"
>
<
head
>
<
meta
charset
=
"UTF-8"
>
<
title
></
title
>
</
head
>
<
body
>
<
form
action
=
"/upload/"
method
=
"POST"
enctype
=
"multipart/form-data"
>
<!-- enctype="multipart/form-data 表示上传的数据进行分片上传"-->
<
p
><
input
type
=
"file"
name
=
"file_name1"
/></
p
>
<
p
><
input
type
=
"text"
name
=
"filename"
/></
p
>
<!-- <p><input type="file" name="file_name2"/></p>
<p><input type="text" name="filename"/></p> -->
<
input
type
=
"submit"
value
=
"Upload"
/>
</
form
>
</
body
>
</
html
>
|
url.py
1
2
3
4
5
6
7
8
|
from
django.conf.urls
import
url
from
django.contrib
import
admin
from
app01.views
import
account
from
app01.views
import
home
urlpatterns
=
[
url(r
'login/'
,account.login ),
url(r
'index/'
,home.index ),
url(r
'upload/'
,home.upload ),
|
Form表单中的CharField字段
1
2
3
4
5
6
7
8
9
10
|
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__
=
'ryan'
from
django
import
forms
class
LoginForm(forms.Form):
username
=
forms.CharField()
password
=
forms.CharField(widget
=
forms.PasswordInput())
#定义password数据格式为不显示
|
models中的CharField字段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from
__future__
import
unicode_literals
from
django.db
import
models
#ORM
# 类 ---->数据库
# 对象 --->一行数据
# 对象.id,对象.value -->每行里的数据
class
UserInfo(models.Model):
USER_TYPE_LIST
=
(
(
1
,
"F"
),
(
2
,
"M"
),
)
#定义USER_TYPE_LIST元组,赋给choices实现多选框功能
name
=
models.CharField(max_length
=
32
,primary_key
=
True
)
user_type
=
models.IntegerField(choices
=
USER_TYPE_LIST,default
=
1
)
ctime
=
models.DateTimeField(auto_now
=
True
)
uptime
=
models.DateTimeField(auto_now_add
=
True
)
email
=
models.EmailField(max_length
=
32
,null
=
True
)
email_default
=
models.EmailField(max_length
=
32
,default
=
"admin@163.com"
)
ip
=
models.GenericIPAddressField(protocol
=
'both'
,null
=
True
,blank
=
True
)
img
=
models.ImageField(null
=
True
,blank
=
True
,upload_to
=
"upload"
)
def
__unicode__(
self
):
return
self
.name
|
两个模块中的charField等字段的区别说明:
forms跟数据库没有关系,当用户发送过来请求的时候,forms只用来验证用户输入的合法性,
即返回给用户的结果(提示)要么是正确的要么是错误,换句话说forms验证用户输入是否合法,
返回给用户的信息就是用户本次输入合法与否
models.xxx只用来控制数据库的创建,对于django框架,如果没有后台管理功能,则不会出现如下的models.xxxx类型的字段,
只会存在基本的几种类,比如布尔、浮点型、整型、字符串类型等基本的几种数据类型,也就是我们常说的Python基本数据类型