1、Model 一对多 补充

models如下:

  1. class UserType(models.Model):
  2. caption = models.CharField(max_length=16)
  3.  
  4. class UserInfo(models.Model):
  5. username = models.CharField(max_length=32)
  6. pwd = models.CharField(max_length=32)
  7. user_type = models.ForeignKey('UserType')

通过queryset查询用户为CEO的用户

  1. >>> from app01.models import UserInfo,UserType
  2. >>> q = UserInfo.objects.filter(user_type__caption='CEO')
  3. >>> print(q)
  4. <QuerySet [<UserInfo: UserInfo object>]>
  5. >>> print(q[0])
  6. UserInfo object
  7. >>> print(q[0].username)
  8. james
  9. >>> print(q[0].pwd)
  10. 45569
  11. >>> print(q[0].user_type.caption)
  12. CEO

用values,value_list查询

  1. >>> q = UserInfo.objects.filter(user_type__caption='CEO').values('username','pwd','user_type__caption')
  2. >>> q
  3. <QuerySet [{'pwd': '45569', 'username': 'james', 'user_type__caption': 'CEO'}]>
  4. >>> q[0]
  5. {'pwd': '45569', 'username': 'james', 'user_type__caption': 'CEO'}

value_list 返回元组可以应用到from的select标签

  1. >>> q = UserInfo.objects.filter(user_type__caption='CEO').values_list('username','pwd','user_type__caption')
  2. >>> q
  3. <QuerySet [('james', '45569', 'CEO')]>
  4. >>> q[0]
  5. ('james', '45569', 'CEO')

2、model操作 F/Q

F:使用查询条件的值

temp = salary+500
models.UserInfo.objects.filter().update(salary=temp)
update userinfo set salary=salary+500

  1. >>> from django.db.models import F
  2. >>> print(models.UserInfo.objects.values('salary'))
  3. <QuerySet [{'salary': '6500'}, {'salary': '6500'}, {'salary': '6500'}]>
  4. >>> print(models.UserInfo.objects.filter().update(salary=F('salary')+500))
  5. 3
  6. >>> print(models.UserInfo.objects.values('salary'))
  7. <QuerySet [{'salary': '7000'}, {'salary': '7000'}, {'salary': '7000'}]>

Q:构造搜索条件
1、传参

  1. >>> models.UserInfo.objects.filter(id=3,user='jasonwang')
  2. <QuerySet [<UserInfo: jasonwang>]>
  3. >>> print(models.UserInfo.objects.filter(id=3,user='jasonwang').query)
  4. SELECT "app01_userinfo"."id", "app01_userinfo"."user", "app01_userinfo"."pwd", "app01_userinfo"."user_type_id", "app01_userinfo"."ctime", "app01_userinfo"."uptime", "app01_userinfo"."img", "app01_userinfo"."email", "app01_userinfo"."address", "app01_userinfo"."salary" FROM "app01_userinfo" WHERE ("app01_userinfo"."id" = 3 AND "app01_userinfo"."user" = jasonwang)

2、传字典

  1. >>> d = {'id':3,'user':'jasonwang'}
  2. >>> models.UserInfo.objects.filter(**d)
  3. <QuerySet [<UserInfo: jasonwang>]>

<input name='id' />
<input name='name' />
获取用户输入,并构造成字典:
models.UserInfo.objects.filter(**d)
3、传Q对象
models.UserInfo.objects.filter(Q对象)

from django.db.models import Q

# q1 = Q()
# q1.connector = 'OR'
# q1.children.append(('id', 1))
# q1.children.append(('id', 2))
# q1.children.append(('id', 3))

# models.Tb1.objects.filter(q1)

  1. >>> q1.connector = 'OR'
  2. >>> q1.children.append(('id',1))
  3. >>> q1.children.append(('id',2))
  4. >>> q1.children.append(('id',3))
  5. >>> qq = models.UserInfo.objects.filter(q1)
  6. >>> print(qq.query)
  7. SELECT "app01_userinfo"."id", "app01_userinfo"."user", "app01_userinfo"."pwd", "app01_userinfo"."user_type_id", "app01_userinfo"."ctime", "app01_userinfo"."uptime", "app01_userinfo"."img", "app01_userinfo"."email", "app01_userinfo"."address", "app01_userinfo"."salary" FROM "app01_userinfo" WHERE ("app01_userinfo"."id" = 1 OR "app01_userinfo"."id" = 2 OR "app01_userinfo"."id" = 3)

