笔记

<script>

alert("hello")

</script>

def _get_server(self, key):
if isinstance(key, tuple):
serverhash, key = key
else:
serverhash = serverHashFunction(key)

if not self.buckets:
return None, None

for i in range(Client._SERVER_RETRIES):
server = self.buckets[serverhash % len(self.buckets)]
if server.connect():
# print("(using server %s)" % server,)
return server, key
#连接不上就换人,打算损失一部分缓存数据
serverhash = str(serverhash) + str(i)
if isinstance(serverhash, six.text_type):
serverhash = serverhash.encode('ascii')
serverhash = serverHashFunction(serverhash)
return None, None


def cmemcache_hash(key):
return (((binascii.crc32(key) & 0xffffffff) >> 16) & 0x7fff) or 1
serverHashFunction = cmemcache_hash


https://github.com/linsomniac/python-memcached/blob/master/memcache.py

https://github.com/lericson/pylibmc


参数配置


CACHE_MIDDLEWARE_ALIAS 缓存别名(默认:default)
CACHE_MIDDLEWARE_SECONDS – 每个页面的缓存时间(s)(默认:600s)
CACHE_MIDDLEWARE_KEY_PREFIX – 如果缓存被多个使用相同 Django 安装的站点共享,配置此参数为站点名称或其它能代表站点的唯一字符串,以防止key冲突。如果不在意,可为空。

//对中间件进行说明

FetchFromCacheMiddleware

会缓存 GET 和 HEAD 200 状态的 responses,而且这些 request 和 response 的headers 是允许的;
同一个 URL request, 不同查询参数,他的 Responses 会被作为不同 page 分别缓存;
这个中间件期待用具有相同 response headers 的 GET request 的response 进行响应,这样它就可以用缓存的 GET response 响应 HEAD request。

UpdateCacheMiddleware

此中间件会在每个 HttpResponse 中自动设置一些 headers:
对于一个页面的新版本(未被缓存过)的请求,设置 Last-Modified header 为当前日期/时间;

设置 Expires header 为当前时期/时间 + 定义的CACHE_MIDDLEWARE_SECONDS

设置 Cache-Control header 的 max age 指令为 CACHE_MIDDLEWARE_SECONDS (max age是指缓存的内容将在多少秒后失效)

特殊情况:

如果 view 设置了自己的 cache 过期时间 (如:设置了 Cache-Control 的 max-age), 则页面的缓存过期时间会以 view 的过期时间为准。

http://www.maiziedu.com/wiki/django/lowlevel/
http://www.maiziedu.com/wiki/django/backend/

http://www.hi-roy.com/2015/08/13/python-memcached%E6%BA%90%E7%A0%81%E5%B0%8F%E7%AA%A5/

http://xdxd.love/2016/01/14/CRC32%E7%AE%97%E6%B3%95%E8%AF%A6%E8%A7%A3%E5%92%8C%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF/

logging.getLogger(__name__).

That’s because in a module, __name__ is the module’s name in the Python package namespace.

package.filename

# 何时求值
QuerySet 本身是可迭代的,返回的iter
迭代 切片 序列化 repr() len() list() bool()


# pickle存QuerySet对象,会先求值
dump

blogs = Blog.objects.all()
pickle.dump(blogs, fd, True)

load
blogs = pickle.load(fd)
print blogs[0].name # not hit db

import cPickle as pickle

pickle.dump(obj, file[, protocol])
pickle.load(file)

dumps(obj, protocol=None)
loads(str)

更快更节省存储空间。
protocol=True则以高压缩的二进制格式保存持久化后的对象,否则以ASCII格式保存。


Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline='Hello')
用SQL 语句,它等同于:

SELECT ...
WHERE NOT pub_date > '2005-1-3'
AND NOT headline = 'Hello'


感觉不如Q语句那样直白。

from django.db.models import Q
b = Author.objects.exclude(Q(name__contains='a') | Q(email__contains='5'))


# annotate
例如,如果你正在操作一个Blog 列表,你可能想知道每个Blog 有多少Entry:

>>> from django.db.models import Count
>>> q = Blog.objects.annotate(Count('entry'))
# The name of the first blog
>>> q[0].name
'Blogasaurus'
# The number of entries on the first blog
>>> q[0].entry__count
42
Blog 模型本身没有定义entry__count 属性,但是通过使用一个关键字参数来指定聚合函数,你可以控制Annotation 的名称:

>>> q = Blog.objects.annotate(number_of_entries=Count('entry'))
# The number of entries on the first blog, using the name provided
>>> q[0].number_of_entries
42


# values values_list 取出特定列,不转为QuerySet
values(*field)
values_list(*field)
values_list(*field, flat=True) 仅限单字段

外键将会返回 字段_id 作为字典key
多对多 等待测试

# only defer
only(*field) #仅返回特定列(会自动包括id),转为QuerySet
defer(*field) #排除


# order_by
order_by('name')
order_by('-name')

#dates(field, kind, order='ASC')
返回DateQuerySet - QuerySet,其计算结果为datetime.date对象列表,表示特定种类的所有可用日期QuerySet。

field应为模型的DateField的名称。 kind应为"year"、"month"或"day"。隐式的是升序排序。若要随机排序,请使用"?",像这样:

"year" 返回对应该field的所有不同年份值的list。
“month”返回字段的所有不同年/月值的列表。
“day”返回字段的所有不同年/月/日值的列表。

等待测试 用于blog的日期分类


Entry.objects.dates('pub_date', 'year') # 返回entry中出版日期不同年的文章。

文章选择列表可以搞出来不同月份发表的分类,然后根据月份去查找相应的文章。


