django-admin startproject 项目名
业务分化,可以优化团队合作,可以明确找锅
python manage.py startapp 子app名
python manage.py runserver
__init__.py
: 声明当前文件夹为一个可导入的包
settings.py
: 整个项目的配置文件
urls.py
: 主控路由映射文件
wsgi.py
: 项目上线时使用的uwsgi服务器的连接文件
manage.py
: 控制管理当前项目
admin.py
: django内置了一个数据库管理工具
models.py
: 数据库,模型类
views.py
: 存储不同
语言 转中文
LANGUAGE_CODE = ‘zh-Hans‘
定义时区
TIME_ZONE = ‘Asia/Shanghai‘
配置模板 在TEMPLATES列表字典中配置DIRS 并手动创建template文件夹
TEMPLATES = [
{
‘DIRS‘: [os.path.join(BASE_DIR,‘template‘)],
}]
谁可以访问我
ALLOWED_HOSTS = ["*"]
配置图片 手动创建static文件夹
STATICFILES_DIRS=(
os.path.join(BASE_DIR,‘static‘),
)
在INSTALLED_APPS中加入子app 否则无法创建数据库模板类
INSTALLED_APPS = [
‘子app名‘,
]
class Student(models.Model):
# 学生名字
name = models.CharField(max_length=30,verbose_name=‘学生名字‘) # 字符串 最大30字符
# 年龄
age = models.IntegerField(default=0,verbose_name=‘年龄‘) # 数字类型 默认为 0岁
from . import models
admin.site.register(models.Student)
1. python manage.py migrate 框架Django有自带的数据表 生成相关数据表
2. python manage.py makemigrations 查找差异 创建迁移文件
3. python manage.py migrate 根据迁移文件 生成数据表及字段
Django所提供用来帮助你管理项目所使用到的数据表的
*注意: 访问之前先创建 框架Django有自带的数据表 也就是 python manage.py migrate
否则会保Django-session的错
python3 manage.py createsuperuser
#提供一个可读性更高的名字
def __str__(self):
return self.name
·为模板页面返回模板变量
- {{ var }} 来自views.py的 var 变量
?
·编写视图函数:
- app -> views.py -> def(request)
- 视图函数操作模型类表
* 让视图函数返回所有学生
* content = models.Student.objects.all()
* return render(request,‘xxx.html‘,locals())
·编写映射关系: 路由映射关系是通过path函数找到对应视图
- 路由映射,必须写末尾的斜杠
- 路由查找,从上到下,匹配的到某一个,直接调用视图函数即可
- 404:页面没找到 403:服务器拒绝 402:保留位 401:用户权限鉴定失败 400:错误的请求
·返回模板页面 == HTML页面
- 配置模板页面的路径,设置一个路径在settings文件下,保存所有的静态目录,TEMPLATES
- 视图函数使用render进行页面渲染并返回
·模板标签:
- 必须要有闭合标签
- 如:{% for i in 迭代对象 %} {% endfor %}
#·css,js,mp3,audio -----》 路径查找: 绝对、相对
#- settings.py ->
STATICFILES_DIRS=(os.path.join(BASE_DIR,‘static‘),)
?
#·在html中上方全局加载
- {% load static %}
有一个数据库:sqlite3 学习使用的轻量级数据库文件
创建表:吧表创建在对应的app下-> models.py
python manage.py makemigrations 查找当前数据库差异,迁移文件
python manage.py migrate 通过迁移文件执行真正的SQL
用户的提交数据方式:get,post request.method == ‘GET‘ or ‘POST‘
明确防跨站请求伪造令牌
—— {% csrf_token %}
request.POST.get(‘表单的name值’) -> 表单-> value
存储数据 models.Student.create(字段=value等等)
request.method # 判断当前用户访问方式
request.method == ‘GET‘
request.method == ‘POST‘
获取表单多值时候,不能使用get函数
我们需要使用getlist 获取多个值
解析到的数据类型为:application/x-www-form-urlencoded,form-data
request.GET:获取GET形式提交的数据
get形式提交的数据
获取ip: request.META:访问的头部信息
REMOTE_ADDR:获取访问者的IP地址
if ‘HTTP_X_FORWARDED‘ in request.META:
ip = request.META.get(‘HTTP_X_FORWARDED‘)
else:
ip = request.META[‘REMOTE_ADDR‘]
#查询数据库ip是否已存在
models.Students.objects.get(ip=IP)
获取文件类型
request.FILES
#例:
path(‘路由字符串/‘, views.index)
path(‘abc/‘, views.index)
将参数做到连接里
路由命名传参:
path(‘index/<str:name>/<int:age>/‘, views.index),
re_path(r‘^index/(?P<name>[a-z]{3})/(?P<age>\d{1,2})/‘,views.index ),
(?P<id>\w+)/
路由非命名传参:更灵活,但是必须对应参数位置
re_path(r‘^index/([a-z]{3})/(\d{1,2})/‘,views.index)
空白符号:\r \n \v \t \b
APP:业务分化,方便团队合作
主路由文件:只做分发
from django.urls import path,re_path,include
urlpatterns = [
path(‘admin/‘, admin.site.urls),
re_path(‘‘,include(‘xue_app.urls‘))
]
子路由文件:需要我们手动创建相关app的urls.py,实现视图映射
from django.urls import path
#导入子app的视图文件
from xue_app import views
#配置子app路由 结尾加 /
urlpatterns = [
path(‘‘, views.index),
path(‘show/‘, views.show),
]
主路由-》子路由-》分发
当路由修改时,如果HTML页面跳转与视图函数重定向使用的是原始的连接内容,那么都需要更改
耦合性太强
现在通过路由反向解析,可以解决这个问题
path(‘‘, views, name=)
html:
href={% url ‘url_name‘ ‘args1‘ ‘args2‘... %}
views:
from django.shortcuts import render,redirect,reverse
redirect(reverse(‘url_name‘,args=(‘args1‘,‘args2‘)))
在路由文件:子路由
app_name 全局变量,一般使用app名作为命名空间名
href={% url ‘app_name:url_name‘ ‘args1‘ ‘args2‘... %}
from django.shortcuts import render,redirect,reverse
redirect(reverse(‘app_name:url_name‘,args=(‘args1‘,‘args2‘)))
用户的提交数据方式:get,post request.method == ‘GET‘ or ‘POST‘
明确防跨站请求伪造令牌 {% csrf_token %}
视图函数判断请求方式 POST
request.POST.get() -> 表单 -> value值
存储数据 models.Student.create(字段=value等等)
{{ var|add:1 }}
add:过滤器名字
参数:var、1
模板过滤器最多只能接收两个参数,必须要有一个参数:1~2
将当前app注册到settings->INSTALL_APPS
在app目录下创建templatetags
文件夹,用来保存所有的过滤器文件
在templatetags文件夹下创建一个__init__.py
文件,声明当前文件夹为一个可导入的包
在templatetags文件夹下创建一个你的.py文件,用来保存对应的过滤器函数
导入from django.template import Library
需要在这个文件下有一个全局变量名为:register = Library()
编写过滤器函数
注册函数为真正过滤器
@register.filter(name=‘your_func‘)
模板页面要想使用自定义过滤器,首先导入过滤器文件:{% load youfilter %}
{{ var|your_func}}
与自定义过滤器一个文件夹下即可
@register.simple_tag(name=‘‘)
首先在模板文件夹下定义一个base.html
可以在子模版中,通过最顶部使用{% extends ‘base.html‘ %}引入过来
在base.html的父模板页面中可以使用{% block title %}{% endblock %}指明块
父模板中没有的块,在子模版中强行加入,是不会被渲染出来的
思考:解决了什么问题?HTML代码编写时,更精简,复用性更高
使用{% include %} 标签将额外编写的组件HTML代码加载进来
可以实现HTML代码的复用,解耦和
节约代码量,使HTML干净整洁
# 找到DATABASES
DATABASES = {
‘default‘: {
‘ENGINE‘: ‘django.db.backends.sqlite3‘,
‘NAME‘: os.path.join(BASE_DIR, ‘db.sqlite3‘),
}
}
# 注掉上面 变更为
DATABASES = {
‘default‘: {
‘ENGINE‘: ‘django.db.backends.mysql‘, # 数据库引擎
‘NAME‘: "django_data", # 使用的数据库库名,该库需要手动创建
"USER": "root", # 自己的用户名
"PASSWORD": "chenkai", # 自己的数据库密码
"HOST": "172.16.19.49", # 数据库主机地址 自己的本地ip
"PORT": "3306" # mysql的端口号
}
}
进入MySQL的bin目录,执行如下命令:
#登录mysql
mysql -u 用户名 -p密码
# 进入mysql配置
user mysql;
# 变更配置
update user set host = ‘%‘ where user = ‘root‘;
# 给出 特权 Ps:让他可以这么做
flush privileges;
?
查询:
表层面:
查询所有是教授的老师 英雄为母表 ADC为子表
子表 有一个继承母表市局的字段(正向查询),同样母表也有一个隐藏的小写子表表名字段用来查询子表的数据(反向查询)
母表.objects.filter(小写子表名__子表特有字段__gt=0) ------》 反向查询
用的是隐藏起来哪个关联表字段进行查询 就是反向查询
子表名.继承母表字段名 ---》 正向
数据层面
m1 = 子表.objects.get() ---》反向m1.继承母表的变量字段 ----》 正向
小写子表名 不是一条m1的字段,他是django做出来隐藏的
#英雄 --》 ADC(为子表)
#增
a1 = models.Hero.objects.create(name=‘黄忠‘)
a2 = models.Skill.objects.create(kill=a1,skill=‘百步穿杨‘)
#查
b1 = models.Hero.objects.get(name=‘黄忠‘)
b2 = models.Skill.objects.get(kill=b1)
#改
b2.skill=‘一箭狙神‘
b2.save()
#删
b2.delete()
数据层面
老师结果.student_set.all()
-----》 反向
_set
== models.objects
根据外键 查询 ---》 正向
表层面:
Teacher.objects.filter(student__name__startswith=‘贾‘)
---》 反向
Student.objects.filter(tea__name=‘贾老师‘)
---》 正向
修改
单独修改简单:直接字段赋值,save() 即可
批量修改
结果集.update(tea=要变更的值)
直接为这些set数据 批量修改
直接立竿见影到数据库,不需要save
删除:
on_delete =
models.CASCADE
:老师删除,球员也跟着消失,外键绑定
models.SET_NULL
:老师删除,球员外键为null,数据还在,外键关系消失
null=True
blank=True
开启一个包含当前项目所有环境的命令行工具命令: python manage.py shell
例:终端在manage.py 同级目录下:python manage.py shell
表关系 学生 ---》 老师
from s_app import models
a1 = models.Teacher.objects.create(name=‘李老师‘)
a2 = models.Teacher.objects.create(name=‘贾老师‘)
a1
<Teacher: 李老师>
a2
<Teacher: 贾老师>
q1 = models.Student.objects.create(tea=a1,name=‘张小宁‘)
q2 = models.Student.objects.create(tea=a1,name=‘贾小璇‘)
q3 = models.Student.objects.create(tea=a2,name=‘李小括‘)
q4 = models.Student.objects.create(tea=a2,name=‘潘小飞‘)
q1
<Student: 张小宁>
q2
<Student: 贾小璇>
q3
<Student: 李小括>
q4
<Student: 潘小飞>
q1.tea.name
‘李老师‘
c1 = models.Student.objects.filter(tea__name=‘贾老师‘)
c1
<QuerySet [<Student: 李小括>, <Student: 潘小飞>]>
c2 = models.Teacher.objects.filter(student__name=‘潘小飞‘)
c2
<QuerySet [<Teacher: 贾老师>]>
# 把潘小飞调给李老师教
q4.tea.name = ‘李老师‘
q4.save()
q4.tea.name
‘李老师‘
把所有同学调给贾老师教
l = models.Student.objects.filter(tea=a1)
j = models.Student.objects.filter(tea=a2)
l.update(tea=a2)
结果集.直接delete()
#删除张小宁
q1.delete()
#批量删除贾老师所有学生(将一个数据集直接删除)
j.delete()
ManyToManyField
字段定义? 数据保留,外键关系消失,删除和添加只影响外键关系
? add
-----》 例: 子表结果.关联字段.add(某结果集[0],某结果集[3],某结果集[6],)
remove
-----》 例: 子表结果.关联字段.remove(某结果集[0],某结果集[3],某结果集[6],)
? 结果/结果集.delete()
数据层面 :针对某些特定字段数据进行查询 ---> (反向查询:关联表_set
)
正向
子表结果.关联字段.all()
反向
母表结果.隐藏小写子表名字段__set.all()
表层面 : 针对的是整张表的数据 ---> (反向查询:直接使用小写关联表名
)
正向
子表.objects.filter(关联字段__子表某字段=‘一个指定结果’)
反向
母表.objects.filter(隐藏的小写子表名__子表某字段=‘一个指定结果’
什么是cookie?
类似令牌一样的东西,用来把每次客户端访问服务端的数据信息提交给我
request 获取
response 设置
明文传输,极度不安全
默认有效期:随客户端关闭而消失
每个HttpRequest
对象都对应一个COOKIES
对象,该对象是字典形式.
request.COOKIES[‘session变量名‘] # 获取
对COOKIES的设置通过一个页面HttpResponse
对象的set_cookie
HttpResponse.set_cookie(key, value=‘‘, max_age=None, expires=None, path=‘/‘, domain=None, secure=None, httponly=False)
#语法: 页面.set_cookie(‘session变量名‘,session的值) # 设置 session值
delete_cookie[‘session变量名‘]
通过 set_signed_cookie
函数进行持有签名的 COOKIE 值设置,避免用户在客户端进行修改
要记得,这个函数并不是对 COOKIE 值进行加密
HttpResonse.set_signed_cookie(key, value, salt=‘‘, max_age=None, expires=None, path=‘/‘,
domain=None, secure=None, httponly=True)
为 cookie 值添加签名,其余参数与 set_cookie
相同
Request.get_signed_cookie(key, salt=‘‘, max_age=None)
从用户请求中获取通过salt盐值加了签名的 Cookie 值。 这里的 salt 要与之前存储时使用的 salt 值相同才可以解析出正确结果。 还要注意的是,如果对应的key值不存在,则会引发KeyError
异常,所以要记得异常捕获来确定是否含 有 Cookie 值
def check_salt_cookie(request): try: salt_cookie = request.get_signed_cookie(key=‘salt_cookie‘,salt=‘nice‘) except KeyError: #获取不到该key值的Cookie response = HttpResponse(‘正在设置一个salt Cookie值‘) response.set_signed_cookie(key=‘salt_cookie‘,salt=‘nice‘,value=‘salt_cookie‘) return response else: #获取到了对应key值,展示到新的HttpResonse中 return HttpResponse(‘获取到的salt Cookie值:%s‘ % salt_cookie)
? 第一次访问的时候,还没有加 Cookie 值,所以我们在获取的时候会抛出 KeyError 异常
? 此时捕获异常,并且设置 Cookie 即可;
? 再次刷新的时候,因为这里已经给出了 Cookie 值,则不会引发异常,会在页面中展示获取到的加盐 cookie
? 什么是session?
session是基于cookie的,在网络中,又称会话控制,简称会话。用以存储用户访问站点时所需的信息及配置属性。当用户在我 们的 Web 服务中跳转时,存储在 Session 中的数据不会丢失,可以一直在整个会话过程中存活。
在 django
中,默认的 Session 存储在数据库中session
表里。默认有效期为两个星期。
加密传输 更安全
客户端访问服务端,服务端为每一个客户端返回一个唯一的 sessionid ,比如 xxx 。
客户端需要保持某些状态,比如维持登陆。那么服务端会构造一个 {sessionid: xxx } 类似这样的字典数据加 到 Cookie 中发送给用户。注意此时,只是一个随机字符串,返回给客户端的内容并不会像之前一样包含实际数 据。
服务端在后台把返回给客户端的 xxx 字符串作为 key 值,对应需要保存的服务端数据为一个新的字典,存储在 服务器上,例如: {xxx : {id:1}}
session_data = request.session.get(Key)
session_data = request.session[Key]
ession_data = request.session.get(Key)
session_data = request.session[Key]
del request.seesion[Key]
删除对应session, Key 值不存在时,引发 KeyError
request.session.clear()
清空 Session 中的所有数据。这里客户端还会保留 sessionid 只不过在服务端 sessionid 对应的数据没有了。
request.session.flush()
INSTALLED_APPS = ( ... ‘django.contrib.sessions‘, ... )
MIDDLEWARE_CLASSES = ( ‘django.contrib.sessions.middleware.SessionMiddleware‘, ... )
直接删除当前客户端的的Seesion
数据。这里不光服务端sessionid
对应的数据没有了,客户端的 sessionid
也会被删除
原文:https://www.cnblogs.com/canhun/p/10964089.html