# con = Q()
#
# q1 = Q()
# q1.connector = 'OR'
# q1.children.append(('id', 1))
# q1.children.append(('id', 2))
# q1.children.append(('id', 3))
#
# q2 = Q()
# q2.connector = 'OR'
# q2.children.append(('status', '在线'))
#
# con.add(q1, 'AND')
# con.add(q2, 'AND')
#
# models.Tb1.objects.filter(con)

  1. >>> q1.connector = 'OR'
  2. >>> q1.children.append(('id',1))
  3. >>> q1.children.append(('id',2))
  4. >>> q1.children.append(('id',3))
  5. >>> qq = models.UserInfo.objects.filter(q1)
  6. >>> print(qq.query)
  7. SELECT "app01_userinfo"."id", "app01_userinfo"."user", "app01_userinfo"."pwd", "app01_userinfo"."user_type_id", "app01_userinfo"."ctime", "app01_userinfo"."uptime", "app01_userinfo"."img", "app01_userinfo"."email", "app01_userinfo"."address", "app01_userinfo"."salary" FROM "app01_userinfo" WHERE ("app01_userinfo"."id" = 1 OR "app01_userinfo"."id" = 2 OR "app01_userinfo"."id" = 3)
  8. >>> q2 = Q()
  9. >>> q2.connector = 'OR'
  10. >>> q2.children.append(('address','haidian'))
  11. >>> con = Q()
  12. >>> con.add(q1,'AND')
  13. <Q: (OR: ('id', 1), ('id', 2), ('id', 3))>
  14. >>> con.add(q2,'AND')
  15. <Q: (AND: (OR: ('id', 1), ('id', 2), ('id', 3)), ('address', 'haidian'))>
  16. >>> qq = models.UserInfo.objects.filter(con)
  17. >>> print(qq.query)
  18. SELECT "app01_userinfo"."id", "app01_userinfo"."user", "app01_userinfo"."pwd", "app01_userinfo"."user_type_id", "app01_userinfo"."ctime", "app01_userinfo"."uptime", "app01_userinfo"."img", "app01_userinfo"."email", "app01_userinfo"."address", "app01_userinfo"."salary" FROM "app01_userinfo" WHERE (("app01_userinfo"."id" = 1 OR "app01_userinfo"."id" = 2 OR "app01_userinfo"."id" = 3) AND "app01_userinfo"."address" = haidian)
  19. >>> print(qq)
  20. <QuerySet [<UserInfo: jason>]>
  21. >>> print(qq[0])
  22. jason
  23. >>>

3、model多对多操作

- 创建

a. 方式一:
class B2G(models.Model):
b_id = models.ForeignKey('Boy')
g_id = models.ForeignKey('Girl')

class Boy(models.Model):

username = models.CharField(max_length=16)

class Girl(models.Model):

name = models.CharField(max_length=16)

b. 方式二:
class Boy(models.Model):

username = models.CharField(max_length=16)
# girl_set
class Girl(models.Model):

name = models.CharField(max_length=16)

b = models.ManyToManyField('Boy')

- 操作:
添加:
正向

  1. g1 = models.Girl.objects.get(id=1)
  2.  
  3. g1.b.add(models.Boy.objects.get(id=1))
  4. g1.b.add(1)
  5.  
  6. bs = models.Boy.objects.all()
  7. g1.b.add(*bs)
  8. g1.b.add(*[1,2,3])

反向

  1. b1 = models.Boy.objects.get(id=1)
  2. b1.girl_set.add(1)
  3. b1.girl_set.add(models.Girl.objects.all())
  4.  
  5. b1.girl_set.add(*[1,2,3,4])

...
删除:

  1. g1 = models.Girl.objects.get(id=1)
  2. g1.b.clear() # 清空和girl ID=1所关联的所有数据
  3.  
  4. g1.b.remove(2)
  5. g1.b.remove(*[1,2])