#select_related
filter() 和select_related() 链的顺序不重要。下面的查询集是等同的:

Entry.objects.filter(pub_date__gt=timezone.now()).select_related('blog')
Entry.objects.select_related('blog').filter(pub_date__gt=timezone.now())


select_related('blog') 必须是外键字段或onetoone


from django.db import models

class City(models.Model):
# ...
pass

class Person(models.Model):
# ...
hometown = models.ForeignKey(City)

class Book(models.Model):
# ...
author = models.ForeignKey(Person)

外键可以一直传下去
Book.objects.select_related('author__hometown')


默认的Book.objects.select_related()不加参数会自动关联所有的外键字段。


过滤外键字段的时候需要__
e = Entry.objects.select_related().only('blog__name', 'headline').get(pk=1)

e.pub_date # hit db
e.blog.tagline # hit db

select_related('foo', 'bar')
等同于select_related('foo').select_related('bar')

#prefetch进行两步sql操作。
1:主表中数据拉出来
2:关系表与中间表join,where id in 主表id


prefetch后会关联填充在QuerySets中,后续对关联字段的读取不会hit db,而是在QuerySets中获取。

但是只能是all(),后续的改变如pizza.toppings.filter()将创建新的query,hit db而不会用QuerySets。


过滤主表
es = Entry.objects.prefetch_related('authors').filter(headline__contains='l')


{u'time': u'0.001', u'sql': u"SELECT `blog_entry`.`id`, `blog_entry`.`blog_id`, `blog_entry`.`headline`, `blog_entry`.`body_text`, `blog_entry`.`pub_date`, `blog_entry`.`mod_date`, `blog_entry`.`n_comments`, `blog_entry`.`n_pingbacks`, `blog_entry`.`rating` FROM `blog_entry` WHERE `blog_entry`.`headline` LIKE BINARY '%l%'"}

{u'time': u'0.001', u'sql': u'SELECT (`blog_entry_authors`.`entry_id`) AS `_prefetch_related_val_entry_id`, `blog_author`.`id`, `blog_author`.`name`, `blog_author`.`email` FROM `blog_author` INNER JOIN `blog_entry_authors` ON (`blog_author`.`id` = `blog_entry_authors`.`author_id`) WHERE `blog_entry_authors`.`entry_id` IN (1, 2)'}

过滤关联表
尝试在pre_related的时候filter,发现sql语句变了。
es = Entry.objects.prefetch_related('authors').filter(authors__name__contains='N')

相应的sql如下:
{u'time': u'0.000', u'sql': u"SELECT `blog_entry`.`id`, `blog_entry`.`blog_id`, `blog_entry`.`headline`, `blog_entry`.`body_text`, `blog_entry`.`pub_date`, `blog_entry`.`mod_date`, `blog_entry`.`n_comments`, `blog_entry`.`n_pingbacks`, `blog_entry`.`rating` FROM `blog_entry` INNER JOIN `blog_entry_authors` ON (`blog_entry`.`id` = `blog_entry_authors`.`entry_id`) INNER JOIN `blog_author` ON (`blog_entry_authors`.`author_id` = `blog_author`.`id`) WHERE `blog_author`.`name` LIKE BINARY '%N%'"}

不知道为啥直接粗暴的join了???


如同select_related一样,也是可以链式关联下去的 __ 连接字段即可。

#批量插入
bulk_create(objs, batch_size=None)
此方法以有效的方式(通常只有1个查询,无论有多少对象)将提供的对象列表插入到数据库中:

>>> Entry.objects.bulk_create([
... Entry(headline="Django 1.0 Released"),
... Entry(headline="Django 1.1 Announced"),
... Entry(headline="Breaking: Django is awesome")
... ])
这有一些注意事项:

将不会调用模型的save()方法,并且不会发送pre_save和post_save信号。

# count

Entry.objects.count()

count()在后台执行SELECT COUNT(*) count(),很快的!

#iterator
a = Author.objects.all()
for i in a:
print i # hit db
for i in a:
print i # not hit db
for i in a.iterator():
print i # hit db
connection.queries

iterator不会缓存结果,而是直接数据库一点点取。对于返回大量数据性能较好。

#日期字段的快捷方式latest earliest

Entry.objects.latest('pub_date')
没有啥技巧,select按照日期字段order_by而已。

#update
update()方法立即应用,对更新的QuerySet的唯一限制是它只能更新模型主表中的列,而不是相关模型。


Author.objects.update(email='666@qq.com')
for i in Author.objects.all():
print i.name, i.email

一旦分片或者求值后就不能update的了
只能python方式修改
e = Entry.objects.get(id=10)
e.comments_on = False
e.save()

#delete
默认情况下,Django的ForeignKey模拟SQL约束ON DELETE CASCADE字,任何具有指向要删除的对象的外键的对象将与它们一起被删除。

模拟,其实是一步步删除,先删除关联,在删除被关联表。


同样,不能对分片或求值的进行delete操作。

# in

Entry.objects.filter(id__in=[1, 3, 4])
SQL等效:
SELECT ... WHERE id IN (1, 3, 4);


# range
范围测试(包含于之中)。
import datetime
start_date = datetime.date(2005, 1, 1)
end_date = datetime.date(2005, 3, 31)
Entry.objects.filter(pub_date__range=(start_date, end_date))


search
一个Boolean类型的全文搜索,以全文搜索的优势。这个很像 contains ,但是由于全文索引的优势,以使它更显著的快。
Entry.objects.filter(headline__search="+Django -jazz Python")


#其他lookup
gt gte le lte startswith istartswith endswith iendswith

year month day week_day hour minute second

原文地址:https://www.cnblogs.com/newpython/p/8329339.html