数据库配置:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME':'dbname',
'USER': 'root',
'PASSWORD': '123456',
'HOST': '',
'PORT': '',
}
}
模板配置
TEMPLATE_DIRS = (
os.path.join(BASE_DIR,'templates'),
)
静态文件配置
STATICFILES_DIRS = (
os.path.join(BASE_DIR,'static'),
)
MEDIA_ROOT:是本地路径的绝对路径,一般是这样写
MEDIA_URL:是指从浏览器访问时的地址前缀
MEDIA_URL = '/upload/' MEDIA_ROOT = os.path.join(BASE_DIR,'upload')
路由映射
1、每个路由规则对应一个view中的函数
url(r'^index/(\d*)', views.index),
url(r'^list/(\d*)/(\d*)/$', views.list),
url(r'^manage/(?P<name>\w*)/(?P<id>\d*)', views.manage),
url(r'^login/(?P<name>\w*)', views.login,{'id':333}),
复制代码
def index(request,id): # id形参的名字是随便定义的
return render_to_response('index.html')
def list(request,id1,id2): # id1,id2形参的名字是随便定义的
return render_to_response('list.html')
def manage(request,name,id): # name,id形参的名字是和(?P<name>\w*)/(?P<id>\d*)是一样的
return render_to_response('index.html')
def login(request,name,id): # name,id形参的名字是和(?P<name>\w*),{'id':333}是一样的
return render_to_response('login.html')
复制代码
2、根据app对路由规则进行一次分类
1
2
3
4
5
6
from django.conf.urls import include
urlpatterns = patterns[
url(r'^web/', include('web.url')),
url(r'^app01/', include('app01.url')),
]
django中的路由系统和其他语言的框架有所不同,在django中每一个请求的url都要有一条路由映射,这样才能将请求交给对一个的view中的函数去处理。其他大部分的Web框架则是对一类的url请求做一条路由映射,从而是路由系统变得简洁。
models
同步数据库
python manage.py makemigrations
python manage.py migrate
1、创建Model,之后可以根据Model来创建数据库表
1
2
3
4
5
6
|
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正则表达式),django1.10逐步废弃使用下面一种 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 图片,需要max_length 24、models.FilePathField 文件,需要max_length
更多参数:
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)
gender_choice = (
(0,'男'),
(1,'女'),
)
gender = models.IntergetFiled(choice=gener_choice) # 数据库中存储的是0,1但是显示的是男,女
6、max_length # 在charfield必须指定最大长度 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 # 在Admin错误提示 14、auto_created=False # 自动创建 15、help_text # 在Admin中提示帮助信息 16、validators=[] # 自定义规则 17、upload-to # 指定上传的路径
18、class Meta():
verbose_name = '这张表的名字在admin后台的显示名字'
verbose_name_plural = verbose_name
ordering = ['-id'] # 根据id反向排序
数据库操作:
增加:create()
1
2
3
4
5
6
7
8
|
# 第一种方式
models.类名.objects.create(hostname
=
name)
# 第二种方式
obj
=
models.类名(hostname
=
name)
obj.save()
注意:hostname是数据库中的字段名,name是变量
|
更新:update()
1
2
3
4
5
6
7
|
# 第一种方式
models.类名.objects.
filter
(
id
=
2
).update(hostname
=
'tomcat'
)
# 第二种方式
obj
=
models.类名.objects.get(
id
=
2
)
obj.hostname
=
'tomcat'
obj.save()
|
删除:delete()
1
2
3
|
models.类名.objects.get(
id
=
2
).delete()
models.类名.objects.
filter
(
id
=
2
).delete()
models.类名.objects.
all
().delete()
|
查询:filter(),all(),get(),getlist()用于取多个值
1
2
3
|
models.类名.objects.get(
id
=
123
)
# 获取单条数据,不存在则报错(不建议)
models.类名.objects.
all
()
# 获取全部
models.类名.objects.
filter
(name
=
'tomcat'
)
# 获取指定条件的数据
|
显示指定字段:values(),values_list()
models.类名.objects.get(id=123).values('id','name') # 返回的是queryset字典 models.类名.objects.get(id=123).values__list('id','name') # 返回的是queryset元组
复杂查询:Q()表达式:
https://docs.djangoproject.com/en/1.9/topics/db/queries/#complex-lookups-with-q-objects
数量:count()
1
2
3
|
models.类名.objects.
filter
(name
=
'tomcat'
).count()
models.类名.objects.get(name
=
'tomcat'
).count()
models.类名.objects.
all
().count()
|
去重:distinct()
models.类名.objects.values('字段').distinct()
大于小于:__gt,__lt,__gte,__lte
1
2
3
|
models.类名.objects.
filter
(id__gt
=
1
)
# 获取id大于1的值
models.类名.objects.
filter
(id__lt
=
10
)
# 获取id小于10的值
models.类名.objects.
filter
(id__lt
=
10
, id__gt
=
1
)
# 获取id大于1 且 小于10的值
|
等于多个值:__in
1
2
|
models.类名.objects.
filter
(id__in
=
[
11
,
22
,
33
])
# 获取id等于11、22、33的数据
models.类名.objects.exclude(id__in
=
[
11
,
22
,
33
])
# not in
|
模糊查询:__contains,__icontains
1
2
3
|
models.类名.objects.
filter
(name__contains
=
"ven"
)
models.类名.objects.
filter
(name__icontains
=
"ven"
)
# icontains大小写不敏感
models.类名.objects.exclude(name__icontains
=
"ven"
)
|
范围查询:__range
1
|
models.类名.objects.
filter
(id__range
=
[
1
,
2
])
# 范围bettwen and
|
其他类似:__startswith,__endswith, __iendswith, __istartswith
排序:order_by("name") 相当于asc;order_by("-name") 相当于desc;
1
2
|
models.类名.objects.
filter
(name
=
'seven'
).order_by(
'id'
)
# asc,从小到大
models.类名.objects.
filter
(name
=
'seven'
).order_by(
'-id'
)
# desc,从大到小
|
返回第n-m条:第n条[0];前两条[0:2]
1
2
3
|
# limit 、offset
models.类名.objects.
all
()[
10
:
20
]
|
分组与聚合:group_by,annotate,aggregate
- Avg(返回所给字段的平均值)
- Count(根据所给的关联字段返回被关联 model 的数量)
- Max(返回所给字段的最大值)
- Min(返回所给字段的最小值)
- Sum(计算所给字段值的总和)
1
2
3
4
|
# group by
from
django.db.models
import
Count,
Min
,
Max
,
Sum
# models.类名.objects.filter(c1=1).values('id').annotate(c=Count('num'))
# SELECT "app01_类名"."id", COUNT("app01_类名"."num") AS "c" FROM "app01_类名" WHERE "app01_类名"."c1" = 1 GROUP BY "app01_类名"."id"
|
还可以:
>>> Publisher.objects.filter(name='广东人民出版社').aggregate(Count('name'))
还可以自定义别名
>>> Publisher.objects.filter(name='广东人民出版社').aggregate(mycount = Count('name'))
查询胡大海出的书的总价格是多少
>>> Book.objects.filter(authors__name='胡大海').aggregate(Sum('price'))
查询各个作者出的书的总价格是多少
>>> Book.objects.values('authors__name').annotate(Sum('price'))
查询各个出版社最便宜的书价是多少
>>> Book.objects.values('publisher__name').annotate(Min('price'))
跨表操作
一对一
一对多
多对多
F和Q
F 使用查询条件的值
#
# from django.db.models import F
# models.Tb1.objects.update(num=F('num')+1)
# Q 构建搜索条件
from django.db.models import Q
# con = Q()
#
# q1 = Q()
# q1.connector = 'OR'
# q1.children.append(('id', 1))
# q1.children.append(('id', 10))
# q1.children.append(('id', 9))
#
# q2 = Q()
# q2.connector = 'OR'
# q2.children.append(('c1', 1))
# q2.children.append(('c1', 10))
# q2.children.append(('c1', 9))
#
# con.add(q1, 'AND')
# con.add(q2, 'AND')
#
# models.Tb1.objects.filter(con)
#
# from django.db import connection
# cursor = connection.cursor()
# cursor.execute("""SELECT * from tb where name = %s""", ['Lennon'])
# row = cursor.fetchone()
form验证
只要有表单提交就必须要有form验证
如:
forms
from django import forms
from hello.models import Publisher
class PublisherForm(forms.Form):
name = forms.CharField(label="名称", error_messages={"required": "这个项必须填写"})
address = forms.CharField(label="地址", error_messages={"required": "这个项必须填写"})
city = forms.CharField(label="城市", error_messages={"required": "这个项必须填写"})
state_province = forms.CharField(label="省份", error_messages={"required": "这个项必须填写"})
country = forms.CharField(label="国家", error_messages={"required": "这个项必须填写"})
website = forms.URLField(label="网址", error_messages={"required": "这个项必须填写"})
views
from django.shortcuts import render, render_to_response, redirect,HttpResponse from hello.models import Publisher from hello.forms import PublisherForm def add_publisher(request): if request.method == "POST": publisher_form = PublisherForm(request.POST) if publisher_form.is_valid(): Publisher.objects.create( name = publisher_form.cleaned_data['name'], address = publisher_form.cleaned_data['address'], city = publisher_form.cleaned_data['city'], state_province = publisher_form.cleaned_data['state_province'], country = publisher_form.cleaned_data['country'], website = publisher_form.cleaned_data['website'], ) return HttpResponse("添加出版社信息成功!") else: publisher_form = PublisherForm() return render(request, 'add_publisher.html', locals())
is_valid()验证成功
参数和models里面的参数类似
modelform 万金油
forms
from django import forms
from hello.models import Publisher
class PublisherForm(forms.ModelForm):
class Meta:
model = Publisher # 把models中的Publisher类绑定过来
exclude = ("id",) # 指定不要显示的字段,fields是指定要显示的字段
views
from django.shortcuts import render, render_to_response, redirect,HttpResponse
from hello.models import Publisher
from hello.forms import PublisherForm
def add_publisher(request):
if request.method == "POST":
publisher_form = PublisherForm(request.POST)
if publisher_form.is_valid():
publisher_form.save() # 这里这一句就把前端传过来的值全部写入数据库中了
return HttpResponse("添加出版社信息成功!")
else:
publisher_form = PublisherForm()
return render(request, 'add_publisher.html', locals())
自定义中间件
自定义中间件
1、创建中间件类
1
2
3
4
5
6
7
8
9
10
|
class
defindemiddleware:
def
process_request(
self
,request):
print
(
123
)
def
process_view(
self
, request, callback, callback_args, callback_kwargs):
print
(
456
)
def
process_exception(
self
, request, exception):
print
(error)
def
process_response(
self
, request, response):
print
(end)<br>
return
response
|
2、注册中间件
1
2
3
4
5
6
7
8
9
|
MIDDLEWARE_CLASSES
=
(<br>
'my.middleware.defindedmiddleware'
,
# 目录结构my/middleware/类名
'django.contrib.sessions.middleware.SessionMiddleware'
,
'django.middleware.common.CommonMiddleware'
,
'django.middleware.csrf.CsrfViewMiddleware'
,
'django.contrib.auth.middleware.AuthenticationMiddleware'
,
'django.contrib.auth.middleware.SessionAuthenticationMiddleware'
,
'django.contrib.messages.middleware.MessageMiddleware'
,
'django.middleware.clickjacking.XFrameOptionsMiddleware'
,
)
|
django 1.10中有点不一样,创建时需要继承父类:
from django.utils import deprecation class defindemiddleware(deprecation.MiddlewareMixin): def process_request(self,request): print(123)
分页:
https://docs.djangoproject.com/en/1.9/topics/pagination/
缓存
Django-redis 文档:
http://niwinz.github.io/django-redis/latest/
http://django-redis-cache.readthedocs.org/en/latest/
Django-redis 缓存后端安装:
$ sudo apt-get install redis-server # 安装Redis Server $ . ~/myprojectenv/bin/active # Source 到虚拟环境 $ pip install django-redis-cache # 安装缓存后端
Django-redis 缓存后端配置:
CACHES = { 'default': { 'BACKEND': 'redis_cache.RedisCache', 'LOCATION': '127.0.0.1:6379', 'OPTIONS': { 'DB': 1, 'PASSWORD': 'yadayada', 'PARSER_CLASS': 'redis.connection.HiredisParser', 'CONNECTION_POOL_CLASS': 'redis.BlockingConnectionPool', 'PICKLE_VERSION': -1, }, }, }
参数
(1)LOCATION:
Redis 服务器信息,可以是 address/port,也可以是 unix 域套接字。
可配置单个string,或者是 strings 的列表。
示例:
127.0.0.1:6379 #普通的TCP连接
/path/to/socket # Unix 域套接字连接
redis://[:password]@localhost:6379/0 # 普通的TCP连接
rediss://[:password]@localhost:6379/0 # SSL 封装的 TCP 连接
# http://redis.io/topics/encryption
unix://[:password]@/path/to/socket.sock?db=0 # Unix 域套接字连接
(2)Database Number:
设置存储空间, 可在 OPTIONS 和 LOCATION 中配置 ( Default DB: 1)
redis://@localhost:6379/0
CACHES = {
'default': {
'OPTIONS': {
'DB': 1,
..
},
...
}
}
(3)Password:
如果 Redis Server 设置了密码,则 CACHE 中也需要设置密码, 可在 OPTIONS 中配置,也可在 LOCATION 中配置
CACHES = {
'default': {
'OPTIONS': {
'PASSWORD': 'yadayada',
...
},
...
}
}
Django-redis 缓存后端配置(redis主从):
CACHES = { 'default': { 'LOCATION': [ '127.0.0.1:6379', # Primary '127.0.0.1:6380', # Secondary '127.0.0.1:6381', # Secondary ], 'OPTIONS': { 'PASSWORD': 'yadayada', 'MASTER_CACHE': '127.0.0.1:6379', ... }, ... } }
例子:
这里使用redis主从架构,做之前需要配置好redis主从,配置好两份redis.conf配置文件即可,slaveof 127.0.0.1 6379
(1)配置好redis主从
$ sudo cp /etc/redis/redis.conf{,1}
$ sudo vi /etc/redis/redis.conf
37 daemonize yes
45 port 6379
64 bind 127.0.0.1
391 requirepass 123456
$ sudo vi /etc/redis/redis.conf1
37 daemonize yes
45 port 6380
64 bind 127.0.0.1
206 slaveof 127.0.0.1 6379
391 requirepass 123456
$ sudo redis-server /etc/redis/redis.conf
$ sudo redis-server /etc/redis/redis.conf1
$ ps -ef | grep redis-server
root 44429 1627 0 14:53 ? 00:00:00 redis-server 127.0.0.1:6379
root 44447 1627 1 14:54 ? 00:00:00 redis-server 127.0.0.1:6380
xiaozhi+ 44480 27618 0 14:54 pts/1 00:00:00 grep --color=auto redis-server
(2)配置settings
CACHES = {
'default': {
'BACKEND': 'redis_cache.RedisCache',
'LOCATION': ['127.0.0.1:6379','127.0.0.1:6380'],
'OPTIONS': {
'MASTER_CACHE': '127.0.0.1:6379',
'DB': 2,
'PASSWORD': '123456',
},
'KEY_PREFIX': 'MyProject',
'TIMEOUT': 480
}
}
(3)使用url方式进行view缓存
from django.views.decorators.cache import cache_page
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^$',cache_page(60 * 15)(Index.as_view())=,name='INDEX'),
url(r'^index2/$',Index2.as_view(),name='INDEX2'),
]
或者在views中的方法上调用装饰器
from django.views.decorators.cache import cache_page
@cache_page(60 * 15, key_prefix='index2')
def Index2(request):
return render(request,'index.html')
(4)使用template片段缓存
{% extends 'base.html' %}
{% load cache %}
{% load staticfiles %}
.
.
{% cache 500 sidebar %}
.
{% endcache %}
信号: (想不起来用法想地雷就可以了)
一般把信号卸载和项目同名的__init__文件中
内置信号
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 # 创建数据库连接时,自动触发
对于Django内置的信号,仅需注册指定信号,当程序执行相应操作时,自动触发注册函数:
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 callback(sender, **kwargs):
print("xxoo_callback")
print(sender,kwargs)
xxoo.connect(callback)
# xxoo指上述导入的内容
from django.core.signals import request_finished
from django.dispatch import receiver
@receiver(request_finished)
def my_callback(sender, **kwargs):
print("Request finished!")
2、自定义信号
a. 定义信号
1
2
|
import
django.dispatch
pizza_done
=
django.dispatch.Signal(providing_args
=
[
"toppings"
,
"size"
])
|
b. 注册信号
1
2
3
4
5
|
def
callback(sender,
*
*
kwargs):
print
(
"callback"
)
print
(sender,kwargs)
pizza_done.connect(callback)
|
c. 触发信号
1
2
3
|
from
路径
import
pizza_done
pizza_done.send(sender
=
'seven'
,toppings
=
123
, size
=
456
)
|