查询:

  1. g1 = models.Girl.objects.get(id=1) # SQL
  2. g1.b.all() # SQL
  3. g1.b.filter().count()
  4.  
  5. b1 = models.Boy.objects.get(id=1)
  6. b1.girl_set.all()
  7.  
  8. models.Girl.objects.all().values('id','name', 'b__username')
  9. models.Boy.objects.all().values('id','username', 'girl__name')

更新:

ORM:
python操作数据库模块:
MySQLdb
pymysql

原生SQL
# from django.db import connection
# cursor = connection.cursor()
# cursor.execute("""SELECT * from tb where name = %s""", ['Lennon'])
# row = cursor.fetchone()

4、中间件

中间件介绍:

中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能。 
每个中间件都会负责一个功能,例如,AuthenticationMiddleware,与sessions处理相关。

激活中间件:

需要在settings.py配置文件中,配置MIDDLEWARE_CLASSES:

  1. MIDDLEWARE_CLASSES = [
  2. 'django.middleware.security.SecurityMiddleware',
  3. 'django.contrib.sessions.middleware.SessionMiddleware',
  4. 'django.middleware.common.CommonMiddleware',
  5. 'django.middleware.csrf.CsrfViewMiddleware',
  6. 'django.contrib.auth.middleware.AuthenticationMiddleware',
  7. 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
  8. 'django.contrib.messages.middleware.MessageMiddleware',
  9. 'django.middleware.clickjacking.XFrameOptionsMiddleware',
  10. # 'django.middleware.cache.FetchFromCacheMiddleware',
  11. ]

当然你也可以不试用任何的中间件,这个可以设置为空。

中间件顺序

一般我们我们从浏览器发出一个请求 Request,得到一个响应后的内容 HttpResponse ,这个请求传递到 Django的过程如下,process request 和 process response的执行顺序正好相反,当有请求过来的时候,默认从上倒下执行!然后在返回的时候从下面在返回回去,如下图所示。

也就是说,每一个请求都是先通过中间件中的 process_request 函数,这个函数返回 None 或者 HttpResponse 对象,如果返回前者,继续处理其它中间件,如果返回一个 HttpResponse,就处理中止,返回到网页上。 
中间件不用继承自任何类(可以继承 object ),

自定义一个中间件:

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

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

process_exception 这个方法只有在出现错误的时候才会触发

先写一个自定义中间件,然后在看他的原理和源码,首先把自定义的中间件加到settings文件中:

写类:
process_request
process_view
process_exception
process_response

  1. from django.shortcuts import HttpResponse
    from django.utils import deprecation
    class M1(deprecation.MiddlewareMixin):
    def process_request(self, request):
    print('M1.process_request')
    # return HttpResponse('滚')
  2.  
  3. def process_view(self, request, callback, callback_args, callback_kwargs):
    print('m1.process_view')
  4.  
  5. def process_exception(self, request, exception):
    print('m1.process_exception')
  6.  
  7. def process_response(self, request, response):
    print('M1.process_response')
    return response
  8.  
  9. def process_template_response(self,request,response):
    print('template')
  10.  
  11. class M2(deprecation.MiddlewareMixin):
    def process_request(self, request):
    print('M2.process_request')
    def process_view(self, request, callback, callback_args, callback_kwargs):
    print('m2.process_view')
    def process_exception(self, request, exception):
    print('m2.process_exception')
  12.  
  13. def process_response(self, request, response):
    print('M2.process_response')
    return response

django 1.10中自定义中间建需要制定继承的deprecation.MiddlewareMixin类,否则会出现如下报错

mw_instance = middleware(handler)
TypeError: object() takes no parameters


1.10配置文件:
MIDDLEWARE =

  1. MIDDLEWARE = [
  2. 'md.mymiddle.M1',
  3. 'md.mymiddle.M2',
  4. 'django.middleware.security.SecurityMiddleware',
  5. 'django.contrib.sessions.middleware.SessionMiddleware',
  6. 'django.middleware.common.CommonMiddleware',
  7. 'django.middleware.csrf.CsrfViewMiddleware',
  8. 'django.contrib.auth.middleware.AuthenticationMiddleware',
  9. 'django.contrib.messages.middleware.MessageMiddleware',
  10. 'django.middleware.clickjacking.XFrameOptionsMiddleware',
  11. ]

测试使用url和views

  1. url(r'^md/',views.md),
  1. def md(request):
  2. return HttpResponse('ok')

