django日常总结
django上传文件返回413 payload too large
原因:django自带服务器只支持1-3mb大小的请求体。
解决:在settings文件中添加此项参数,改变最大上传大小
DATA_UPLOAD_MAX_MEMORY_SIZE = 1010241024
用python统计代码行数的脚本
import os
#定义代码所在的目录
base_path = '/Users/hjj/mt/yunhe_sys2'
#在指定目录下统计所有的py文件,以列表形式返回
def collect_files(dir):
filelist = []
for parent,dirnames,filenames in os.walk(dir):
for filename in filenames:
if filename.endswith('.py'):
#将文件名和目录名拼成绝对路径,添加到列表里
filelist.append(os.path.join(parent,filename))
return filelist
#计算单个文件内的代码行数
def calc_linenum(file):
with open(file) as fp:
content_list = fp.readlines()
code_num = 0 #当前文件代码行数计数变量
blank_num = 0 #当前文件空行数计数变量
annotate_num =0 #当前文件注释行数计数变量
for content in content_list:
content = content.strip()
# 统计空行
if content == '':
blank_num += 1
# 统计注释行
elif content.startswith('#'):
annotate_num += 1
# 统计代码行
else:
code_num += 1
# 返回代码行数,空行数,注释行数
return code_num,blank_num,annotate_num
if __name__ == '__main__':
files = collect_files(base_path)
total_code_num = 0 #统计文件代码行数计数变量
total_blank_num = 0 #统计文件空行数计数变量
total_annotate_num = 0 #统计文件注释行数计数变量
for f in files:
code_num, blank_num, annotate_num = calc_linenum(f)
total_code_num += code_num
total_blank_num += blank_num
total_annotate_num += annotate_num
print(u'代码总行数为: %s' % total_code_num)
print(u'空行总行数为: %s' % total_blank_num)
print(u'注释行总行数为: %s' % total_annotate_num)
将django orm模型中的datetimefield转为datefield
record_obj = VisitRecord.objects.annotate(date_only=Cast('visit_datetime', DateField())).get(
visitor_id=user.uid, date_only=now_date,deleted='0')
AUTH_USER_MODEL refers to model 'system.User' that has not been installed
-
配置项中是否有
这一项配置与authenticate有关,没有配置会找不到userAUTH_USER_MODEL = 'system.User'
-
INSTALLED_APP 中 添加 ‘system'。
存入emoji表情 mysql 报错1366 incorrect string value
-
- 在django setting中配置DATABASE项 OPTIONS': {
'charset': 'utf8mb4'
}
- 在django setting中配置DATABASE项 OPTIONS': {
-
- 检查mysql 的my.cnf中字符集是否是utf8mb4
django RestfulAPI 返回图片
-
第一种形式,在settings.py中设置static_url和staticfiles_dirs,当url中访问static_url指定的参数时,就会访问staticfiles_dirs中的文件,也就是可以通过一个url相对路径,访问到服务器中的绝对路径。
-
比如 static_url = /uploads/
staticfiles_dirs = [os.path.join(base_dir, 'static')],只要访问的url路径是/uploads/,就可以从base_dirs.static中去遍历对应的静态文件,返回给前端的路径为/uploads/xxxx.jpg,这样就能展示了
-
-
第二种形式,利用JsonResponse,data可以返回文件的描述符,比如:
with open (xxxx,'rb') as f: res = Httpresponse(data=f,Content_type='image/jpg')
如果不加content_type,前端访问道德结果是乱码。
-
第三种,利用FileResponse(data=f,content_type='image/jpg'),也可以返回图片信息。
-
在django.http中可以引入JsonResponse,FileResponse,django.shortcuts可以引入日常三剑客
-
使用 python manage.py dbshell可以直接连接到数据库,执行sql语句
django有状态服务
-
什么是有状态
- 上下文关系,两个来自相同的客户端的请求,是否有联系
-
HTTP协议中的状态
- 基于cookie和session
-
小程序中的状态
- 不同于HTTP网络连接,小程序和django不是有状态的,而是要通过微信服务器建立联系。
- 用小程序的storage来存储cookie,经过微信服务器的转发,到达django服务后台
- 小程序通过访问django服务器获取cookies,再将取到的cookies放入storage,访问django服务器,django会自动匹配cookie对应的session,可以取出对应的数据
-
有状态的定制页
- 保存用户的关心分类,加入到session中,下次访问可以取出所关心的分类,筛选数据。
-
JsonResponse中safe=false的作用
def __init__(self, data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None, **kwargs): if safe and not isinstance(data, dict): raise TypeError( 'In order to allow non-dict objects to be serialized set the ' 'safe parameter to False.' )
可以看到JsonResponse中的源码作用是为了让data,可以不用是一个字典格式。
django数据库备份
需求:将sqlite中的表同步到mysql
- 导出数据
python manage.py dumpdata appname > filename(json)
- 表结构同步
- 创建mysql数据库并更新配置
- 在setting中配置DATABASES
- 创建slave数据库
- 将配置好的databases中的default换成slave放到原DATABASES中
- 创建数据库表
- python manage.py migrate --run-syncdb --database slave
- 创建mysql数据库并更新配置
- 数据迁移
- python manage.py loaddata filename.json
定义索引的两种方式
-
在字段后面直接dbindex=True
-
定义Meta类
class Meta: indexs = [ models.Index(fields=['field']) ]
- 数据库字符串拼接
from django.db.models import Value
from django.db.models.functions import Concat
def concat_function():
user = User.objects.filter(open_id='test_open_id').annotate(
screename = Concat(
Value('open_id='),
'open_id',
Value(','),
Value('nickname='),
'nickname'
)
)[0]
-
取字符串的长度
from django.db.models.functions import Length
annotate(open_id_length = Length('open_id'))[0]
-
取当前时间
from django.db.models.functions import Now def now_function(): app = App.objects.filter(date_lte=Now())
-
Trunc时间截断函数
from django.db.models.function import Trunc def trunc_function(): app_per_day = App.objects.annotate(publish_day=Trunc('publish_day','day')).values('publish_day').annotate(num=Count('appid'))
- 查看数据库变更的sql语句
python manage.py sqlmigrate appname 具体的生成文件序号
-
打印orm执行的sql语句
users = User.objects.all( )
print(users.query) 可以显示sql语句
-
查看生成文件
python manage.py showmigrations appname
如果执行了migrate 前面就会加上x
迁移文件详解
- dependencies 字段 依赖于哪些文件迁移
- appname
- 具体文件序号
- operations字段
- 对那些表做了什么操作
懒加载和预加载
-
什么是懒加载
- 模型存在外键和多对多关系
- 不检索关联对象的数据
- 调用关联对象会再次查询数据库
-
django orm中的数据加载
- 比如一个应用中有user和menu两个多对多字段,查询user的字段时他不会关联所关联的外键对象,也就是不会查询menu。所以要查询menu的话,先要查user,再根据user查menu。
-
预加载的方法
- 预加载单个关联对象 —— select_related
- 预加载多个关联对象 —— prefetch_related # 参数是所关联的对象
- 比如 users = User.object.prefetch_related('menu')
- 第一次会查询用户表,第二次查询app表
数据库连接的处理逻辑
- 使用CONN_MAX_AGE配置限制DB连接寿命,默认为0,表示每个DB连接的寿命保持到该次请求结束。
短链接
长连接
短链接弊端:
- 每个请求都将重复连接数据库
- 处理高并发请求给服务带来巨大压力
- 无法承载更高并发的服务
- 避免负优化
- django部署线程数:n
- 最大连接数:m
- n < m 否则其他服务无法连接数据库
- 不必要的检索
- QuerySet使用values, value_list() 函数返回python结构容器
- 查询长度应该用count函数,而不是len
- 查询是否为空使用exists(),而不是if
django 中的Queryset对象如果执行了update,这个对象就不存在了,比如
queryset = Book.objects.filter(xxxxx)
queryset.update(id=xxxxx)
print(queryset) --> None
字符串转字节
如果字符串里有反斜杠,调用bytes方法会产生转义符号,无法避免。注意b''方法里不能存变量。
所以转义要么已知字节流内容,要么是不包含反斜杠的变量!
未完待续。。。