基础架构部文档
基础架构部文件格式标准参考
技术文档
mr_doc 接入ucenter 认证登录
loki日志收集
https证书与ssl/tls 加密
FTP 主动模式和被动模式的区别
Hadoop-windows10安装部署Hadoop2.7.3
JKS和PFX证书文件格式相互转换方法
KVM 基础操作
k8s nginx ingress日志收集到ELK并分析
Django基础
clash http代理 socks代理服务器搭建 配置
Ubuntu 22.04 安装 FFmpeg v7.0
Office正版化项目的个人体验和心得
重置jenkins构建历史
K8S实施方案
k8s的yaml文件语法
Docker的优势与虚拟机的区别
问题处理文档
HR推送数据问题处理报
Nginx从入门到放弃01-nginx基础安装
Nginx从入门到放弃02-Nginx基本命令和新建WEB站点
Nginx从入门到放弃03-Nginx调优
Nginx从入门到放弃04-Nginx的N种特别实用示例
JMeter教程
01-mariadb编译安装
02-mariadb二进制安装
Docker修改默认的存储路径
01-influxdb2时序数据库简介及安装
02-influxdb2时序数据库核心概念
03-influxdb2时序数据库flux查询语言
04-influxdb2--Python客户端influxdb-client
05-Spring boot 集成influxdb2
06-influxdb2其他知识
OA添加waf后相关问题的解决过程
排除java应用cpu使用率过高
exsi迁移文档
视频测试
阿里云产品试题
超融合服务器和传统服务器的区别
Serv-U问题集锦
文件夹共享操作手册
磁盘脱机处理方案
Office内存或磁盘空间不足处理方法
Cmd中ping不是内部或外部命令的解决方法
ELK 搭建文档
限制用户的远程桌面会话数量
Docker快速安装rocketmq、redis、zookeeper
超融合建设方案
git 入门
HR系统写入ES数据报错403
ELK搭建文档
KVM 安装和基础使用文档
helm 安装 rancher
访问共享提示禁用当前用户解决方法
K8S StorageClass搭建
KVM 扩展磁盘
借助sasl构建基于AD用户验证的SVN服务器
fastdfs编译安装并迁移数据
关闭系统保护的必要性
SCF 前置机部署
阿里云OSS学习文档
阿里云学习文档-VPC
(k8s踩坑)namespace无法删除
rancher-helm安装
zookeeper集群安装
批量替换K8s secrets 中某个特定域名的tls证书
kibana 批量创建索引模式
centos7 恢复Yum使用
ACP云计算部分知识点总结
Loki 日志系统搭建文档
自动更新k8s集群中所有名称空间中特定证书
AI分享
(AI)函数调用与MCP调用的区别
安装戴尔DELL Optilex 7040 USB驱动时提示无法定位程序输入点 kernel32\.dll
新华三服务器EXSI 显卡直通
本文档使用「觅思文档专业版」发布
-
+
首页
Django基础
# Django ### 基本概念 Django 是一个由 Python 编写的一个开放源代码的 Web 应用框架,用于快速开发可维护和可扩展的 Web 应用程序,只要很少的代码,就可以轻松地完成一个正式网站所需要的大部分内容,并进一步开发出全功能的 Web 服务。其本身基于 MVC 模型,即 Model(模型)+ View(视图)+ Controller(控制器)设计模式,MVC 模式使后续对程序的修改和扩展简化,并且使程序某一部分的重复利用成为可能。 ### 特点 - **ORM(对象关系映射):** Django 提供了一个强大的 ORM,允许开发者通过 Python 代码来定义和操作数据库模型,而无需直接使用 SQL。这使得数据库操作更加抽象和易于管理。 - **MVC 架构:** Django 遵循 MVC(模型-视图-控制器)的软件设计模式,但它使用了稍微不同的术语。在 Django 中,模型(Model)表示数据结构,视图(View)负责呈现用户界面,而控制器(Controller)的职责被称为视图(View)。 - **模板引擎:** Django 使用模板引擎来生成 HTML,这使得前端和后端的代码分离更加容易。Django 的模板语言允许开发者在模板中嵌入动态内容。 - **自动化 admin 界面:** Django 自动生成管理后台,使得管理和操作数据库的过程变得非常简单。开发者可以轻松地创建、修改和删除数据库记录,而无需编写自定义的管理界面。 - **表单处理:** Django 提供了强大的表单处理工具,使得用户输入的验证和处理变得更加简单。这对于开发 Web 表单和处理用户提交的数据非常有用。 - **安全性:** Django 内置了一些安全性功能,例如防止常见的 Web 攻击(如 CSRF 攻击),并提供了方便的用户身份验证和授权系统。 - **可扩展性:** Django 的组件是松耦合的,允许开发者使用现有的组件或编写自己的应用程序来扩展框架功能。 - **社区支持:** Django 拥有庞大的社区支持,提供了大量的文档、教程和第三方包,使得学习和使用 Django 变得更加容易。 ### 项目目录结构 ---settings.py 配置文件 --urls.py 路由与视图对应关系(路由层) --wsgi.py wsgiref模块(不考虑) --mannage.py django入口文件 --db.sqlite3 django自带的sqlite3小型数据库 --admin.py django后台管理 --apps.py 注册使用 --migrations文件夹 数据库迁移记录 --models.py 数据库相关的模型类(orm) --tests.py 测试文件 --views.py 视图函数(视图表) ### 实例创建 1、HttpResponse #返回字符串 2、render #返回HTML页面 3、redirect #重定向 新建项目之后需要修改setting.py文件  #### 1.项目静态文件配置 在setting,py文件最后添加 ```python STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static') ] ``` 静态文件解析: 在前端页面<head>里添加 ```python {% load static %} <link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}"> <script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script> ``` 前期在使用Django提交post请求时,需在setting.py中注释掉一行代码  #### 2.request对象方法初识: ```python request.method # 返回请求方式,并且全是大小写的字符串形式 request.POST # 获取用户post请求提交的普通数据,不包含文件 request.POST.get() # 只获取列表最后一个元素 request.POST.getlist() # 直接将列表取出 request.GET # 获取用户get请求提交的数据 request.GET.get() # 只获取列表最后一个元素 request.GET.getlist() # 直接将列表取出 """ get请求携带的数据是有大小限制的 post请求则没有限制 """ ``` #### 3、Django链接数据库(setting.py) ```python DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'test', 'USER': 'root', 'PASSWORD': '123456', 'HOST': '127.0.0.1', 'PORT': 3306, 'CHARSET': 'utf8' } } 代码声明 Django默认使用MySQLdb模块链接MySQL,需手动改为pymysql模块链接 在项目名下的init文件或任意应用名下的init文件中修改都可 import pymysqltest pymysql.install_as_MySQLdb() 出现报错将错误文件中的 decode→encode ``` #### 4、Django ORM ```python """ ORM 对象关系映射 类 表 对象 记录 对象属性 记录某个字段的值 """ 1.先在应用下面的models.py文件书写一个类 class User(models.Model): # id int primary_key auto_increment id = models.AutoField(primary_key=True) # username varchar(32) username = models.CharField(max_length=32) # CharField必须指定max_length # password varchar(32) password = models.CharField(max_length=32, verbose_name='密码') # verbose_name参数是所有字段都有,用来对解释字段 2.**********************************数据库迁移************************************ python manage.py makemigrations # 将操作记录写在migrations文件夹下 python manage.py migrate # 将操作真正同步到数据库中 # 只要修改了model.py文件中跟数据库相关的代码,就需要重新执行上述代码 ******************************************************************************** 当没有定义主键时,orm会自动帮你创建一个名为id的主键 ``` ##### 4.1字段的增删改 ```python # (一)字段的增加 # 1.可以在终端直接给出默认值 # 2.将该字段设置为可以为空 info = models.CharField(max_length=32, verbose_name='信息', null=True) # 3.直接给字段设置默认值 hobby = models.CharField(max_length=32, verbose_name='爱好', default='study') # (二)字段的修改 直接修改字段后执行数据库迁移的两条命令即可 # (三)字段的删除 直接注释字段后执行数据库迁移的两条命令即可 ``` ##### 4.2数据的增删改查 ```python # (一)查 res = models.User.objects.filter(username=username) print("res") """ 返回值是列表套字典的形式 支持索引取值 切片操作 但是不支持负数索引 不推荐使用索引的方式取值 user_obj = models.User.objects.filter(username=username).first() """ filter括号内可以携带多个参数,可以当做SQL语句中的where # 查所有数据 # 方式1 # data = models.Reg.objects.filter() # print(data) # 方式2 user_queryset = models.User.objects.all() return render(request, 'userlist.html', locals()) # (二)增 res = models.Reg.objects.create(username=username, password=password, confirm=confirm) # 返回值,即当前被创建对象本身 print(res.username, res.password, res.confirm) # 第二种增加 reg_obj = models.Reg(username=username, password=password, confirm=confirm) reg_obj.save() ``` ##### 4.3如何创建表关系 ```python class Book(models.Model): title = models.CharField(max_length=32, verbose_name='书本名称') # 总共8位 小数后保留2位 price = models.DecimalField(max_digits=8, decimal_places=2, verbose_name='书本价格') # 图书和出版社是一对多,并且书是多的一方,所以外键字段放在书表里 # 默认与出版社表的主键作关联 publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE) # 图书和作者是是多对多的关系,外键字段在任意方即可,但推荐建在查询频率高的一方 # author是一个虚拟字段,主要是用来告诉orm书籍表和作者表是多对多的关系,让orm自动帮你创建第三张关系表 author = models.ManyToManyField(to='Author') class Publish(models.Model): name = models.CharField(max_length=32, verbose_name='出版社名') address = models.CharField(max_length=32, verbose_name='出版社地址') class Author(models.Model): name = models.CharField(max_length=32, verbose_name='作者名称') age = models.IntegerField(verbose_name='年龄') # 作者与作者详情表是一对一的关系,外键建在任意一方都可以 author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE) class AuthorDetail(models.Model): phone = models.BigIntegerField(verbose_name='电话号码') hobby = models.CharField(max_length=32, verbose_name='爱好') 注意: 1.django升级到2.0之后,表与表之间关联的时候,必须要写on_delete参数,否则会报异常 2.由于多对多(ManyToManyField)没有 on_delete 参数,所以以上只针对外键(ForeignKey)和一对一(OneToOneField) 3.ForeignKey,OneToOneField会自动在字段后加_id ``` #### 5、Django请求生命周期流程图  ```python """ web服务网关接口 1.请求来的时候解析封装 响应走的时候打包处理 2.django默认的wsgiref模块不能承受高并发 最大只有1000左右 上线之后会自动替换成uwsgi来增加并发量 3.WSGI跟wsgiref和uwsgi之间的关系 WSGI是协议 wsgiref和uwsgi是实现该协议的功能模块 django后端 1.django中间件 类似于django的门户 2.urls.py 路由层 识别路由匹配对应的视图 3.views.py 视图层 网站整体的业务逻辑 4.templates文件夹 模板层 网站所有的HTML文件 5.models.py 模型层 ORM 额外扩展: 缓存数据库: 提前将想要的数据准备好,提高效率和响应时间 """ ``` #### 6.反向解析 ```python # 先给路由与视图函数起一个别名 path('jump/', views.func, name='ddd') # 反向解析 # 后端反向解析 from django.shortcuts import reverse def xxx(request): print(reverse('ddd')) # 前端反向解析 <a href="{% url 'ddd' %}">111</a> # 别名不能冲突 ``` #### 7.路由分发 ```python """ django的每一个应用都可以有自己的templates文件夹、urls.py、static文件夹 基于此特点 Django可以很好的做到分组开发 只需要将书写的APP全部拷贝到一个新的Django目录下,然后在配置文件中注册所有的APP,再利用路由分发的特点将APP整合起来 当一个Django项目中的url特别多的时候,总路由urls.py的代码非常冗余,不好维护 这个时候也可以利用路由分发来减轻总路由的压力 # 总路由 from django.contrib import admin from django.urls import path, include from app01 import urls as app01_urls from app02 import urls as app02_urls urlpatterns = [ path('admin/', admin.site.urls), # 路由分发 # 方法一 path('app01/', include(app01_urls)), # 只要url前缀是app01开头,全部交由app01处理 path('app02/', include(app02_urls)), # 只要url前缀是app02开头,全部交由app02处理 # 方法二 推荐使用 path('app01/', include('app01.urls')), path('app02/', include('app02.urls')) ] # 分路由 # app01.urls from django.urls import path from app01 import views urlpatterns = [ path('login/', views.login) ] #app02.urls from django.urls import path from app02 import views urlpatterns = [ path('login/', views.login) ] """ ``` #### 8.伪静态 ```python """ 静态网页 数据是写死的 不会变化 伪静态 将一个动态网页伪装成静态网页 目的在于增大本网站的的seo查询力度,并增加搜索引擎收藏本网上的概率 """ urlpatterns = [ path('reg.html', views.reg) ] ``` #### 9.虚拟环境 相当于新建一个纯净的Python解释器,需要什么模块就装什么模块  #### 10.Django1.x和Django2.x的区别 ```python """ Django1.x路由层使用的是url方法 而在Django2.x和3.x中使用的是path方法 url()第一个参数支持正则匹配 path()第一个参数不支持正则匹配,些什么就就匹配什么 2.x和3.x中的re_path()等价于1.x中的url() from django.urls import re_path re_path(r'^index/', views.index) 模型层里的外键1.x版本默认都是级联更新删除的 但在2.x和3.x版本中需要手动配置 1.x: models.ForeignKey(to='Publish') 2.x: models.ForeignKey(to='Publish', on_delete=models.CASCADE) """ ``` #### 11.视图层 ```python # 视图函数必须要返回一个HttpResponse对象 # render简单内部原理 from django.template import Template,Context res = Template('<h1>{{ user }}</h1>') con = Context({'user:{'username':'jason','password':'123'}'}) ret = res.render(con) print(ret) return HttpResponse(ret) ``` #### 12.JsonResponse ```python """ json格式数据的作用: 前后端数据交互需要用到json作为过渡 实现跨语言传输数据 前端序列化 JSON.stringify() json.dump() JSON.parse() json.loads() """ import json from django.http import JsonResponse def ab_json(request): user_dict = {'username:': 'tank强壮', 'password': '123', 'hobby': 'music'} # 序列化字典方法一 json_str = json.dumps(user_dict, ensure_ascii=False) return HttpResponse(json_str) # 序列化字典方法二 return JsonResponse(user_dict, json_dumps_params={'ensure_ascii': False}) # 序列化列表 l = [111, 222, 333, 444, 555] return JsonResponse(l, safe=False) # 默认只能序列化字典,序列化其他需要加safe参数 ``` #### 13.form表单上传文件 ```python def ab_file(request): if request.method == 'POST': print(request.POST) # 只能获取到普通的键值对数据,文件不行 print(request.FILES) # 获取文件数据 file_obj = request.FILES.get('file') # 文件对象 print(file_obj.name) with open(file_obj.name, 'wb') as f: # 保存文件 for line in file_obj.chunks(): f.write(line) return render(request, 'file.html') ``` #### 14.request对象方法 ```python """ request.method request.POST request.GET request.FILES request.body 原生的浏览器发过来的二进制数据 request.path request.get_full_path() """ print(request.path) # 只能获取到路由 /app01/ab_file/ print(request.get_full_path()) # 能获取到路由后面的完整参数 /app01/ab_file/?username=json ``` #### 15.FBV(function based view)与CBV(class based view) ```python # 视图函数可以是函数也可以是类 # FBV def login(request): return HttpResponse("app01:login") # CBV # CBV路由 path('index/', views.MyLogin.as_view()) from django.views import View class MyLogin(View): def get(self, request): return render(request, 'file.html') def post(self, request): return HttpResponse("post方法") """ FBV与CBV各有千秋 CBV特点: 能够直接根据请求方式的不同直接匹配到对应的方法执行 """ ``` #### 16.CBV源码剖析 ```python # 突破口在urls.py path('login/', views.MyLogin.as_view()) # CBV与FBV在路由匹配的本质上是一样的 都是路由 对应 函数内存地址 # path('login/', views.view) 与FBV一模一样 """ 函数名/方法名加括号的执行优先级最高 as_view()是被@classmethod修饰的类方法 """ @classonlymethod def as_view(cls, **initkwargs): def view(request, *args, **kwargs): self = cls(**initkwargs) # cls就是我们自己写的类 # self = MyLogin(**initkwargs) # 产生一个我们自己写的类的对象 return self.dispatch(request, *args, **kwargs) """ 面向对象属性方法查找顺序: 先从对象本身找 再从产生对象的类里面找 之后再去父类找 看源码看到self点一个东西,首先要清楚当前这个self是谁 """ return view def dispatch(self, request, *args, **kwargs): if request.method.lower() in self.http_method_names: handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed return handler(request, *args, **kwargs) ``` #### 17.模板语法传值 {{}}:变量相关 {%%}:逻辑相关 传递函数名会自动加括号调用 但是模板语法不支持给函数传额外的参数 传类名的时候也会自动加括号调用(实例化) 内部能够自动判断出当前的变量名是否可以加括号调用 如果可以就会自动执行 针对的是函数名和类名 ```python def index(request): n = 123 f = 123.45 s = "闸口" b = True l = ['小红', '小李', '小芳', '小孩'] t = (111, 333, 222, 444) d = {'username': 'yh', 'password': '123', 'hobby': [111,222,333, {'gp': 'NB'}]} se = {'贝贝', '晶晶', '欢欢'} def func(): print('被执行了') return '桃花朵朵开' class MyClass(object): def get_self(self): return 'self' @staticmethod def get_func(): return 'func' @classmethod def get_class(cls): return 'cls' obj = MyClass() return render(request, 'index.html', locals()) <p>{{ n }}</p> <p>{{ f }}</p> <p>{{ s }}</p> <p>{{ b }}</p> <p>{{ l }}</p> <p>{{ t }}</p> <p>{{ d }}</p> <p>{{ se }}</p> <p>{{ func }}</p> <p>{{ obj }}</p> <p>{{ obj.get_class }}</p> <p>{{ obj.get_func }}</p> <p>{{ obj.get_self }}</p> # Django模板语法取值是固定的格式,只能采用句点符"." <p>{{ l.0 }}</p> <p>{{ d.hobby.3.gp }}</p> # 既可以点键,也可以点索引,也可以两者混用 ``` #### 18.过滤器 ```python # 类似于模板语法的内置方法 # 基本语法 {{ 数据|过滤器:参数 }} <h1>过滤器</h1> <p>统计长度:{{ s|length }}</p> <p>默认值(第一个参数布尔值是True就展示第一个参数的值否则就展示冒号后面的值):{{ b|default:'啥也不是' }}</p> <p>文件大小:{{ file_size|filesizeformat }}</p> <p>日期格式化:{{ current_time|date:'Y-m-d H:i:s' }}</p> <p>切片操作(支持步长):{{ l|slice:'0:4:3' }}</p> <p>切取字符(包含三个点,1.x算三个字符,2.x和3.x版本三个点算一个字符):{{ s|truncatechars:10 }}</p> <p>切取单词(不包含三个点,按空格切):{{ info|truncatewords:10 }}</p> <p>移除特定字符:{{ info|cut:' ' }}</p> <p>拼接字符:{{ l|join:'&' }}</p> <p>拼接字符(加法):{{ n|add:10 }}</p> <p>拼接字符:{{ s|add:info }}</p> <p>转义:{{ www|safe }}</p> <p>转义:{{ res }}</p> # 转义 # 前端 |safe # 后端 from django.utils.safestring import mark_safe res = mark_safe('<h1>羽河</h1>') """ 在写全栈项目的时候,前端代码不一定非要在前端页面书写,也可以先在后端写好然后传递给前端 """ ``` #### 19.标签 ```python # for循环 <h1>标签</h1> {% for pet in l %} <p>{{ pet }}</p> {% endfor %} # if判断 {% if b %} <p>baby</p> {% elif s %} <p>come on</p> {% else %} <p>old</p> {% endif %} # 混合使用 {% for foo in l %} {% if forloop.first %} <p>第一个数据</p> {% elif forloop.last %} <p>最后一个数据</p> {% else %} <p>{{ foo }}</p> {% endif %} {% endfor %} """ 第一个数据 小李 小芳 小孩 贝贝 晶晶 最后一个数据 """ # 处理字典的其他方法 {% for foo in d.keys %} <p>{{ foo }}</p> {% endfor %} {% for foo in d.values %} <p>{{ foo }}</p> {% endfor %} {% for foo in d.items %} <p>{{ foo }}</p> {% endfor %} """ username password hobby yh 123 [111, 222, 333, {'gp': 'NB'}] ('username', 'yh') ('password', '123') ('hobby', [111, 222, 333, {'gp': 'NB'}]) """ # with起别名 {% with d.hobby.3.gp as nb %} <p>{{ nb }}</p> <p>在with语法内就可以通过as后面的别名快速使用到获取方式复杂的数据</p> {% endwith %} ``` #### 20.自定义过滤器、标签以及inclusion_tag ```python """ 步骤: 1.先在应用下创建一个名字为“templatetags”文件夹 2.在该文件夹下创建任意名称的.py文件 3.在该py文件下必须先写如下两句话: from django import template register = template.Library() """ # 自定义过滤器(参数最多有两个) mytags.py from django import template register = template.Library() @register.filter(name='count') def my_sun(n1, n2): return n1 + n2 # 使用 {% load mytags %} <p>{{ n|count:666 }}</p> # 自定义标签(参数可以有多个) @register.simple_tag(name='plus') def show(a, b, c, d): return '%s-%s-%s-%s'%(a,b,c,d) # 使用 {% load mytags %} <p>{% plus 'yh' 'tm' 'zdy' 123 %}</p> # 标签多个参数之间彼此空格隔开 # 自定义inclusion_tag """ 内部原理: 先定义一个方法 在页面上调用此方法,还可以传值 该方法会生成一些数据并传递给一个HTML页面 之后将渲染好的结果放到调用 """ # 自定义inclusion_tag @register.inclusion_tag('menu.html') def left(n): data = ['第{}项'.format(i) for i in range(n)] # 第一种 return {'data': data} # 第二种 return locals() # 将data传递给menu.html menu.html <ul> {% for foo in data %} <li>{{ foo }}</li> {% endfor %} </ul> index.html {% left 10 %} # 总结:当HTML页面某一个地方的页面需要传参数才能够动态地渲染出来,并且在多个页面上都需要使用到该局部,那么久考虑将该局部页面做成inclusion_tag形式 ``` #### 21.模板的继承 ```python # 用于页面设计时,总体框架不变,只改变局部 {% extends 'home.html' %} # 继承模板 # 对于需要修改的部分,先在原模板中划定可以修改的区域 {% block content %} 模板内容 {% endblock %} # 子页面就可以对划定的区域进行修改,用法与划定相同 {% block content %} 子页面内容 {% endblock %} # 一般情况下模板页面上至少有三块可以被修改的区域 1.css区域 2.html区域 3.js区域 {% block css %} {% endblock %} {% block content %} {% endblock %} {% block js %} {% endblock %} # 这样每个子页面都可以有自己独有的css代码 html代码 js代码 """ 模板的页面上划分的区域越多,那么该模板的扩展性越强,但不宜太多 """ ``` #### 22.模板的导入 ```python """ 将页面的某一个局部当成模块的形式 哪个地方需要就可以直接导入使用即可 """ {% include '.html' %} ``` #### 23.测试脚本 ```python """ 当只是想测试Django中某一个py文件的内容,直接写一个测试脚本即可 """ # 测试环境的准备 拷贝manage.py中的前四行代码 然后添加两行代码 import os import sys def main(): os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Day64.settings') import django django.setup() # 在这个代码块的下面就可以测试Django的单个py文件了 from app01 import models # 增 reg = models.User.objects.create(name='yh', age=20, register_time='2022-4-13') print(reg) import datetime ctime = datetime.datetime.now() user_obj = models.User(name='xyh', age=24, register_time=ctime) user_obj.save() # 删 reg = models.User.objects.filter(pk=2).delete() print(reg) """ pk会自动查找到当前表的主键字段 指代的就是当前表的主键字段 用了pk之后就不需要知道当前表的主键字段是什么了 """ user_obj = models.User.objects.filter(pk=3).first() user_obj.delete() # 改 models.User.objects.filter(pk=4).update(name='zdy') user_obj = models.User.objects.get(pk=5) user_obj.name = 'zxy' user_obj.save() """ get方法返回的直接就是当前数据对象 但是该方法不推荐使用 一旦数据不存在就会报错 而filter则不会 """ if __name__ == '__main__': main() ``` #### 24.必知会13条 ```python # 必知会13条 # 1.all() 查询所有数据 # 2.filter() 带有过滤条件 # 3.get() 直接拿数据对象,若不存在则直接报错 # 4.first() 拿queryset里面的第一个数据 res = models.User.objects.all().first() print(res) # 5.last() 拿queryset里面的最后一个数据 # 6.values() 可以指定获取的数据的字段,返回结果是列表套字典 res = models.User.objects.values('name') # <QuerySet [{'name': 'yh'}, {'name': 'zdy'}, {'name': 'zxy'}]> print(res) # 7.values_list() 可以指定获取的数据的字段,返回结果是列表套元组 res = models.User.objects.values_list('name', 'age') # <QuerySet [('yh', 20), ('zdy', 20), ('zxy', 24)]> print(res) # 8.distinct() 去重 res = models.User.objects.values('name', 'age').distinct() print(res) """ 去重一定是一模一样的数据 如果带有主键那么肯定不一样 在查询中一定不能忽略主键 """ # 9.order_by() 排序 res = models.User.objects.order_by('age') # 默认升序 res = models.User.objects.order_by('-age') # 降序,在字段前加一个负号 print(res) # 10.reverse() 反转,前提需要数据已经排过序了 res = models.User.objects.all() res1 = models.User.objects.order_by('age').reverse() print(res, res1) # 11.count() 统计当前数据的个数 res = models.User.objects.count() print(res) # 12.exclude() 排除在外 res = models.User.objects.exclude(name='yh') print(res) # 13.exists() 判断数据是否存在,返回布尔值 res = models.User.objects.filter(pk=5).exists() print(res) ``` #### 25.双下划线查询 ```python # 双下划线查询 # 1.年龄大于25岁的数据 res = models.User.objects.filter(age__gt=25) print(res) # 2.年龄小于25岁的数据 res1 = models.User.objects.filter(age__lt=25) print(res1) # 3.大于等于 小于等于 res2 = models.User.objects.filter(age__gte=24) print(res2) # 4.或者 res3 = models.User.objects.filter(age__in=[20, 24, 32]) print(res3) # 5.区间 首尾都要 res4 = models.User.objects.filter(age__range=[20, 32]) print(res4) # 6.字段里包含某个字符 模糊查询 res5 = models.User.objects.filter(name__contains='y') print(res5) # 忽略大小写 res6 = models.User.objects.filter(name__icontains='y') print(res6) # 查询注册时间 按照年份或月份来查询 res7 = models.User.objects.filter(register_time__month='4') res8 = models.User.objects.filter(register_time__year='2022') print(res7, res8) ``` #### 26.一对多的增删改查 ```python # 一对多外键增删改查 # 增 # 方法一 直接写实际字段 id models.Book.objects.create(title='西游记', price=88.88, publish_id=1) # 方法二 虚拟字段 对象 publish_obj = models.Publish.objects.filter(pk=2).first() models.Book.objects.create(title='水浒传', price=66.66, publish=publish_obj) # 删 models.Publish.objects.filter(pk=2).delete() # 改 # 方式一 models.Book.objects.filter(pk=1).update(publish_id=2) # 方式二 publish_obj = models.Publish.objects.filter(pk=1).first() models.Book.objects.filter(pk=1).update(publish_id=publish_obj) ``` #### 27.多对多的增删改查 ```python # 多对多 增删改查 操作第三张虚拟表 # 增 # 方式一 book_obj = models.Book.objects.filter(pk=1).first() book_obj.author.add(1) # 书籍id为1的书籍绑定一个主键id为1的作者 book_obj.author.add(2, 3) # 可以绑定多个 # 方式二 author_obj = models.Author.objects.filter(pk=1).first() author_obj1 = models.Author.objects.filter(pk=2).first() author_obj2 = models.Author.objects.filter(pk=3).first() book_obj.author.add(author_obj, author_obj1, author_obj2) """ add给第三张表添加数据 括号内可以传数据也可以传对象,且都支持多个 """ # 删 # 方式一 # book_obj.author.remove(2) # 方式二 author_obj = models.Author.objects.filter(pk=1).first() author_obj1 = models.Author.objects.filter(pk=3).first() book_obj.author.remove(author_obj,author_obj1) """ remove给第三张表添加数据 括号内可以传数据也可以传对象,且都支持多个 """ # 改 # 方式一 # book_obj.author.set([2]) # 括号内必须给一个可迭代对象 # 方式二 author_obj = models.Author.objects.filter(pk=1).first() author_obj1 = models.Author.objects.filter(pk=3).first() book_obj.author.set([author_obj, author_obj1]) """ set给第三张表修改数据 括号内可以传数据也可以传对象,且都支持多个 并且括号内必须是一个可迭代对象 先删除后新增 """ # 清空 清除某个书籍与所有作者的绑定关系 book_obj.author.clear() # 括号内不加参数 ``` #### 28.正反向概念 ```python 外键字段如果在我手上,我查你就是正向 外键字段如果不在我手上,我查你就是反向 book >>> publish # 外键字段在book表中(正向) publis >>> book # 外键字段在book表中(反向) """ 正向查询按字段 反向查询按表名小写 """ ``` #### 29.多表查询 ##### 29.1子查询(基于对象的跨表查询) ```python # 基于对象的跨表查询 # 查询书籍主键为***的出版社名称 book_obj = models.Book.objects.filter(pk=1).first() # 书查出版社 正向 res = book_obj.publish print(res.name) # 出版社名称 print(res.addr) # 出版社地址 # 查询书籍主键为***的作者 book_obj = models.Book.objects.filter(pk=2).first() # 书查作者 正向 res = book_obj.author.all() # <QuerySet [<Author: Author object (1)>]> print(res) # 查询作者***的电话号码 author_obj = models.Author.objects.filter(name='yh').first() res = author_obj.author_detail print(res.phone) """ 在书写orm语句时如果比较复杂,就写一点看一点 """ # 查询出版社是***出版的书 publish_obj = models.Publish.objects.filter(name='新华出版社').first() # 出版社查书 反向 res = publish_obj.book_set.all() print(res) # 查询作者是***的书籍 author_obj = models.Author.objects.filter(name='yh').first() # 作者查书 反向 res = author_obj.book_set.all() print(res) # 查询手机号是***的作者姓名 author_detail_obj = models.AuthorDetail.objects.filter(phone=15892354249).first() # 手机号查作者 反向 res = author_detail_obj.author print(res.name) """ 基于对象的反向查询时 当查询结果有多个时,就必须加_set.all() 当查询结果只有一个时,就不需要加_set.all() """ ``` ##### 29.2联表查询(基于双下划线的跨表查询) ```python # 基于双下划线的跨表查询 # 查询作者***的手机号 res = models.Author.objects.filter(name='zdy').values('author_detail__phone') print(res) # 反向 # res = models.AuthorDetail.objects.filter(author__name='xyh').values('phone') # print(res) # 查询书籍主键为***的出版社名称和书的名称 res = models.Book.objects.filter(pk=1).values('publish__name', 'title') print(res) # 反向 # res = models.Publish.objects.filter(book__id=1).values('name', 'book__title') # print(res) # 查询书籍主键是***的作者的姓名 res = models.Book.objects.filter(pk=1).values('author__name') print(res) # 反向 res1 = models.Author.objects.filter(book__id=1).values('name') print(res1) # 查询书籍主键是***的作者手机号 res = models.Book.objects.filter(pk=1).values('author__author_detail__phone') print(res) # 反向 res1 = models.AuthorDetail.objects.filter(author__book__id=3).values('phone') print(res1) ```
叶浩
2024年4月1日 17:16
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
Word文件
PDF文档
PDF文档(打印)
分享
链接
类型
密码
更新密码
有效期