查看输出结果:

  1. M1.process_request
  2. M2.process_request
  3. m1.process_view
  4. m2.process_view
  5. M2.process_response
  6. M1.process_response

5 Django的Request/Response处理流程的分析

一、 处理过程的核心概念

如下图所示django的总览图,整体上把握以下django的组成

核心在于中间件middleware,django所有的请求、返回都由中间件来完成。

中间件,就是处理HTTP的request和response的,类似插件,比如有Request中间件、view中间件、response中间件、exception中间件等,Middleware都需要在 “project/settings.py” 中 MIDDLEWARE_CLASSES 的定义。大致的程序流程图如下所示:


首先,Middleware都需要在 “project/settings.py” 中 MIDDLEWARE_CLASSES 的定义, 一个HTTP请求,将被这里指定的中间件从头到尾处理一遍,暂且称这些需要挨个处理的中间件为处理链,如果链中某个处理器处理后没有返回response,就把请求传递给下一个处理器;如果链中某个处理器返回了response,直接跳出处理链由response中间件处理后返回给客户端,可以称之为短路处理。

上面的两张流程图可以大致描述Django处理request的流程,按照流程图2的标注,可以分为以下几个步骤:

1. 用户通过浏览器请求一个页面

2. 请求到达Request Middlewares,中间件对request做一些预处理或者直接response请求

3. URLConf通过urls.py文件和请求的URL找到相应的View

4. View Middlewares被访问,它同样可以对request做一些处理或者直接返回response

5. 调用View中的函数

6. View中的方法可以选择性的通过Models访问底层的数据

7. 所有的Model-to-DB的交互都是通过manager完成的

8. 如果需要,Views可以使用一个特殊的Context

9. Context被传给Template用来生成页面

a. Template使用Filters和Tags去渲染输出

b. 输出被返回到View

c. HTTPResponse被发送到Response Middlewares

d. 任何Response Middlewares都可以丰富response或者返回一个完全不同的response

e. Response返回到浏览器,呈现给用户

上述流程中最主要的几个部分分别是:Middleware(中间件,包括request, view, exception, response),URLConf(url映射关系),Template(模板系统),下面一一介绍一下。

1、Middleware(中间件)

Middleware并不是Django所独有的东西,在其他的Web框架中也有这种概念。在Django中,Middleware可以渗入处理流程的四个阶段:request,view,response和exception,相应的,在每个Middleware类中都有rocess_request,process_view, process_response 和 process_exception这四个方法。你可以定义其中任意一个活多个方法,这取决于你希望该Middleware作用于哪个处理阶段。每个方法都可以直接返回response对象。

Middleware是在Django BaseHandler的load_middleware方法执行时加载的,加载之后会建立四个列表作为处理器的实例变量:

_request_middleware:process_request方法的列表

_view_middleware:process_view方法的列表

_response_middleware:process_response方法的列表

_exception_middleware:process_exception方法的列表

Django的中间件是在其配置文件(settings.py)的MIDDLEWARE_CLASSES元组中定义的。在MIDDLEWARE_CLASSES中,中间件组件用字符串表示:指向中间件类名的完整Python路径。

Django项目的安装并不强制要求任何中间件,如果你愿意,MIDDLEWARE_CLASSES可以为空。中间件出现的顺序非常重要:在request和view的处理阶段,Django按照MIDDLEWARE_CLASSES中出现的顺序来应用中间件,而在response和exception异常处理阶段,Django则按逆序来调用它们。也就是说,Django将MIDDLEWARE_CLASSES视为view函数外层的顺序包装子:在request阶段按顺序从上到下穿过,而在response则反过来。以下两张图可以更好地帮助你理解:

2、URLConf(URL映射)

如果处理request的中间件都没有直接返回response,那么Django会去解析用户请求的URL。URLconf就是Django所支撑网站的目录。它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表。通过这种方式可以告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码。具体的,在Django项目的配置文件中有ROOT_URLCONF常量,这个常量加上根目录”/”,作为参数来创建django.core.urlresolvers.RegexURLResolver的实例,然后通过它的resolve方法解析用户请求的URL,找到第一个匹配的view。

原版本: 如果process_request中有return, 则所有的process_response执行一遍

6、缓存

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

