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

  1. 配置项中是否有
    这一项配置与authenticate有关,没有配置会找不到user

    AUTH_USER_MODEL = 'system.User'
    
  2. INSTALLED_APP 中 添加 ‘system'。

存入emoji表情 mysql 报错1366 incorrect string value

    1. 在django setting中配置DATABASE项 OPTIONS': {
      'charset': 'utf8mb4'
      }
    1. 检查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
  • 数据迁移
    • python manage.py loaddata filename.json

定义索引的两种方式

  1. 在字段后面直接dbindex=True

  2. 定义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连接的寿命保持到该次请求结束。

短链接

长连接

短链接弊端:

  1. 每个请求都将重复连接数据库
  2. 处理高并发请求给服务带来巨大压力
  3. 无法承载更高并发的服务
  • 避免负优化
    • 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''方法里不能存变量。
所以转义要么已知字节流内容,要么是不包含反斜杠的变量!

未完待续。。。

posted @ 2019-07-06 18:12  Jimmyhe  阅读(236)  评论(0)    收藏  举报