目录
1.什么是静态文件,django静态文件配置如何配置,如何解决接口前缀不断变化,html页面上路径的引用需要反复修改的问题
2.request对象的方法有哪些,分别是干什么用的,请具体阐述细节及注意事项
3.django自带的数据库是什么,如何换成其他数据库例如MySQL,如何配置更换
4.什么是django orm,如何使用django orm,数据库迁移命令如何书写
1.表关系如何判定,django orm中如何建立表关系,有什么特点和注意事项
4.什么是正反向的概念,及查询口诀,你能否总结一下正反向查询不同情况下点击不同字段的规律
5.MySQL中的跨表查询如何实现,针对主动链表操作,你能否说一说每一种链表操作的具体特点
3.什么是ajax,请手写出ajax的基本语法结构。指出ajax发送json格式数据需要注意什么,发送包含文件类型数据又需要注意什么
4.前后端传输数据编码格式有哪些,针对这些格式django后端有怎样的区别处理
1.聚合查询,分组查询的关键字各是什么,各有什么特点或者注意事项
2.F与Q查询的功能,他们的导入语句是什么,针对Q有没有其他用法
4.什么是事务,事务的特性有哪些,你是否了解数据库设计范式(列举三个即可)
静态文件: 不会更改的文件, 如js,css,jq,img等
配置:
- STATIC_URL=/'static'/
- STATICFILES_DIR = [os.path.join(BASE_DIR,'static']
html方面:
{% load static 文件绝对路径%}
request对象方法
request.method 获取请求方式, 结果是纯大写的字符串
request.POST 获取POST请求发送来的普通数据[不包含文件]
request.POST.get() 默认值获取列表中最后一个数据
request.POST.getlist() 获取键对用的整个列表, 无论有几个数据值
request. GET 获取url?之后可以携带不超过2kb的非敏感数据.
request.GET.get() 默认只获取列表中最后一个数据值
request.GET.getlist() 获取键对应的整个列表, 无论有几个数据值
django自带的数据库是sqlit3, 只能做本地测试的小型关系型数据库,无法承受过大的数据量, 可以通过链接别的数据库进行操作, 如mysql,
pycharm右上角,左下角等地找到database, 然后进行链接, 第一次链接的时候会下载一个驱动[根据提示一步步操作即可], 后续无需再次下载. 输入用户名密码以及数据库之后apply>>>再test connection, 链接成功后按🆗即可.
数据库配置
- DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.mysql', # 指定数据库软件名称
- 'NAME': '', # 指定库名
- 'USER': '', # 用户名
- 'PASSWORD': '', # 密码
- 'HOST': '127.0.0.1',
- 'PORT': 3306,
- 'CHARSET': 'utf8'
- }
- }
ORM 对象关系映射表
类名 >>>> 表名
类属性>>>表里的字段
类实例>>> 表里的一行行数据
====================================
类 ---------->>> 表
对象 -------->>> 表里面的数据
对象点属性 -->>> 字段对应的值
orm基本操作
- class Users(models.Model):
- uid = models.AutoField(primary_key=True) # 等价于uid int primary key auto_increment
- name = models.CharField(max_length=32) # 等价于name varchar(32)
- pwd = models.IntegerField() # 等价于pwd int
数据库迁移命令:
pycharm: models.py中, make migrations>>>migrate
cmd: python manage.py make migrations>>> python manage.py mirgate
models.User.objects.filter()
models.User.objects.create()
models.User.objects.filter(id=1).update(name='yietong666')
models.User.objects.filter(id=4).delete()
表关系的判断主要通过换位思考双方的关系的来的, 比如: 个人与个人信息是一对一关系, 班级与课程是一对多关系, 老师与课程是多对对关系等
表关系的建立主要通过外键字段foreignkey来建立链接,
一对一表关系, ORM中外键关联字段 models.OneToOneField() , 会自动添加_id后缀
一对多表关系, ORM中外键字段在多的一方, models.Foreignkey() 会自动添加_id
多对多表关系,ORM中有三种创建多对对字段的方式, moels.ManyToManyField() 会自动添加_id后缀
方式1: 直接在查询频率改的表中填写即可, 自动创建第三张表
方式2 : 自己创建第三张表
方式3: 自己创建第三张表关系, 但是还是需要orm多对多字段做关联.
注意事项:
django1.x 针对models.ForeignKey()>>>> models.OneToOneField() 不需要on_delete字段, 而django2.x,3.x则需要添加on_delete字段.
django的生命周期是:前端请求--->nginx--->uwsgi.--->中间件--->url路由---->view视图--->orm---->拿到数据返回给view---->试图将数据渲染到模版中拿到字符串---->中间件--->uwsgi---->nginx---->前端渲染。
路由层是django框架除了中间件的第一层. 写在urls.py的urlpatterns列表中, 语法为path('网址后缀',函数名). 一旦网址后缀匹配上了, 就会自动执行后边的函数并结束整个路由的匹配.
默认情况下不写斜杠, django会做二次处理, 第一次匹配不上,会让浏览器加斜杠再次请求.
django配置文件中也可以指定是否自动添加斜杠APPEND-SLASH = False
当网址后缀不固定的时候, 可以使用转换器来匹配
'int':IntConverter()
path': PathConverter(),
'slug': SlugConverter(),
'str': StringConverter(),
'uuid': UUIDConverter(),
path('func/
转换器匹配到的内容会被当作视图函数的关键字参数传入, 转换器有几个那么视图函数的形参就必须对应.>>> def func(request,year,info):pass
re_path(正则表达式,函数名)
一旦网址后缀的正则能够匹配到内容就会自动执行后面的函数, 并结束整个路由的匹配
当网址后缀不固定时, 可以使用转换器来匹配
re_path('^test/(\d+)/',views.test) 正则表达式匹配到的内容就会当作视图函数的位置参数传递给视图函数
re_path('^test/(?P
正则表达式匹配到的内容会当作视图函数的关键字参数传递给视图函数
在1.x版本中, 之指出正则匹配,并且方法是url
2/3/4中, path(), re_path()等价于url()
反向解析的出现是为了防止写死的路由中途出现变化导致所有页面的相关链接失效, >>>>>>
反向解析返回一个结果, 该结果可以访到对应的路由
具体措施为:
path('register/',views.reg,name='reg_view')
html页面上:
{% url 'reg_view' %}
后端:
- from django.shortcuts import reverse
-
- reverse('reg_view')
反向解析的操作三个方法都一样(path() / re_path()/ url()
path('reg//' ,views.reg,name='reg_view')
当路由中有不确定的匹配因素, 反向解析的时候需要认为给出一个具体的值
reverse('reg_view',args=('yietong'.))
{% 'reg_view', 'yietong'%}
django 中的应用都可以又自己独立的urls.py templates文件夹, static文件夹, 能换个让基于django开发的多个应用完全独立, 便于小组开发
总路由
- path('app01/',include('app01.urls')),
- path('app02/',include('app02.urls')),
子路由
- path('after/',views.after) # app01
- path('after/',views.after) # app02
当项目很大, 应用很多的时候使用路由分发特别方便
路由分发场景下多个应用涉及到反向解析别名冲突的时候无法正常解析而出现的
1. 名称空间 namespace
- path('app01/', include(('app01.urls', 'app01'), namespace='app01'))
- path('app01/', include(('app01.urls', 'app02'), namespace='app02'))
2. 别名不要冲突
all() >>> 查询所有结果
filter(**kwargs) >>> 它包含了与所给筛选条件相匹配的对象
get(**kwargs)>>> 返回与所给筛选条件相匹配的对象, 返回结果有且只有一个,如果符合筛选条件的对象超过IP一个或者一个都没有就会报错, 所以布套推荐使用, 可以使用first()来代替
exclude(**kwargs) >>> 包含了与所给筛选条件不匹配的对象
values(*field)>>> 返回一个valuequeryset对象,----一个特殊的QuerySet, 运行后得到的并不是一些列model的实例化对象, 而是一个可迭代的字典序列
value_list(*field)>>> 他与value()非常相似, 他返回的是一个元组序列, values返回的是一个字典
order_by(): >>> 对查询结果排序
reverse()>>> 对查询结果反向排序, 请注意, reverse() 通常只能在具有已定义顺序的QuerySet上调用,[ 在model类的meta中指定ordering 或者调用order_by()方法 ]
distinct()>>>> 从返回结果中提出重复记录,如果查询跨越多个表, 可能在计算QuerySet时得到重复的结果, 此时可以使用distinct(), 注意 只有在PostgreSQL中支持按字段去重
count()>>>> 返回数据库中匹配查询QuerySet的对象数量
first()>>> 返回第一条记录
last()>>> 返回最后一条记录
exists() >>> 如果QuerySet包含数据, 就返回True, 否则返回False.
返回QuerySet对象的方法有
all(), filter(), exclude(), order_by(), reverse(), distinct()
特殊的QuerySet
values() 返回一个可迭代的字段序列
values_list() 返回一个可迭代的元组序列
返回具体对象
get(), first(), last()
返回布尔值的方法
exists()
返回数字的方法
count()
__gr >>> 大于
__gte >>> 大于等于
__lt >>> 小于
__lte >>> 小于等于
__in >>> 成员运算
__range >>> 判断范围[数字]
模糊查询:
字段__contains >>> 不忽略大小写
字段__icontains >>> 忽略大小写
日期处理
字段__year
字段__month
字段__day
add() >>> 添加数据, 括号内既可以填写数字值, 也可以填写数据对象, 支持多个
remove() >>> 删除数据, 括号内既可以填写数字值也可以填写数据对象, 支持多个
set() >>> 修改数据, 括号内必须时可迭代对象
clear() >>> 清空指定数据, 括号内不需要任何参数
正反向概念的核心在于外键字段在哪里
正向查询>>> 通过书查询出版社, 外键字段在书表中
反向查询>>> 通过出版社查询书籍, 外键字段在书籍表中
有一个跨表查询的小窍门>>> 正向查询按照外键字段, 反向查询按照表名小写
跨表查询通过关联外键实现的,
一对多:
ORM中外键字段在多的一方>>> models.ForeignKey() 会自动添加_id后缀
多对多:
ORM 中有三种创建字段的方式>>> models.ManyToManyField()
1.直接在查询频率搞得表中填写字段即可, django会自动创建第三张表关系
authors = models.ManyToManyField(to='Author')
优点: 第三张表自动创建, 缺点: 第三张表扩展性差
2. 自己创建第三张表
- class Book(models.Model):
- pass
- class Author(model.Model):
- pass
- class Book2Author(models.Model):
- book_id = models.ForeignKey(to='Book')
- models.ForeignKey(to='Book')
- models.ForeignKey(to='Author')
优点: 第三张表扩展性强, 缺点: 无法使用正反向查询以及多对多四个方法
3.自己创建第三张表关系, 但是还要orm多对多字段做关联
- class Book(models.Model):
- authors = models.ManyToManyField(
- to='Author',
- through='Book2Author',
- through_fields=('book_id','author_id')
- )
-
-
- class Author(models.Model):
- pass
-
- class Book2Author(models.Model):
- book_id = models.ForeignKey(to='Book')
- author_id = models.ForeignKey(to='Author')
优点: 扩展性强并且支持正反向查询, 缺点: 无法使用多对多的四个方法
一对一:
ORM中外键字段建在查询频率较高的表中 >>> models.OneToOneField()会自动添加_id后缀
ps: Django 1.x中 针对models.ForeignKey(), models.OneToOneField()不需要添加on_delete=models.CASCADE, 而django2.x, 3.x中需要自己添加
django orm 默认都是惰性查询, 当orm的语句在后续的代码中真正需要使用的时候才会展示, django orm 自带有limit分页(默认21页)功能, 用以减轻数据库端以及服务端的压力
ORM的优化操作有only 与 defer 和 select_related 与 prefetch_related
only 会将括号里填写的字段封装成一个个数据对象,对象在点击的时候不会再走数据库查询,
对象也可以惦记括号内没有的字段, 只不过这个时候每次查询都会走数据库.
defer刚好与之相反. >>> 数据对象惦记括号内出现的字段, 每次都会走数据库查询,
点击括号内没有的字段,不会走数据库查询.
select_related 括号内只能接收外键字段, (一对一, 一对多)自动链表, 得出的数据对象再点击表中数据的时候都不会再走数据库查询
prefetch_related 底层其实是子查询, 将查询之后的结果也一次性封装到数据对象中, 用户在使用的时候是感觉不出来的
当字段数据的可能性是可以完全列举出来的时候, 应该考虑使用choices参数. 如性别,学历,成绩等
- class UserInfo(models.Model);
- username = models.CharField(max_length=32)
- gender_choice = (
- (1,'male'),
- (2,'female'),
- (3,'otrher'),
- )
-
- gender = models.IntegerField(choices=gender_choice)
- userinfo_obj.get_gender_display()
ajax是js自带的功能,其特点为: 异步提交,局部刷新
- $.ajax({
- url:'', // 控制数据的提交地址
- type:'', // 控制请求方式, 默认是get 请求
- data:{}, // 组织提交的数据
- success:function(args){
- 异步回调函数
- }
- })
发送数据编码的格式有四种
Content-Type
格式1: urlencoded
name='yietong'&pwd=123&hobby=read
django后端会统一处理到request.POST中
格式2: formdata
数据格式无法查阅, django后端自动将文件数据处理到request.FILES中, 将普通数据处理到request.POST中,
格式3:application/json
数据格式: json格式
django后端不会处理, 再request.body中存储(bytes类型)自己处理.
语法注意事项
- data:JSON.stringfy({'name':'yietong''pwd':123}),
-
- contentType:'application/json',
-
- $.('#d3').click(function(){
- //1. 产生内置对象
- let formData = new FormData();
- // 2. 添加普通数据
- formData.append('username',$('#d1).val())
- // 3. 添加文件数据
- formData.append('file',$('#d2')[0].files[0]
- // 4. 发送ajax请求
- $.ajax({
- url:'',
- type:'post',
- data:formaData,
- contentType:false, // 不使用任何编码
- success:function(args){}
- })
- })
回调函数
后端跟ajax交互, 不应该再返回首页, 通常情况下都是返回json核实数据.. 前端针对HttpResponse和JsonResponse返回的json格式数据处理策略不同
前者不会自动反序列化, 后者会自动反序列化.
如果想让前者页自动反序列化, 可以添加应该固定的参数>>> dataTyp:'JSON'
聚合查询是没有分组之前的查询, 关键字为aggregate, from django.db.models import Max,Min,Sum,Avg,Count
分组之后查询的关键字为annotate
按照整条数据分组语句为>>> models.Book.objects.annotate()
按照表中某个字段分组语句为>>> models.book.objects.values('title').annotate(), 按照的是annotate之前的values括号中指定的字段分组
from django.db.models import F
查询条件不是自定义的而是来自于表中的其他字段. 例如将书本加上固定字样格式, 上调价格等,
但是由于字符串无法直接进行拼接, 使用需要导入模块
- from django.db.models.functions import Concat
-
- from django.db.models import Value
-
- res = models.book.objects.filter(pk=5).update(title=Concat(F('title'),Value('中秋快乐')))
from django.db.models import Q
使用Q对象, 可以支持逻辑运算符>>> 逗号是and关系, | 管道符是or关系, ~波浪号是not关系
当我们需要一个搜索功能, 并且条件由用户指定, 这时候需要将搜索内容变成字符串,
- q_obj = Q()
-
- q_obj.connector = 'or' # 默认是and 可以改成or
-
- q_obj.children.append(('price__gt',200))
-
- res = models.Book.objects.filter(q_obj)
- print(res.query)
AutoField()
CharField()
IntegerField()
BigIntegerField()
DateField()
DateTimeField()
DecimalField()
EmailField()
BooleanField()
传布尔值存数字0或1
TextField()
存储大段文本
FileField()
存储文件数据 自动找指定位置存储 字段存具体路径
ForeignKey()
OneToOneField()
ManyToManyField()
- class MyCharField(models.Field):
- def __init__(self, max_length, *args, **kwargs):
- self.max_length = max_length
- super().__init__(max_length=max_length, *args, **kwargs)
-
- def db_type(self, connection):
- return 'char(%s)' % self.max_length
- info = MyCharField(max_length=32)
max_length
verboses_name
auto_now
auto_now_add
null
default
max_digits
decimal_places
unique=True
db_index=Trueto
to_field
related_name
choices
当字段数据的可能性是可以完全列举出来的时候 应该考虑使用该参数
性别
学历
成绩
- class UserInfo(models.Model):
- username = models.CharField(max_length=32)
- gender_choice = (
- (1, '男性'),
- (2, '女性'),
- (3, '其他'),
- )
- gender = models.IntegerField(choices=gender_choice)
- userinfo_obj.get_gender_display()
on_delete
1、models.CASCADE
级联操作,当主表中被连接的一条数据删除时,从表中所有与之关联的数据同时被删除
2、models.SET_NULL
当主表中的一行数据删除时,从表中所有与之关联的数据的相关字段设置为null,此时注意定义外键时,这个字段必须可以允许为空
3、models.PROTECT
当主表中的一行数据删除时,由于从表中相关字段是受保护的外键,所以都不允许删除
4、models.SET_DEFAULT
当主表中的一行数据删除时,从表中所有相关的数据的关联字段设置为默认值,此时注意定义外键时,这个外键字段应该有一个默认值
5、models.SET()
当主表中的一条数据删除时,从表中所有的关联数据字段设置为SET()中设置的值,与models.SET_DEFAULT相似,只不过此时从表中的相关字段不需要设置default参数
6、models.DO_NOTHING
什么都不做,一切都看数据库级别的约束,注数据库级别的默认约束为RESTRICT,这个约束与django中的models.PROTECT相似
事务是作为单个逻辑工作单元执行的一系列操作。一个逻辑工作单元必须有四个属性,称为原子性、一致性、隔离性和持久性 (ACID) 属性,只有这样才能成为一个事务。事务一般都是与数据库打交道的操作.
为了建立冗余较小、结构合理的数据库,设计数据库时必须遵循一定的规则。在关系型数据库中这种规则就称为范式。范式是符合某一种设计要求的总结。
范式简单理解即为:一张数据表的设计结构需要满足的某种设计标准的级别。
第一范式是最基本的范式。1NF是对属性的
原子性
,要求属性具有原子性,不可再分解;如学生(学号,姓名,性别,出生年月日),如果认为最后一列还可以再分成(出生年,出生月,出生日),它就不是一范式了,否则就是
第二范式在第一范式的基础之上更进一层。第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。也就是说在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。
2NF是对记录的
唯一性
,要求记录有唯一标识,即实体的唯一性,即不存在部分依赖;第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。
如果一个关系属于第二范式,并且在
两个(或多个)非主键属性之间不存在函数依赖
。(非主键属性之间的函数依赖也称为传递依赖),那么这个关系属于第三范式。3NF是对字段的
冗余性
,要求任何字段不能由其他字段派生出来,它要求字段没有冗余,即不存在传递依赖;
一般地,在进行数据库设计时,应遵循三大原则,也就是我们通常说的三大范式,即第一范式要求确保表中每列的原子性,也就是不可拆分;第二范式要求确保表中每列与主键相关,而不能只与主键的某部分相关(主要针对联合主键),主键列与非主键列遵循完全函数依赖关系,也就是完全依赖;第三范式确保主键列之间没有传递函数依赖关系,也就是消除传递依赖。
1. 创建django项目以及配置各种基础设置信息
2. 模型类的创建以及数据准备
3. 首页搭建
巨幕, 侧边栏,导航条, 图片展示
4. 书籍展示页搭建
模板继承 extend, block,, select_related, 过滤器, 标签
5.书记添加页搭建
from表单, create(), add()
6. 书籍编辑页搭建
form表单, update(0, set()
7, 书籍删除页搭建
return false