举个例子来说:如果访问量比较大的时候,有很多相同的操作比如:有时候请求的数据比如访问同一条数据,或者同一个页面的时候,其实是没必要的。

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

  • 开发调试
  • 内存
  • 文件
  • 数据库
  • Memcache缓存(python-memcached模块)
  • Memcache缓存(pylibmc模块)

1、配置

a、开发调试

  1. # 此为开始调试用,实际内部不做任何操作
  2. # 配置:
  3. CACHES = {
  4. 'default': {
  5. 'BACKEND': 'django.core.cache.backends.dummy.DummyCache', # 引擎
  6. 'TIMEOUT': 300, # 缓存超时时间(默认300,None表示永不过期,0表示立即过期)
  7. 'OPTIONS':{
  8. 'MAX_ENTRIES': 300, # 最大缓存个数(默认300)
  9. 'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3)
  10. },
  11. 'KEY_PREFIX': '', # 缓存key的前缀(默认空)
  12. 'VERSION': 1, # 缓存key的版本(默认1)
  13. 'KEY_FUNCTION' 函数名 # 生成key的函数(默认函数会生成为:【前缀:版本:key】)
  14. }
  15. }
  16.  
  17. # 自定义key
  18. def default_key_func(key, key_prefix, version):
  19. """
  20. Default function to generate keys.
  21.  
  22. Constructs the key used by all other methods. By default it prepends
  23. the `key_prefix'. KEY_FUNCTION can be used to specify an alternate
  24. function with custom key making behavior.
  25. """
  26. return '%s:%s:%s' % (key_prefix, version, key)
  27.  
  28. def get_key_func(key_func):
  29. """
  30. Function to decide which key function to use.
  31.  
  32. Defaults to ``default_key_func``.
  33. """
  34. if key_func is not None:
  35. if callable(key_func):
  36. return key_func
  37. else:
  38. return import_string(key_func)
  39. return default_key_func

b、内存

  1. # 此缓存将内容保存至内存的变量中
  2. # 配置:
  3. CACHES = {
  4. 'default': {
  5. 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
  6. 'LOCATION': 'unique-snowflake',
  7. }
  8. }
  9.  
  10. # 注:其他配置同开发调试版本

c、文件

  1. # 此缓存将内容保存至文件
  2. # 配置:
  3.  
  4. CACHES = {
  5. 'default': {
  6. 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
  7. 'LOCATION': '/var/tmp/django_cache',
  8. }
  9. }
  10. # 注:其他配置同开发调试版本

d、数据库

  1. # 此缓存将内容保存至数据库
  2.  
  3. # 配置:
  4. CACHES = {
  5. 'default': {
  6. 'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
  7. 'LOCATION': 'my_cache_table', # 数据库表
  8. }
  9. }
  10.  
  11. # 注:执行创建表命令 python manage.py createcachetable

e、Memcache缓存(python-memcached模块)

  1. # 此缓存使用python-memcached模块连接memcache
  2.  
  3. CACHES = {
  4. 'default': {
  5. 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
  6. 'LOCATION': '127.0.0.1:11211',
  7. }
  8. }
  9.  
  10. CACHES = {
  11. 'default': {
  12. 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
  13. 'LOCATION': 'unix:/tmp/memcached.sock',
  14. }
  15. }
  16.  
  17. CACHES = {
  18. 'default': {
  19. 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
  20. 'LOCATION': [
  21. '172.19.26.240:11211',
  22. '172.19.26.242:11211',
  23. ]
  24. }
  25. }

f、Memcache缓存(pylibmc模块)

  1. # 此缓存使用pylibmc模块连接memcache
  2.  
  3. CACHES = {
  4. 'default': {
  5. 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
  6. 'LOCATION': '127.0.0.1:11211',
  7. }
  8. }
  9.  
  10. CACHES = {
  11. 'default': {
  12. 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
  13. 'LOCATION': '/tmp/memcached.sock',
  14. }
  15. }
  16.  
  17. CACHES = {
  18. 'default': {
  19. 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
  20. 'LOCATION': [
  21. '172.19.26.240:11211',
  22. '172.19.26.242:11211',
  23. ]
  24. }
  25. }

2、应用

