## 命令
1. `python manage.py startapp APPNAME`:创建app,然后需要在settings.py里`INSTALLED_APPS`列表安装应用
2. `python manage.py makemigrations appName` :生成迁移文件,让django知道模型发生了哪些变化
3. `python manage.py migrate appName` :执行迁移,在数据库里生成相应表单
4. `python manage.py inspectdb > xxx/models.py`:将数据库中有的表生成到指定模型文件中
5. `python manage.py createsuperuser`:创建后台管理账号
6. `python [manage.py](http://manage.py) clearsessions`:删除当前表里所有过期的session数据
7. `python3 [manage.py](http://manage.py) createcachetable`:生成数据库缓存的表
## 笔记
### 项目VS应用
- Django 中,每一个应用都是一个 Python 包
- 项目则是一个网站使用的配置和应用的集合
### 路由
1. path()
1. route:路由位置
2. view:特定的视图函数
3. kwargs:传递给视图函数的参数
4. name:为url取名
2. include()分布式路由
它的作用是截断原先的路由,插入新的匹配url部分
3. re_path():`?P<命名>reg`
### URL的命名组
- 普通字符串命名
- 正则表达式非命名组
- 正则表达式命名组
- 在 Django 的 URL 解析器中,'[http://127.0.0.1:8000/](http://127.0.0.1:8000/)' 并不是 URL 的一部分,即只有'[http://127.0.0.1:8000/](http://127.0.0.1:8000/)' 后面会被解析
- 通常是由上至下逐一去匹配
![django_转换器.png](https://s2.loli.net/2022/02/24/LQHBeV4g7XDRfmq.png)
### Model模型
Model类已经实现了数据库的CURD
**改变数据库模型步骤**
1. 编辑models.py文件,改变模型。
2. 将应用添加到settings.py配置文件的INSTALL_APPS中
3. 运行 `python manage.py makemigrations` 为模型的改变生成迁移文件。
4. 运行 `python manage.py migrate` 来应用数据库迁移。
### 视图函数
接收浏览器请求(HttpRequest),并通过HttpResponse返回响应函数
### 请求
HttpRequest对象,通过request可以获得丰富的信息,如请求的协议,请求体,请求路径、请求方法、客户端相关信息。。。。
[详细参考](https://docs.djangoproject.com/zh-hans/3.2/ref/request-response/)
### 响应
![django_状态码.png](https://s2.loli.net/2022/02/24/otN6MK3Be7vruHc.png)
### Get 和Post
通常来说不管是什么请求方法都会统一由一个view视图函数接收,然后再通过`request.method`区分具体的请求方法,来做不同的事情
为了防止访问攻击,采用了csrf
### MVC与MTV
**MVC:降低模块间的耦合度**
- M:Model,对数据库层面的封装
- V:View,用于用户展示结果
- C:Controller,用于处理数据、获得数据、返回结果
**MTV:**
- M:Model,负责与数据库交互
- T:Templates,负责呈现到浏览器的内容,可以根据视图层传递的数据生成对应的HTML
- V:View,接收数据,获取数据,返回结果
### 模板标签
- {% if %}。。。{%else%} 。。。{% endif %}
- {% for %} 。。。{% empty %} 。。。 {% endfor %}
### 模板过滤器
格式:`data|过滤器`
- lower
- upper
- safe:默认不对变量内的字符串进行html转义
- add:”n” :将value值增加n
### 模板继承
子模板:{% extends “base.html” %}
父模板:{% block block_name %}子类中可以修改的部分 {% endblock block_name %}
注意:子模板无法继承父模板的变量
### URL解析
- 绝对地址:http://xxx.xxx.xxx(推荐)
- 相对地址:
- /xxx,将地址栏里的地址和这部分数据拼在一起
- xxx,将地址栏里最后一个`/`前的地址和这部分数据拼在一起
### URL反向解析
- templates中使用{% url ‘name’ %},这个name是在urls路由配置时定义的,动态反射当前正确的路由
- Django中解析通过`from django.urls import reverse`
### 静态文件加载
setting.py配置
- `STATIC_URL=’xxx’`:服务器看到这个地址字段表示这是一个静态请求,而不是模板文件,即从这个字段后面的地址在`STATICFILES_DIRS`文件下去查找
- `STATICFILES_DIRS = ((’xxxx’),)`:表示服务器本地寻找静态文件的实际位置
加载(注意斜杠)
- IP/`STATIC_URL`/`STATICFILES_DIRS`下存储的地址
- /`STATICFILES_DIRS`下存储的地址
- 通过`{% load static %}`加载,`{% static ‘静态资源路径’ %}`使用静态资源,即`STATICFILES_DIRS`下图片所在的位置,不用加上`STATIC_URL`前缀和前面斜杠
### 模型层及ORM
- 建议创建数据库时指定字符集便于中文输入`create database DBName default charset utf8`
- ORM特点:
- 模型类允许通过面向对象的方式操作数据库,实现了操作和数据的解耦
- 通过类生成数据表格
- 通过配置可以进行数据库的切换
- 由于映射的缘故,会有一定的性能消耗
- 字段类型:[参考](https://docs.djangoproject.com/zh-hans/3.2/ref/models/fields/#field-types)
- 配置
![django_数据库设置.png](https://s2.loli.net/2022/02/24/hC1bSpBRktAMyYd.png)
- 模型:继承于`django.db.models.Model`的类,每一个类属性都是数据库中的一个字段,模型是数据交互的接口,表示操作数据库的方式
- Meta类:给模型赋予属性,在类里增加一个Meta类
- 表名:`db_table = “Name”`
- 字段选项:
- primary_key:设置为True,则指定字段为主键
- blank:设置True时,字段可以为空,主要用于后台
- null:True,表示该列值可以为空,默认为False,建议添加default设置默认值
- default:设置所在列默认值
- db_index:表示该列增加索引
- unique:表示唯一索引
- db_column:指定列的名称,不指定则为字段名
- verbose_name:admin显示名称,一般写在第一个位置,可以代替这个字段名,具有更好的展示可读性
- 管理器对象:每一个模型类都会有`objects`,来实现数据库的CURD
**创建数据**
- `MyModel.objects.create(attr1=,attr2=)`只要执行了,没有报错,数据就存入了
- 创建Model实例对象,并调用save()保存
```python
obj = MyModel(attr1=,attr2=)
obj.attr1 = value
obj.save()
```
**查询数据**
- .all()方法,返回一个容器对象列表,可以通过各个对象中属性名来访问属性
- .values(’字段名’)方法,按字段去取数据,返回的是字典
- .values_list(’字段名’)方法,返回的是元组,通过索引取值
- order_by(’字段名’)排序,默认升序,如果想要降序,在字段名前加一个负号
- .quary属性,可以查看获得的对象使用的具体sql语句
**条件查询**
- .filter(’属性‘=条件,’属性‘=条件)方法,多个参数,默认是与关系,多做等值类查询;如果想要做非等值查询,需要使用查询谓词,eg:__exact等值匹配、__contains包含查询、__startwith、__endwith、__gt大于、__lt小于、__lte小于等于、__in、__range(等同于between and)
- .exclude()方法,取非
- .get()方法,返回单条数据,如果查询结果多于一条或没有数据都会报错
**修改数据**
- 单条修改:1. get() 2. 通过属性直接修改 3. save()
- 批量修改:1. filter()、all() 2. update(属性=值)
**删除数据**
通常来说不会真正删除数据,而是通过增加字段`is_active`来标注这个数据
- delete()
**F对象**
F对象包裹的字段可以理解为,没有取出该数据,而是在原来的基础上直接进行操作,在数据库的层面上实现高并发,一般可以用于数据更新,数据比较
**Q对象**
主要是用于与、或、非条件查询,用Q包裹条件,并带上特定符号(&、|、~)
**聚合查询**
- .aggregate(结果变量名=聚合函数(”列”)),聚合函数如:Sum、Avg、Count、Max、Min,返回字典结果
**原生数据库操作**
- .raw(”sql语句”),返回值只能做基础操作,如循环索引,不推荐,容易有sql注入的风险
### admin
**注册自定义模型类**
- 需要在`admin.py`下注册导入`admin.site.register(XXX,XXXManager)`,其中`XXXManager`由`admin.ModelAdmin`继承而来
- list_dispalay:数组,展示字段
- list_display_links:数组,选择哪个字段作为修改的跳转字段
- list_filter:数组,可以在右侧展示过滤选项
- search_fields:数组,搜索框,根据设置进行模糊查询、
- list_editable:数组,不用跳转,可直接编辑列表,需要和跳转列表互斥
### 关系映射
- OneToOneField:一对一
- Foreign:一对多
- ManyToManyField:多对多
- 必须设置属性on_delete:级联删除
- models.CASCADE:级联删除,删除包含ForeifnKey的对象
- models.PROTECT:阻止引用对象被删除
- SET_NULL:设置外键为空,需要指定null=True
- SET_DEFAULT
- 反向属性:
- 一对一:被关联的外键类可以通过类名,反向查询自己所关联的类
- 一对多:外键类名.关联类名_set.all()
- 多对多:同第二种
### Cookies&Session
> 保持会话状态的存储技术
>
**Cookies:客户端浏览器上的存储空间**
- 键值对存储,ASCII存储,不能是中文字符串
- 存储数据有生命周期
- 按域存储隔离,不同域之间无法互相访问
- 每次请求都会将Cookie全部数据携带到服务端,如果数据太多,会影响性能,建议尽量精简
![django_设置cookie.png](https://s2.loli.net/2022/02/24/PhAGnakJr4BdbwI.png)
**Session:将所有状态数据存储到服务器,返回给浏览器一个sessionId,以后通过sessionId进行身份验证**
- INSTALL_APPS需要检查是否添加session这个应用
- MIDDLEWARE需要检查是否有session这个中间件
- 在settings.py中设置SESSION_COOKIE_AGE,确定过期时间
![django_设置session.png](https://s2.loli.net/2022/02/24/YLDVrFG89cdbpPB.png)
### 缓存
> 用于存储临时数据。由于视图渲染有一定的成本,数据库查询亦会带来一定的性能消耗,对于低频变动的页面可以考虑使用缓存技术,减少实际渲染的次数,用户拿到响应的时间成本会更低
>
缓存思想:查询缓存看是否有,没有就生成并产生缓存,具有一定时间周期
使用场景:博客列表页、电商产品详情页
- 缓存配置:将复杂的查询结果进行存储,下一次可以直接获得结果
**数据库缓存:**
![django_数据库缓存.png](https://s2.loli.net/2022/02/24/P36VjWlSNeYZQGf.png)
**服务器内存:**
![django_内存缓存.png](https://s2.loli.net/2022/02/24/yhEVliuJswfYgFC.png)
**文件系统缓存(不推荐)**
![django_本地缓存.png](https://s2.loli.net/2022/02/24/MShwXvymQL8nAJZ.png)
- 服务器缓存策略
整体缓存:`from django.views.decorators.cache import cache_page`:cache_page(时间)装饰器,可以写在路由里或者视图函数上,虽然简单,缺点是没有办法指定删除,不是特别方便
局部缓存:`from django.core.cache import cache`,cache.set()、cache.get()、cache.delete()。。。。
- 浏览器缓存策略
- 强缓存:不会从服务器发送请求,直接从缓存中读取资源:
1. 响应头-expires(早期):指定缓存过期时间,是根据服务器时间的一个绝对时间,到什么时候缓存失效
2. 响应头-cache-control(现):是一个相对时间,过多久后缓存失效,浏览器优先使用cache_control
- 协商缓存:强缓存中数据一旦过期,就会跟服务器通信,而对于大的图片、静态文件既不会经常变动,且重新传输会十分消耗资源。协商缓存是浏览器同服务器去协商当前缓存是否可用,如果可用服务器不必返回数据,浏览器继续使用原先的缓存:
1. 响应头-last_modified:最近的修改时间,如果服务器返回该响应头,表示该资源需要协商缓存
2. 请求头-if_modified_since:当缓存到期,浏览器将last_modified作为请求头,与服务器协商,如果服务器返回304[响应体]则代表缓存可以用,200[响应体为最新资源]代表缓存不可用
### 中间件
> 是一个轻量级插件系统,改变全局的输入或输出,通过继承类实现(`django.utils.deprecation.MiddlewareMixin`)
>
- 中间件必须实现其中一个方法或多个:
- process_request:执行路由之前调用,返回None(继续往后)或HttpResponse(直接返回),一般用作请求过滤
- process_view:调用视图函数之前被调用,返回None或HttpResponse
- process_response:响应返回前调用,在每个请求上调用,返回HttpResponse对象
- process_exception:档处理过程中抛出异常时被调用,返回一个HttpResponse
- process_template_response:响应中有render方法时被调用,需要针对相应做二次封装,该返回为提前实现的render方法
- 配置:settings.py `MIDDLEWARE = []`,其中路径为项目路径下存放中间件类的文件地址
- 执行顺序:类似于栈,以视图函数为分界,由注册中间件从上至下,再从下至上
- CSRF攻击:通过浏览器中保存有登录状态的COOKIE,模拟用户发起请求。在Django中CSRF防范通过网页中提交的表单里添加`{%srf_token%}`,让COOKIE和网页表单中拥有两个密钥,请求需要两个都在的时候才会成功。如果希望有些视图不需要csrf校验,可以加上一个装饰器`from django.views.decorators.csrf import csrf_exempt`
### 分页
> `django.core.paginator`
>
- 方便阅读
- 减轻服务端压力
[详细参考](https://docs.djangoproject.com/zh-hans/3.2/topics/pagination/)
```python
def test_page(request):
data = ['a','b','c','d','e']
page_num = request.GET.get('page',1)
paginator = Paginator(data,1)
res = paginator.page(int(page_num))
return render(request,"site1/test_page.html",locals())
```
![django_分页.gif](https://s2.loli.net/2022/02/24/hzXvMjtHsBmoLPy.gif)
```html
{% for r in res %}
{{ r }}
{% endfor %}
<br>
{% if res.has_previous %}
<a href="test_page?page={{ res.previous_page_number }}">上一页</a>
{% else %}
上一页
{% endif %}
{% for i in paginator.page_range %}
{% if i == res.number %}
{{i}}
{% else %}
<a href="test_page?page={{i}}">{{ i }}</a>
{% endif %}
{% endfor %}
{% if res.has_next %}
<a href="test_page?page={{ res.next_page_number }}">下一页</a>
{% else %}
下一页
{% endif %}
```
### 上传文件
- form表单
- 表单中有一个`enctype=“multipart/form-data”`字段
- `<input type=”file” name="fileName">`标签上传文件
- `request.FILE[”fileName”]`
- 上传资源统一为`media资源`,在settings.py文件中需要加上MEDIA_URL(端上访问的路径)和MEDIA_ROOT(本地存的路径),同时为了让该设置生效,需要在路由里添加一个专门的路由,详细参考
```python
from django.conf.urls.static import static
from django.conf import settings
urlpatterns += static(settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT)
```
### 收发邮件
- 协议:
- SMTP:负责邮件发送到服务器,属于推送型协议
- IMAP:从远程服务器拉取邮件,具备摘要浏览功能,是双向协议,客户端操作可以反馈给服务器(归档,标星...)
- POP3:从远程服务器拉取邮件,单向协议,无摘要功能客户端操作无法反馈给服务端
- `from django.core import mail`
### 项目部署
- WSGI(Web Server Gateway Interface)是python应用程序与Web服务之间的一种接口
- uWSGI,功能更加完善,支持协议更多
- 启动:在uwsgi.ini 文件下执行`uwsgi --ini uwsgi.ini`
- 停止:`uwsgi --stop uwsgi.pid`
- 有任何文件修改都要重启uwsgi服务
## 继续学习[https://www.zhihu.com/question/340154278/answer/2186549182](https://www.zhihu.com/question/340154278/answer/2186549182)
Django学习笔记