本文为个人学习前后端分离开发 后端所学到的部分技术,内容中没有涉及到模板的具体使用,更多的是对视图views、路由urls和数据库的操作以及部分调整admin后台的操作。学习这些内容可以为开发api打好铺垫
1.1.1. 1.1 创建
• mkvirtualenv 环境名 -p python3 • python -m venv 环境名
1.1.2. 1.2 激活环境
• win: 环境名\Scripts\activate • linux: source 环境名/bin/activate
1.1.3. 1.3停止虚拟环境
• deactivate
1.1.4. 1.4 删除虚拟环境
• rmvirtualenv
1.1.5. 1.5 进入虚拟环境
• workon
1.1.6. 1.6 pip的部分操作
• pip install 安装依赖包
• pip uninstall 卸载依赖包
• pip list 查看已安装的依赖包
• pip freeze 冻结当前环境的依赖包
1.2.1. 1.1 安装Django
• pip install django==版本
1.2.2. 1.2 创建Django项目
• django-admin startproject 项目名
.
1.2.3. 1.3 跑Django项目
• python manage.py runserver
1.2.4. 1.4 创建子应用
• python manage.py startapp 子应用
2.1. 2.1 定义路由的方式
2.1.1. 1. 总 • 所有的路由都定义在 项目的urls中 • url(r’^users/index/$’,views.index)
2.1.2. 2. 总 + 子
• 执行顺序
•
在settings中的ROOT_URLCONF指定项目urls
• 项目的urls指定了子项目的urls
• 子项目的urls指向具体视图
• 路由
• 总路由
• url(r’^users’,include(‘users.urls’))
• 子路由
• url(r’^index/$’, views.index)
2.1.3. 3. 子
• 总路由
•
url(r’^’, include(‘users.urls’))
• 子路由
• url(r’^users/index/$’,view.index)
2.2. 2.2 静态文件访问
2.2.1. 开发过程中,在settings文件中添加STATICFILES_DIRS • # 配置静态文件加载存储目录
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static_files'),
os.path.join(BASE_DIR, 'static_files/img'),
]
2.2.2. 生产过程中
如果将来将项目部署上线后,django服务器不再提供对静态文件访问的支持,因为Django服务器是动态业务逻辑服务器,不擅长静态文件处理
需要将静态文件放到 nginx
3.1 请求Request
3.1.1. 提取URL路径参数
• 使用正则表达式在URL中获取请求参数,Django会将提取的参数直接传递到视图的传入参数中,加形参。 •
url(r’[a-z]+/\d{4}/KaTeX parse error: Undefined control sequence: \d at position 79: …-z]+)/(?P\̲d̲{4})/ ’, views.tianqi),
3.1.2. 提取GET属性的数据 Django中的QueryDict对象,即是 request.GET属性
• 与字典不同,QueryDIct对象用来处理同一个键带有多个值的情况 • get方法,有多个值的情况获取最后一个值
• querydict.get(‘键’) • getlist() 方法,值以列表的返回,如果键不存在返回空列表
• querydict.getlist(‘键’)
3.1.3. 提取POST属性的表单数据,request.POST属性,也是一个queryDict对象
• POST属性也是queryDict的对象,同样有get()与geilist()方法
3.1.4. 获取请求体非表单数据, request.body属性 获取的是一个 bytes类型的数据,需要进行转换
• json_str = json_bodys.decode() 方法 将bytes类型的数据转换成 json字符串
• json_dict = json.loads(json_str) 方法 将 json字符串转换成json字典或json列表
• json_str = json.dumps(json_dict) 方法将json字典转换成json字符串
3.1.5. 获取请求头数据request.META属性为字典类型
可通过request.META[‘CONTENT_LENGTH’]直接获取,或者request.META.get(‘HTTP_HOST’) 常见请求头
CONTENT_LENGTH 请求正文的长度(作为字符串)
CONTENT_TYPE 请求正文的MIME类型。
HTTP_ACCEPT 响应的可接受内容类型。
HTTP_ACCEPT_ENCODING - 响应的可接受编码。
HTTP_ACCEPT_LANGUAGE响应的可接受语言。
HTTP_HOST - 客户端发送的HTTP主机头。
HTTP_REFERER - 引用页面(如果有)。
HTTP_USER_AGENT - 客户端的用户代理字符串。
QUERY_STRING - 查询字符串,作为单个(未解析)字符串。
REMOTE_ADDR - 客户端的IP地址。
REMOTE_HOST - 客户端的主机名。
REMOTE_USER Web服务器验证的用户(如果有)。 •
REQUEST_METHOD - 诸如“GET”或“POST”之类的字符串。
SERVER_NAME - 服务器的主机名。
SERVER_PORT - 服务器的端口(作为字符串)。
• 除了上面给出的CONTENT_LENGTH和CONTENT_TYPE之外,请求中的任何HTTP头都将转换为META密钥,方法是将所有字符转换为大写,用下划线替换任何连字符,并在名称中添加HTTP_前缀。因此,例如,名为X-Bender的标头将映射到META密钥HTTP_X_BENDER。
3.1.6. request的其他属性
• method
一个字符串,表示请求使用的HTTP方法,例如 GET或者POST
• user
• 请求的用户对象,例如AnonymousUser
• path
一个字符串,表示请求页面的完整路径,不包括域名和参数部分
• encoding
一个字符串,表示提交数据的编码方式,一般事utf-8 • 如果为NOne,表示为浏览器的米热设置,一般为utf-8
• 这个属性是可写的,可通过修改它来访问表单数据使用的编码,接下来对属性的任何访问将使用新的encoding值
• FILES
类似于字典的对象,包含所有的上传文件
3.2. 3.2 响应response
3.2.1. 在试图函数返回 HTTPRESPONSE()
• return HttpResponse(content=‘hello seven’,
content_type=‘text/html’, status=201)
• 其中contet写的返回的内容,content_type为返回的类型,status为返回的状态码
3.2.2. JsonResponse(dict,safe=True)
• dict处尽量是字典,否则可以会报错,可以指定safe参数为Flase,这样会将数据包成字典进行返回
3.2.3. 重定向 redirect
• 首先在视图函数内导入 redirect
• from django.shortcuts import redirect
• 在视图函数中 写 return redirect("/user/index")
• 假如写入的重定向路径开头没/ 则会在当前路径下直接重定向,假如写了/ 则会在根路径下进行跳转
3.2.4. 反向解析 reverse
• 在子应用的urls中为路由指定name,这种情况会发生,多个子应用如果别名相同的话,可能只解析到一个子应用的路由,因此我们需要在项目的urls中为每个子应用的路由添加命名空间
• 例如 url(r’^response_json/$’, views.response_json, name=‘json’), •
• 为子应用的路由添加命名空间 • 语法格式为
path(‘url地址’,include((‘app的url文件地址’,子应用文件名),namespace=‘命名’)
• 例如 path(r'weather/', include(('request_response.urls','request_response'), namespace='request_response')),
]
•
这样在使用反向解析的时候 语法为:
reverse(‘命名空间:别名’),
例如: reverse(‘user:json’)
3.3.1. ookie介绍
• Cookie是存储在浏览器中的一段纯文本信息,尽量不要存储密码等敏感信息
• cookie 以键值对的格式进行信息的存储
• cookie基于域名安全,不同域名的cookie是不可以相互访问的
• 当浏览器请求某网站时,会将浏览器存储的跟网站相关的所有cookie信息提交给网站服务器
3.3.2. cookie使用
• 设置cookie
• 通过HTTPResponse中的set_cookie方法来设置cookie
• response = HTTPResponse(‘ok’) response.set_cookie(‘键’,‘值’, ''cookie生存时间)
• 访问cookie
• 通过 请求对象resquest.COOKIE.get(‘键名’)的得到对应的cookie值
• cookie_name = request.COOKIES.get(‘name’)
• 删除cookie
• 响应对象response.delete_cookie(‘键名’)
• response.delete_cookie(‘age’)
3.4.1. 存储方式
• 内存
SESSION_ENGINE = “django.contrib.sessions.backends.cache”
• 数据库,需要在INSTALLED_APPS中安装Session应用,默认配置文件有
• SESSION_ENGINE = “django.contrib.sessions.backends.db”
• 混合存储
• SESSION_ENGINE = “django.contrib.sessions.backends.cache_db”
3.4.2. Redis内存型数据库
• 安装
• pip install django-redis redis
• 在django的setting中配置
•
# redis数据库配置
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://49.232.23.70:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
#设置session有内存缓存
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
缓存到redis default的配置redis
SESSION_CACHE_ALIAS = "default"
3.4.3. session 的基本操作
• 键值对格式写session
• request.session[‘键’] = 值
• 根据键值取值
• request.session.get(‘键’)
• 删除session 中数据
• request.session.clear()
• 清除所有session 在储存中删除session的整条数据,包括cookie的session_id
• request.session.flush()
• 删除指定的键值,在存储中删除某个键对应的值
• del request.session[‘键’]
• 设置 session的有效期
• request.session。set_expiry(value)
- 如果 value 是整数1,就是这只在value秒之后过期
- 如果 value为0,那么浏览器关闭后sessionguo过期
- 如果为None,在默认两周后过期,通过setting.py中的SESSION_COOKIE_AGE来设置
4.1. 类视图
4.1.1. 1. 导包
from django.views.generic import View 或者 from django.views import
View
4.1.2. 2. 写类
继承View 重写View类的get与post方法
4.1.3. 3
. 类试图的路由格式,url(r’^demoview/$’, views.类名.as_view()) • as_view()是判断请求方法的
4.1.4.
- 装饰器装饰类试图
• 装饰器代码
•
#装饰器
def my_decorator(view_func):
'''定义装饰器'''
def wrapper(request, *args, **kwargs):
print('装饰器被调用了')
return view_func(request, *args, **kwargs)
return wrapper
• 在路由界面进行装饰
url(r'^demoview/$', views.my_decorator(views.ClassView.as_view()))
• 在类试图上进行装饰
• 导包
from django.utils.decorators import method_decorator
• 在类上面装饰类中的某个方法
@method_decorator(‘装饰器名字’, ‘需要被装饰的方法’)
• 例子@method_decorator(my_decorator,'dispatch')
•
这样装饰的效果就是将装饰方法转换成装饰函数,因为方法有一个self的属性
• 在类里面单独装饰某个方法
•
直接在方法名上写
@method_decorator(my_decorator)
4.2. 中间件
4.2.1. 介绍
• Django中的中间件是一个轻量级、底层的插件系统,可以介入Django的请求和响应处理过程,修改Django的输入或者输出,中间件的设计为开发者提供了一种无侵入式的开发方式,增强了django的健壮性,
• 我们可以使用中间件,在Django处理视图的不同阶段对输入或输出进行干预
4.2.2. 中间件的定义方法
• 在settings.py文件的MIDDLEWARE列表中注册中间件 • 写在下面,这个列表后期被反转了(后面的会先执行)
• 在工程同名文件下新建middleware.py文件,文件里为中间件 (定义一个中间件工厂函数,然后返回一个可以被调用的中间件
,中间件工厂函数需要接收一个可以调用的get_response对象)
•
from django.http import HttpResponse
def my_middleware1(get_response):
print('init1111 被调用')
def middlware(request):
print('before request 111111被调用')
response = get_response(request)
print('after response11111 被调用')
return response
return middlware
def my_middleware2(get_response):
print('init2222222 被调用')
def middlware(request):
print('before request22222 被调用')
response = get_response(request)
print('after response 2222222被调用')
return response
return middlware
def my_middleware3(get_response):
print('init 3333333 被调用')
def middlware(request):
print('before request 33333333被调用')
response = get_response(request)
print('after response333333333 被调用')
return response
return middlware
• 执行顺序 类似一个递归的操作 • 请求在被处理之前 所有的中间件是自上而下的去执行
• 当请求被处理之后响应时,所有的中间件的执行顺序是自下而上的
• 假设在中间件的返回response处写了一个固定返回,那么返回的界面就被这个固定的返回界面拦截了
def my_middleware2(get_response):
print('init2222222 被调用')
def middlware(request):
print('before request22222 被调用')
response = get_response(request)
print('after response 2222222被调用')
return HttpResponse('我拦截了所有的界面')
return middlware
5.1.1. 1. 安装
pip install django-cors-headers
5.1.2. 2. 配置 settings.py文件
# 在INSTALLED_APPS里添加
“corsheaders”
INSTALLED_APPS = [
...
'corsheaders'
]
# 在settiongs 里 MIDDLEWARE 中添加如下
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
]
5.1.3. 3. 在settings.py的末尾添加
#跨域增加忽略
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
CORS_ORIGIN_WHITELIST = ()
CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
'VIEW',
)
CORS_ALLOW_HEADERS = (
'accept',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
)
6.1. 创建模板的步骤
- 在子应用目录下创建templates文件夹,存放html文件
在settings.py的模板文件配置项TEMPLATES的‘DIRS’中写入模板文件夹的路径 • 例如: ‘DIRS’: [os.path.join(BASE_DIR, ‘user/templates’)], #指定模板文件加载路径
在视图函数内返回 return render(request, ‘index.html’, context)
其中context为字典数据 context = {
‘name’:‘kobe’,
‘userlist’:[8,24],
‘userdict’:{
‘age’: 20,
‘name’:‘詹姆斯’,
} }
7.1. ORM框架
7.1.1. 1. ORM框架
• O是 object
也就是类对象的意思,R是relation也就是关系,关系数据库中数据表的意思,M是mapping是映射的意思。它帮我们的类和数据表进行一个映射。可依让我们通过类和类对象就能操作它对应表格中的数据,它也可以根据我们设计的类自动帮我们生成数据库中的表格,省去我们建表的过程
7.1.2. 2. 使用django进行数据库开发步骤
• 配置数据库连接信息
• python3 安装 mysql3
• pip install pymysql
• 因为 在 ORM里面它只认识python2的 mysqldb 所以我们需要骗一下系统
• 具体操作:在工程文件里的init里加入如下代码:
import pymysql
pymysql.version_info = (1, 4, 13, "final", 0) # 指定版本
pymysql.install_as_MySQLdb() #将pymysql改别名为 mysqldb
• 1.3 创建一个数据库
• create database 数据库的名称 charset=utf8
• 1.4 在项目文件下的settings中配置数据库
#数据库配置项
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST':'49.232.23.70', # 数据库主机
'PORT':'3306', # 端口号
'USER':'root', # 数据库用户名
'PASSWORD':"seven597", # 数据库密码
'NAME':'django_24', # 数据库名
}
}
• 2.2 在models.py中定义模型类
• 2.1 数据库表名
模型类如果未指明表名,Django默认 以小写app应用名_小写模型类名
为数据库表名,可以在模型类的Meta类中的db_table指明数据库表名
• 2.2 关于主键
• django
会为表创建自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后django不会再创建自动生长的主键列。
• 默认创建主键列属性为id,可以使用pk代替,pk全拼为primary key
• 2.3 属性命名限制
• 不能是python的保留关键字 • 不允许使用连续的下划线,这是由django的查询方式决定的
• 定义属性时需要指定字段类型,通过字段类型的参数指定选项 语法如下: 属性 = models.字段类型(选项)
• 2.4 字段的类型
• AutoField 说明: 自动增长的IntegerField, 通常不用指定,不指定时django会自动创建名为id的自动增长属性
• BooleanField 说明:布尔字段,值为True或False
• NullBooleanField 说明: 支持Null、True、False
• CharField 说明:字符串,参数max_length表示最大字符个数
• TextFiled 说明:大文本字段,一般超过4000个字符的时候使用
• IntegerField 说明: 整数
• DecimalField 说明: 十进制浮点数,参数max_digits表示总数位数,参数decimal_places表示小数位数
• FloatField 说明:浮点数
• DetaField 说明:日期,参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于“最后一次修改”的时间戳,它总是使用当前日期,默认为False;参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为False;参数auto_now_add和auto_now是相互排斥的,组合将会发生错误
• TimeField 说明:时间,参数与DateField相同
• DateTimeField 说明:日期时间,参数同DateField • FileField 说明:上传文件字段
• ImageField 说明:继承于FileField,对上传的内容进行校验,确保上传的是有效图片
• 2.5 选项
• null 说明: 如果是True表示允许为空,默认值为False
• blank 说明:如果为True,则该字段允许为空白,默认为False
• null是数据库范畴的概念,blank是表单验证范畴的
• db_column 说明:字段的名称,如果未指定,则使用属性的名称
• db_index 若值为True,则在表中会为此字段创建索引。默认为False
• default 说明: 默认
• primary_key 说明: 若为True,则该字段会成为模型的主键字段。默认为false,一般作为AutoField的选项
• unique 说明:如果为True,这个字段在表中必须有唯一值,默认值为False
• 2.6 外键
• 在设置外键时,需要通过on_delete选项指明主表删除数据时,对于外键引用表数据如何处理,在django.db.models中包含如下可选常量
• CASCADE级联,删除主表数据时,联通一起删除外键表中的数据
• PROTECT保护,通过抛出ProtectedError异常,来阻止删除主表中被外键应用的数据
• SET_NULL设置为NULL,仅在该字段null=True允许为null时使用
• DO_NOTHING不做任何的操作,如果数据库前置指明级联性,此选项会抛出IntegrityError
• SET_DEFAULT设置为默认值,仅在该字段设置了默认值时可用 • SET()设置为特定值或者调用特定方法,如下
from django.conf import settings
from django.contrib.auth import get_user_model
from django.db import models
def get_sentinel_user():
return get_user_model().objects.get_or_create(username='deleted')[0]
class MyMqdel(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete = models.SET(get_sentinel_user)
)
• 2.3 迁移
• 首先要注册子应用,迁移的话必须注册子应用
• 生成迁移文件: pyton manage.py makemigrations
• 同步到数据库: python manage.py migrate
• 2.4 通过类和对象完成数据的增删改查操作
7.1.3. 3. 演示工具
• shell工具
• python manage.py shell
• 查看Mysql数据库日志
• 进入数据库的配置文件
• sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
• 设置如下两行代码
• general_log_file = /var/log/mysql/mysql.log • general_log = 1
• 重启数据库
• sudo service mysql restart
• 实时查看数据库的日志
• sudo tail -f /var/log/mysql/mysql.log
7.1.4. 4. 数据库操作之增删改查
• 4.1 增 save()
• 首先引入 models.py
book = BookInfo()
book.字段 = '值'
book.save()方法
• 当第二个表有外键的时候,关联第一个表的主键
hero = HeroInfo(
字段 = '值',
外键 = 主键的属性 或者 外键_id = 主键所在表的属性.id)
例如 hbook = book 或者 hbook_id = book.id
)
• create()
类名.objects.creats(
字段=‘值’
)
蕴含了save()方法
• 4.2 查
• 基本查询
• get()
类名.objects.get(id=?)
例如
try:
BookInfo.objects.get(id=15)
except BookInfo.DoesNotExist:
print('查询失败')
加上异常语句,如果找不到id的话会出异常
• all()
• 类名.pbjects.all()
例如: HeroBook.objects.all()
会查询所有的记录,返回一个 QuerySet
• 过滤查询
• filter()
过滤出多个结果 过滤条件的语法是 属性名__比较运算符=值
• exact :表示判等
• BookInfo.objects.filter(字段__eaact = ‘值’)
例子: HeroInfo.objects.filter(hbook_id__exact=2)
说明: 查询字段为 某值的记录,可以查询多个记录,返回QuerySet,即使查询的字段值不存在也不会报错
• contains:表示是否包含 •
BookInfo.objects.filter(字段__contains == ‘值’)
例:
HeroInfo.objects.filter(hname__contains='黄')
说明:查询某字段中包含某值的记录,返回多条记录(QuerySet)
• startswith,endswith:以指定值开头或结尾
• # 查询 以...结尾的
BookInfo.objects.filter(btitle__startswith='西')
查询 以...开头的
BookInfo.objects.filter(btitle__endswith='国')
• isnull:是否为null
BookInfo.objects.filter(btitle__isnull=False)
• 多项查询,in:是否包含在指定项内
• #查询编号为 n 或者 m 的
BookInfo.objects.filter(id__in = [2, 4])
• 比较查询
• gt 大于, gte 大于等于, lt 小于, lte小于等于
• #查询编号大于2的
BookInfo.objects.filter(id__gt = 2)
#查询编号大于等于2的
BookInfo.objects.filter(id__gte = 2)
#查询编号小于4的
BookInfo.objects.filter(id__lt = 4)
#查询编号小于等于4的
BookInfo.objects.filter(id__lte = 4)
• 不等于运算器,使用exclude(id=3)过滤器
• # 查询 id 不为 …的
BookInfo.objects.exclude(id=3)
• 日期查询
• year,month,day,week_day,hour,minute,second
• #查询1995年,11月的发布的书籍,
BookInfo.objects.filter(bpub_date__year='1995', bpub_date__month='11')
#查询1990年1月1日后发布的书籍
BookInfo.objects.filter(bpub_date__gt='1990-1-1')
• F对象与Q对象
• 引用头文件 from django.db.models import F,Q
• F对象进行两个属性之间进行比较,也支持运算操作
BookInfo.objects.filter(bread__gt=F('bcomment'))
BookInfo.objects.filter(bread__gt=F('bcomment') * 2)
• Q对象:逻辑与 逻辑或 逻辑非 and or not
BookInfo.objects.filter(bread__gt=11, id__lt=3)
BookInfo.objects.filter(Q(id__lt=3) | Q(bread__gt=20))
BookInfo.objects.filter(~Q(id__lt=3))
• 聚合函数
•
使用aggregate()过滤器调用聚合函数
• Avg平均
from django.db.models import Sum, Avg,Count,Max,Min
• 排序查询
• # 升序
BookInfo.objects.all().order_by('bread')
#降序
BookInfo.objects.all().order_by('-bread')
• 关联查询
• 举例 : # 书的表为主键所在表,英雄的表存在一个外键存储书的id • 多查一,通过即有外键的表查询外键关联的表
• #多查一,根据英雄查询这个英雄属于哪本书
BookInfo.objects.filter(heroinfo__hname='郭靖')
BookInfo.objects.filter(heroinfo__hname__contains='竹')
• # 根据英雄查书, 多查一
hero = HeroInfo.objects.get(hname='郭靖')
book = hero.hbook #如果有外键直接当前模型对象, 外键代表获取外键模型对象
• 一查多,是通过外键关联的表(主键表)查询外键的所有值
#一查多
HeroInfo.objects.filter(bookinfo__id=1) 不可以用这种方法
HeroInfo.objects.filter(hbook__id=1)
• #根据书查英雄,一查多
book = BookInfo.objects.get(id=1)
heros = book.heroinfo_set.all() # 如果当前没有外键的一方, 应该是当前模型对象多的一方模型小写_set 获取所有应当加_set.all()
• 4.3 删
• delete()
#单个删除
BookInfo.objects.get(btitle='大大三国').delete()
#多个删除
BookInfo.objects.filter(id=8).delete()
• 4.4 改
• save()方法
book = BookInfo.objects.get(btitle='大三国')
book.btitle = '大大三国'
book.save()
update()方法
BookInfo.objects.filter(btitle='西游记').update(btitle='东游记')
7.1.5. 查询集 QuerySet
• 概念
• QuerySet 表示从数据库中获取的对象集合,当调用如下过滤器的时候,返回的是查询集,而不是简单的列表。 all()
filter() exclude() order_by() • 对于QuerySet的数据,可以再次使用查询集
例如: BookInfo.objects.filter(bread__gt=30).order_by('bpub_date')
• 限制查询集
• 可对查询集进行去下标或者切片的操作,等同于sql中的limit和offset子句
qs = BookInfo.objetcs.all()[0:2]
#也可以取步长
HeroInfo.objects.all()[0:10:2]
8.1. 1. 创建超级管理员
python manage.py createsuperuser
8.2. 2. py文件对应的admin后台
8.2.1. apps文件里,name与子应用名字一样,verbose_name为admin里显示的模型组的名字
from django.apps import AppConfig
class BooktestConfig(AppConfig):
name = 'booktest'
verbose_name = '图书'
8.2.2. models.py
• 使用 admin.site.register(模型名字)
• 代码:
from django.contrib import admin
from .models import BookInfo,HeroInfo
Register your models here.
admin.site.register(BookInfo)
admin.site.register(HeroInfo)
8.3. 3. 定义模型站点管理类调整admin站点样式
创建BookInfoAdmin(admin.ModelAdmin) 继承admin的ModelAdmin类,在这个类里面管理模型列表界面
8.3.1. 显示隐藏底部搜索框
actions_on_bottom =True 为显示底部搜索框
8.3.2. 控制列表界面显示模型对应的哪些字段(元素可以是模型中的方法名,字段名),假如我们想格式化显示,可以在模型类中添加对应的方法,将方法名放在这个列表中
• models的模型来中定义的方法
def bpub_date_format(self):
return self.bpub_date.strftime('%Y-%m-%d')
bpub_date_format.short_description = "发布日期" #修改方法名在列表页展示成中文
bpub_date_format.admin_order_field = 'bpub_date' #此方法中的数据依据模型的那个字段进行排序
• admin 的站点管理类中加入代码
list_display = ['id', 'btitle', 'bread_company', 'bcomment', 'is_delete', 'bpub_date_format']
8.3.3. 设置右侧过渡栏
list_filter = ['hbook', 'hgender']
8.3.4. 设置搜索框
search_fields = ['hname', 'id']
8.3.5. 设置编辑界面显示的字段
• 只会显示列表中存在的字段
fields = ['btitle', 'bpub_date']
• 将编辑字段分组展示,可设置默认隐藏显示
fieldsets = [
['基础组', {
'fields':['btitle', 'bpub_date']}],
['高级组', {
'fields': ['bread', 'bcomment'],
'classes':['collapse'] #
}]
]
8.3.6. 关联显示数据(在book中显示hero)
• 创建一个关联显示类,继承model.admin.TabularInline如下
class HeroInfoStack(admin.TabularInline):
model = HeroInfo #关联的模型类
extra = 2 # 显示几个空盒子
在 bookinfo的模型类中加入
inlines = [HeroInfoStack]