a. 全站使用

  1. 使用中间件,经过一系列的认证等操作,如果内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户,当返回给用户之前,判断缓存中是否已经存在,如果不存在则UpdateCacheMiddleware会将缓存保存至缓存,从而实现全站缓存
  2.  
  3. MIDDLEWARE = [
  4. 'django.middleware.cache.UpdateCacheMiddleware',
  5. # 其他中间件...
  6. 'django.middleware.cache.FetchFromCacheMiddleware',
  7. ]
  8.  
  9. CACHE_MIDDLEWARE_ALIAS = ""
  10. CACHE_MIDDLEWARE_SECONDS = ""
  11. CACHE_MIDDLEWARE_KEY_PREFIX = ""

b. 单独视图缓存

  1. 方式一:
  2. from django.views.decorators.cache import cache_page
  3.  
  4. @cache_page(60 * 15)
  5. def my_view(request):
  6. ...
  7.  
  8. 方式二:
  9. from django.views.decorators.cache import cache_page
  10.  
  11. urlpatterns = [
  12. url(r'^foo/([0-9]{1,2})/$', cache_page(60 * 15)(my_view)),
  13. ]

c、局部视图使用

  1. a. 引入TemplateTag
  2.  
  3. {% load cache %}
  4.  
  5. b. 使用缓存
  6.  
  7. {% cache 5000 缓存key %}
  8. 缓存内容
  9. {% endcache %}

更多:猛击这里

7.序列化

关于Django中的序列化主要应用在将数据库中检索的数据返回给客户端用户,特别的Ajax请求一般返回的为Json格式。

1、serializers

  1. from django.core import serializers
  2.  
  3. ret = models.BookType.objects.all()
  4.  
  5. data = serializers.serialize("json", ret)

2、json.dumps

  1. import json
  2.  
  3. #ret = models.BookType.objects.all().values('caption')
  4. ret = models.BookType.objects.all().values_list('caption')
  5.  
  6. ret=list(ret)
  7.  
  8. result = json.dumps(ret)

由于json.dumps时无法处理datetime日期,所以可以通过自定义处理器来做扩展,如:

  1. import json
  2. from datetime import date
  3. from datetime import datetime
  4.  
  5. class JsonCustomEncoder(json.JSONEncoder):
  6.  
  7. def default(self, field):
  8.  
  9. if isinstance(field, datetime):
  10. return o.strftime('%Y-%m-%d %H:%M:%S')
  11. elif isinstance(field, date):
  12. return o.strftime('%Y-%m-%d')
  13. else:
  14. return json.JSONEncoder.default(self, field)
  15.  
  16. # ds = json.dumps(d, cls=JsonCustomEncoder)

8、信号

Django中提供了“信号调度”,用于在框架执行操作时解耦。通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者.

1、Django内置信号

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

对于Django内置的信号,仅需注册指定信号,当程序执行相应操作时,自动触发注册函数:

  1. from django.core.signals import request_finished
  2. from django.core.signals import request_started
  3. from django.core.signals import got_request_exception
  4.  
  5. from django.db.models.signals import class_prepared
  6. from django.db.models.signals import pre_init, post_init
  7. from django.db.models.signals import pre_save, post_save
  8. from django.db.models.signals import pre_delete, post_delete
  9. from django.db.models.signals import m2m_changed
  10. from django.db.models.signals import pre_migrate, post_migrate
  11.  
  12. from django.test.signals import setting_changed
  13. from django.test.signals import template_rendered
  14.  
  15. from django.db.backends.signals import connection_created
  16.  
  17. def callback(sender, **kwargs):
  18. print("xxoo_callback")
  19. print(sender,kwargs)
  20.  
  21. xxoo.connect(callback)
  22. # xxoo指上述导入的内容
  1. from django.core.signals import request_finished
  2. from django.dispatch import receiver
  3.  
  4. @receiver(request_finished)
  5. def my_callback(sender, **kwargs):
  6. print("Request finished!")

2、自定义信号

a. 定义信号

  1. import django.dispatch
  2. pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])

b. 注册信号

  1. def callback(sender, **kwargs):
  2. print("callback")
  3. print(sender,kwargs)
  4.  
  5. pizza_done.connect(callback)

c. 触发信号

  1. from 路径 import pizza_done
  2.  
  3. pizza_done.send(sender='seven',toppings=123, size=456)

