模型管理类
用于控制admin后台页面的展示和操作(直接通过Django提供的图形界面来在后台操作数据库),在应用下的admin.py及models.py中操作。
注册模型管理类:在应用下的admin.py中定义模型管理类并注册,有两种方式:
from django.contrib import admin
from appname.models import AreaInfo
class AreaAdmin(admin.ModelAdmin):
pass
admin.site.register(AreaInfo, AreaAdmin) # 定义模型管理类后注册
@admin.register(AreaAdmin) # 使用装饰器方法注册
class AreaAdmin(admin.ModelAdmin):
pass
修改列表页,即显示信息页
①修改每页显示条目数,模型管理类中添加list_per_page = 10;
②修改操作选项的位置,模型管理类中添加actions_on_top/bottom = True/False;
③将方法作为列并指定方法可排序并指定列标题,模型管理类中添加list_display = [‘字段名’…, ‘方法名’],在模型类(models.py下)中添加方法(其返回值即页面中列上的显示值)并为方法添加属性
方法名.admin_order_field = '字段名'
方法名.short_description = 'xxx'
则可以使方法列按照指定字段排序并指定列标题;
④对于已有的字段指定列标题,在模型类中定义字段时添加参数verbose_name=‘标题’;
⑤访问某字段关联对象,可以定义方法,并在方法中完成查询和输出并返回,在页面上显示;
⑥在右侧显示过滤栏,在模型管理类中添加list_filter = [‘字段名’…];
⑦在上方显示搜索框,在模型管理类中添加search_fields = [‘字段名’],支持模糊查询,列表中添加多个字段表示可以对多个字段进行查询。
注:区分模型类(models)、模型管理类(Admin)、模型管理器类(Manager)。
修改编辑页
①在模型管理类中添加fields = [‘字段1’, ‘字段2’],默认将所有字段按顺序显示,若更改此选项,则会变更字段显示顺序和显示数量;
②对编辑页的字段进行分组显示,如图;
③在母表的对象编辑中添加子表的关联对象,admin.py中新建类,TabularInline表示以表格形式显示,model为子表名在原模型类中添加inlines = [BookStackedInline]
Django提供了功能强大的后台管理页面,此处提出部分常用方法进行举例,详参2.2文档,了解即可,在生产环境中并不常用。
Django中设置上传文件和图片
设置让用户或管理员上传图片,与在配置模板时使用的静态文件的存放位置不同,且在数据库中的存储方式为URL(存储路径)。
①在项目下static目录下新建目录media/应用名,上传的图片文件就保存在此处;
②在应用的models.py文件下新建模型类,或在原有模型类中新建字段pic = models.ImageField(upload_to=‘项目名/’)其中ImageField是FileField的子类(其会自动对上传的文件进行校验,确认是图片文件),upload_to是相对于设置的上传文件路径(在setting中设置)的子目录,而字段本身是一个实例非字符串,显示为路径;
③在settings中设置MEDIA_ROOT=os.path.join(BASE_DIR, ‘static/media’)其与模型类中的路径组合成为上传文件的保存路径;
④在admin中注册PicTest类,即可在后台管理页面上传图片(注意在后台管理页面删除时只是删除了数据库中的记录,并没有删除上传的已保存在media下的文件本身);
⑤若要让用户自定义上传图片,则需要在自定义页面中设置上传表单
<form method="post" action="/pic_handle/" enctype="multipart/form-data">
其enctype属性固定;
⑥request.FILES.get(‘pic’)可以得到提交的对象(request.FILES类似于字典),且根据上传文件的大小,其分为两个处理类django.core.files.uploadhandler.MemoryFileUploadHandler(内存中)
/TemporaryFileUploadHandler(临时文件中),2.5M为限制大小;
⑦上述对象支持一些方法:
使pic = request.FILES.get(‘pic’),则pic.name为上传文件的名称/pic.size上传文件的大小/pic.chunks()是一个类似于redalines()的生成器,最长用于遍历然后写入/pic.read()一次性读取内容,但注意若上传的文件过大,可能会撑爆内存;
⑧设置文件路径并使用’wb’方式打开,如图;
⑨写入,并在数据库中保存路径,注意数据库中保存的路径是从(项目/static/media)计起,即MEDIA_ROOT。
补充内容
1、Django模型类中,choices可以限定取值范围,在定义字段时写入选项choices=xxx_choices,其中xxx_choices为一个二维的元组,其中可以有多个选项,第一个元素表示存在数据库内真实的值,第二个表示页面上显示的具体内容,一般将xxx_choices=((‘a’, ‘1’), (‘b’, ‘2’), (‘c’, ‘3’))直接定义在模型类中,可使用b.get_xxx_display()方法获取相应的具体内容,其中b为模型类的实例,xxx为字段名。
2、Django中自带了用户注册管理系统,在使用前必须先在setting中使用AUTH_USER_MODEL指定django用户认证系统使用的模型类,如果重新设定了用户模型类,则需指定为重设的自定义的用户模型类,若不指定则会使用Django默认的用户模型类;
使用User.objects.create_user(username, email, passwd)指定新用户,默认激活;
使用实例.set_password(‘new’)修改密码;
使用authenticate(username=x, password=y)来验证用户(在django2.x版本,账号未激活即is_active为0则直接返回None),若验证有效则返回User实例对象,若无效则返回None;
使用login(request, user)来对authenticate返回值记录其登录状态,使用login_required对视图函数(若为视图类则不能直接使用,可以在urls.py中装饰as_view函数)进行装饰,可验证其登录状态(若有则正常执行视图,若无则重定向并传递next参数保存重定向之前的页面url);
使用LoginRequiredMixin,可将方法全部封装(写在视图类继承的最左边,是因为要使用此类而非View的as_view()方法);
Django的认证系统会给每一个请求添加request.user属性(且这个user属性会作为参数传递给Django模板),其是User模型类或另外一个内置的AnonymousUser类的实例,可以用user.is_authenticated来区分两者。
3、类视图:用于同一个网页以不同方法提交时分别处理,其继承自django.views中的View类,并在类中def get()/post()等严格以方法名小写为名的类方法,在urls中调用自定义视图类中的as_view()方法,其会自动根据request.method的不同分发给不同的类方法。
4、加密:使用模块
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
此类的实例可以指定加密密钥和有效时间(秒),
生成类实例serializer = Serializer(settings.SECRET_KEY, 3600),
加密token=serializer.dumps(userid),
解密res=serializer.loads(token),
当有效时间超出后,加密生成的token无法进行解密,报错SignatureExpired,其位于itsdangerous模块中。
5、使用Django内置模块发送邮件:配置163邮箱,在setting中添加配置项,在视图中使用内置函数(了解内容,详参Django文档)。
6、使用celery异步发送邮件:发送邮件过程为Django→smtp服务器→目的邮箱 其中Django的send_mail函数是阻塞的,若存在网络延迟,则在用户端会卡在登陆界面(影响用户体验),因此使用celery来完成异步发送邮件。
celery:是一个基于消息传递的分布式任务队列,其工作原理如图所示,三者可以在同一台电脑上也可以在不同电脑上(broker和worker可以有多个),在worker主机上使用celery -A app名 worker -l info
可以开启worker(开启前要先进行django环境的初始化),其会自动检测并连接broker;
配置方式略。
7、使用redis作为django缓存及session存储:安装django-redis(只支持pip3),配置缓存及session如图所示。
8、Django中的缓存机制:
①Memcached,与redis类似都是内存型数据库(可用作Django的缓存)
②数据库缓存,可设置redis/mysql等
③文件系统缓存,即生成单独的文件保存在磁盘中
④本地内存缓存,即直接保存在内存中
⑤虚拟缓存,用于开发模式;
Django默认支持的三种缓存级别:
①站点缓存(缓存整个网站)
②单个视图缓存(对某个视图函数的输出进行缓存)
③模板片段缓存(即一类模板标签,作为模板变量来渲染模板,替换其中的部分内容);
自定义Django中缓存内容:使用django.core.cache中的cache.set(key, value, time),cache.get(key)方法设置并访问缓存,这里使用缓存只是将从数据库查询到的内容进行统一存储,减少访问数据库的次数,而不生成整个html内容,即相当于将查到的内容作为变量存储起来并在访问时进行模板渲染和替换。
缓存时间的重要性:防止由于某种原因缓存一直存在无法更新,只会在一定时间内显示过期的页面。
9、Django中设置生成静态页面:在首页信息被后台admin改动时重新生成静态页面(直接改动数据库时不影响),对已生成的html文件进行重写而不生成多个,在admin中注册模型类时,其每个模型类的管理类中都有save_model(),delete_model()方法,其分别在新增,修改/删除某模型类对应表中文件时使用,重写这两个方法,在此中添加对celery worker的调用,并且应用到所有注册的模型类中。
10、使用搜索引擎框架:
①搜索引擎:对信息(可以是互联网/数据库/文档等内容)进行分析整理,建立关键词索引;
②全文检索框架:搜索引擎有多种,且其中有分词算法/噪音消除/排名算法等复杂内容,将其封装,简便使用的框架称为全文检索框架,这里使用haystack;
③正向索引和倒排索引:对所有的文件/网页进行全盘扫描并分词,生成一个{{文件1:key1,key2},{文件2:key1,key3}…}的索引称为正向索引(依然需要检索大量文件,浪费资源),将生成的索引整合为{{key1:文件1[3],文件2[2]}{key2:文件1[1],文件3[3]}…}的索引称为倒排索引,索引中记录关键词出现的位置(包括出自哪个文件或网页)和频率,倒排索引可直接应用于排名;
④具体操作方法参课件,固定的有:配置/templates目录下search及其索引字段的格式/模板中使用搜索的表单name/搜索结束后传递到模板的内容(query:搜索关键字,page:自动分页后当前页内容,paginator:分页的paginator对象)。
11、Django中使用数据库事务
①from django.db import transaction,使用@transaction.atomic对需要的视图函数进行装饰,可以直接使用在类中的post/ get函数上,然后可以在该视图函数中使用自定义事务功能;
②在函数中设置保存点save_id=transaction.savepoint(),可以在需要的位置使用transaction.savepoint_rollback(save_id)进行回滚;
③一般将整个事务放置于try中。
注:遇到的一些问题
①在django中使用redis存储session,除session_engine以外的配置项不起作用,session可以存储在redis数据库中,但只能存储在默认的数据库0中,且’session’前缀不添加,即后续配置项并没有识别。
解决:在更新django版本后,session的设置使用下述方法进行配置,区别于老版本。
②
安装kombu==4.2.0,因为kombu版本低,可能报错找不到kombu.match文件,修改kombu.transport.redis.py文件,将版本号注释。
③在Django中调用celery tasks时,导入task函数放置于.delay()上方,放置在文档最上方可能会报错。
④celery中worker报错,可能因为版本过高,使用redis2.10.6
⑤解决authenticate()方法会默认检测用户的活跃状态,is_active,在settings.py中添加以下配置
AUTHENTICATION_BACKENDS = ['django.contrib.auth.backends.AllowAllUsersModelBackend']
# 不会检测用户的活跃状态
⑥如图所示的报错,其报错于render和url匹配,但实际问题出现于模板中的url反向解析中的错误(反向解析的第二个参数输入拼写错误),即注意若使用反向解析,则链接生成时要调用view函数,若出问题可能不会在模板中报错,注意报错信息中的信息。
⑦append_slash报错即需要添加斜杠,在模板中post提交的链接;
⑧403forbidden可能是csrf报错,在使用表单和ajax时都需要{% csrf_token %},注意ajax需要设置获取input的csrfmiddlewaretoken值并传入比较;
⑨注意ajax发起的请求都在后台(包括跳转,Loginrequiredmixin类的作用是跳转到登录页面,因此在ajax请求时不能使用),因此虽然跳转请求发起,但在浏览器中看不到跳转的效果,只要不跳转页面和局部更新的就使用ajax请求,且ajax默认发起的请求都是异步的,不会等待回调函数执行,若需要等待则将ajax设置为同步,可在前端页面中设置$.ajaxSettings.async=false,此设置为全局生效,因此一般在指定的请求结束后再变更回去。