由于内置信号的触发者已经集成到Django中,所以其会自动调用,而对于自定义信号则需要开发者在任意位置触发。

更多:猛击这里

8、分页(公共插件)

一、Django内置分页

  1. Paginator

二、自定义分页

分页功能在每个网站都是必要的,对于分页来说,其实就是根据用户的输入计算出应该在数据库表中的起始位置。

1、设定每页显示数据条数

2、用户输入页码(第一页、第二页...)

3、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置

4、在数据表中根据起始位置取值,页面上输出数据


需求又来了,需要在页面上显示分页的页面。如:[上一页][1][2][3][4][5][下一页]

1、设定每页显示数据条数

2、用户输入页码(第一页、第二页...)

3、设定显示多少页号

4、获取当前数据总条数

5、根据设定显示多少页号和数据总条数计算出,总页数

6、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置

7、在数据表中根据起始位置取值,页面上输出数据

8、输出分页html,如:[上一页][1][2][3][4][5][下一页]

  1. #!/usr/bin/env python
  2. # _*_coding:utf-8_*_
  3. from django.utils.safestring import mark_safe
  4.  
  5. class PageInfo(object):
  6. def __init__(self,current,totalItem,peritems=5):
  7. self.__current=current
  8. self.__peritems=peritems
  9. self.__totalItem=totalItem
  10. def From(self):
  11. return (self.__current-1)*self.__peritems
  12. def To(self):
  13. return self.__current*self.__peritems
  14. def TotalPage(self): #总页数
  15. result=divmod(self.__totalItem,self.__peritems)
  16. if result[1]==0:
  17. return result[0]
  18. else:
  19. return result[0]+1
  20.  
  21. def Custompager(baseurl,currentPage,totalpage): #基础页,当前页,总页数
  22. perPager=11
  23. #总页数<11
  24. #0 -- totalpage
  25. #总页数>11
  26. #当前页大于5 currentPage-5 -- currentPage+5
  27. #currentPage+5是否超过总页数,超过总页数,end就是总页数
  28. #当前页小于5 0 -- 11
  29. begin=0
  30. end=0
  31. if totalpage <= 11:
  32. begin=0
  33. end=totalpage
  34. else:
  35. if currentPage>5:
  36. begin=currentPage-5
  37. end=currentPage+5
  38. if end > totalpage:
  39. end=totalpage
  40. else:
  41. begin=0
  42. end=11
  43. pager_list=[]
  44. if currentPage<=1:
  45. first="<a href=''>首页</a>"
  46. else:
  47. first="<a href='%s%d'>首页</a>" % (baseurl,1)
  48. pager_list.append(first)
  49.  
  50. if currentPage<=1:
  51. prev="<a href=''>上一页</a>"
  52. else:
  53. prev="<a href='%s%d'>上一页</a>" % (baseurl,currentPage-1)
  54. pager_list.append(prev)
  55.  
  56. for i in range(begin+1,end+1):
  57. if i == currentPage:
  58. temp="<a href='%s%d' class='selected'>%d</a>" % (baseurl,i,i)
  59. else:
  60. temp="<a href='%s%d'>%d</a>" % (baseurl,i,i)
  61. pager_list.append(temp)
  62. if currentPage>=totalpage:
  63. next="<a href='#'>下一页</a>"
  64. else:
  65. next="<a href='%s%d'>下一页</a>" % (baseurl,currentPage+1)
  66. pager_list.append(next)
  67. if currentPage>=totalpage:
  68. last="<a href=''>末页</a>"
  69. else:
  70. last="<a href='%s%d'>末页</a>" % (baseurl,totalpage)
  71. pager_list.append(last)
  72. result=''.join(pager_list)
  73. return mark_safe(result) #把字符串转成html语言

分页实例

总结,分页时需要做三件事:

  • 创建处理分页数据的类
  • 根据分页数据获取数据
  • 输出分页HTML,即:[上一页][1][2][3][4][5][下一页]

Django 补充models操作,中间件, 缓存,信号,分页的更多相关文章

  1. Django ORM models操作

    title: Django ORM models操作 tags: Django --- Django ORM models操作 Django ORM基本操作 一.数据库的创建及增删改查 1 使用类创建 ...

  2. web框架-(七)Django补充---models进阶操作及modelform操作

    通过之前的课程我们可以对于Django的models进行简单的操作,今天了解下进阶操作和modelform: 1. Models进阶操作 1.1 字段操作 AutoField(Field) - int ...

  3. python自动化开发-[第二十一天]-form验证,中间件,缓存,信号,admin后台

    今日概要: 1.form表单进阶 2.中间件 3.缓存 4.信号 5.admin后台 上节课回顾 FBV,CBV 序列化 - Django内置 - json.dumps(xxx,cls=) Form验 ...

  4. Django之Models操作

    一.字段 AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bigint自增列,必须填入参数 pr ...

  5. Django的models操作

    一.先看单表操作 增 方式1: models.book.objects.create( Book_name = "aaa", Book_info = "bbb" ...

  6. 不在框架中,利用Django的models操作

    import os import sys import django sys.path.apprnd(r'路径') os.chdir(r'路径') os.environ.setdefault('DJA ...

  7. python运维开发(二十)----models操作、中间件、缓存、信号、分页

    内容目录 select Form标签数据库操作 models操作F/Q models多对多表操作 Django中间件 缓存 信号 分页 select Form标签补充 在上一节中我们可以知道Form标 ...

  8. Django数据操作F和Q、model多对多操作、Django中间件、信号、读数据库里的数据实现分页

    models.tb.objects.all().using('default'),根据using来指定在哪个库里查询,default是settings中配置的数据库的连接名称. 外话:django中引 ...

  9. WEB框架Django之中间件/缓存/CBV/信号

    一Djano的中间件 1 中间件的概念 中间件顾名思义,是介于request与respose处理之间的一道处理过程,相对比较轻量级,并且全局上改变django的输入与输出.因为改变是全局, 所有需要谨 ...

随机推荐

  1. JAVA自定义注解 ------ Annotation

    日常开发工作中,合理的使用注解,可以简化代码编写以及使代码结构更加简单,下面记录下,JAVA自定义注解的开发过程. 定义注解声明类. 编写注解处理器(主要起作用部分). 使用注解. 相关知识点介绍, ...

  2. linux内核的oops

    什么是Oops?从语言学的角度说,Oops应该是一个拟声词.当出了点小事故,或者做了比较尴尬的事之后,你可以说"Oops",翻译成中国话就叫做“哎呦”.“哎呦,对不起,对不起,我真 ...

  3. 【转】windows下python开发环境搭建

    1 -- 安装python的前期准备 Python开发有众多工具,又以Eclipse+Pydev最为常见.Eclipse平台对开发同学来讲,肯定是如雷贯耳,自不用废话.而PyDev是Eclipse平台 ...

  4. [PHP开发必备] -- 小巧强悍的MYSQL-Front中文版使用教程,附最新版下载地址

    PHP开发已经各位工程师轻车熟路的事情,MySQL也是经常都要用的产品,能有一个简单而又强大的管理工具,那可是咱们PHP开发工程师的福气. 下面浪风小园子就为大家介绍下来自国外小巧的MySQL管理工具 ...

  5. 【问题】CentOS6.5系统"libc.so.6: version 'GLIBC_2.15' not found"解决方法

    出现"libc.so.6: version 'GLIBC_2.15' not found"问题,是由于glibc版本过低,升级glibc即可. 由于CentOS系统RPM源目前gl ...

  6. VS+mysql+EF搭建

    2016年7月6日更新: vs2010只需要安装mysql的.net connector就可以 vs2012, vs2015都需要安装.net connector + ODBC connector才行 ...

  7. [转]Excel关闭进程

    原文地址:http://www.cnblogs.com/feishu/archive/2010/05/08/1730797.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ...

  8. python正则表达式练习

    正则表达式修饰符 - 可选标志 正则表达式可以包含一些可选标志修饰符来控制匹配的模式.修饰符被指定为一个可选的标志.多个标志可以通过按位 OR(|) 它们来指定.如 re.I | re.M 被设置成 ...

  9. 【BZOJ1912】[Apio2010]patrol 巡逻 树形DP

    [BZOJ1912][Apio2010]patrol 巡逻 Description Input 第一行包含两个整数 n, K(1 ≤ K ≤ 2).接下来 n – 1行,每行两个整数 a, b, 表示 ...

  10. D - Find a way

    D - Find a way Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Desc ...