URL和视图函数
URL(Uniform Resource Locator)
组成:protocol://hostname[:port]/path[?query][#fragment]
书写规范:
-绝对地址:http://127.0.0.1:8000/test_html_param/Paul
-相对地址:
1. ‘/page/1’ – 结果为:http://127.0.0.1:8000/ + /page/1, 在端口后添加
2. ‘page/1’ – 结果为:http://127.0.0.1:8000/test_html_param/ + page/1,在最后一个’/'后添加
test_url.html
<a href="http://127.0.0.1:8000/url_result">绝对地址</a>
<a href="/url_result">带/的相对地址</a>
<a href="url_result">不带/相对地址</a>
<br>
<a href="{%url 'tr' %}">URL 反向解析</a>
test_url_result.html
<p>Test result!</p>
urls.py
path('test/url', test_url),
# path('url_result', test_url_result),
# django 重定向需要repath
# re_path()中只是赋予一个别名,使用别名是在html中
re_path('url_result',test_url_result, name='tr'),
views.py
def test_url(request):
from django.shortcuts import render
return render(request, "test_url.html")
def test_url_result(request):
from django.shortcuts import render
return render(request, 'test_url_result.html')
URL反向解析是指在视图或模板中,使用re_path定义名称来动态查找或计算出相对应的路由,
re_path(route, views, name=“别名”)
{% url '别名' %}
{% url '别名' '参数值1' '参数值2' %}
<a href="{%url 'tr' %}">URL 反向解析</a>
处理URL请求
- Django从配置文件中跟据ROOT_URLCONF找到主路由文件;默认情况下为urls.py
- Django 加载主路由文件中的urlpatterns变量【包含很多路由的数组】
- 依次匹配urlpatterns中的path【from diango,urls import path,repath】,匹配到第一个合适的路由中断匹配
// path('url',视图函数)
// re_path('url',视图函数,别名)
path('admin/', admin.site.urls)
re_path('url_result',test_url_result, name='tr')
- 匹配成功 - 调用对应的视图函数处理请求,返回响应
- 匹配失败 - 返回404响应
视图函数
视图函数是用于接收一个浏览器请求(HttpRequest对象)并通过HttpResponse对象返回响应的函数。
// 语法:
def home_view(request,[其他参数]):
html = "<h1>This is my home!</h1>"
return HttpResponse对象
path转换器
转换器类型:str(匹配除了‘/’之外的非空字符串),int(匹配0或任何正整数,返回一个int),slug,path(匹配包括‘/’的非空字符串)。
// 语法 <转换器类型:自定义名>
// path('page/<int:page>',page_n) 按照关键字传参
def page_view(request, pg):
# html = "<h1>This is number "+str(pg) + " site!</h1>"
html = "<h1>This is number %s site!</h1>" % (pg)
return HttpResponse(html)
path('page/<int:pg>',page_view),
// 小型计算器
def page_cal(request, num1, cal, num2):
if cal == "add":
sum = int(num1) + int(num2)
elif cal == "mul":
sum = int(num1) * int(num2)
elif cal == "sub":
sum = int(num1) - int(num2)
html = "<h1>The result is %s !</h1>" % (sum)
return HttpResponse(html)
path('<int:num1>/<str:cal>/<int:num2>',page_cal)
请求
请求方法包括GET、POST和HEAD方法(以及其他五种不常用的请求:OPTIONS、PUT、DELETE、TRACE、CONNECT)
请求在Django中就是视图函数中第一个参数request,即HttpRequest对象,通过属性描述了请求的所有相关信息,eg:
# request.path_info 是request的路径
# request.method 是request的方法
# request.GET 是QueryDict查询字典的对象,包含get请求方式的所有数据
如http://127.0.0.1:8000/test_request?a=1&&b=2获取{‘a’:['1'],'b':['2']},元素都是数组
# request.POST 是QueryDict查询字典的对象,包含post请求方式的所有数据
# request.FILES 类似于字典的对象,包含所有的上传文件信息
# GET请求只是从服务器读取页面的请求
# POST请求是用户需要提交表单时使用的请求
# COOKIES:Python字典,包含所有的cookie,键和值都为字符串
# session:类似字典的对象,表示当前的会话
# body:字符串,请求体的内容(POST或PUT)
# scheme:请求协议(‘http’/'https')
# request.get_full_path():请求的完整路径
# request.META:请求中的元数据(消息头)
request.META['REMOTE_ADDR']:客户端IP地址
def test_request(request):
print("Path info is ", request.path_info)
print("Method is ", request.method)
print("Querystring is ", request.GET)
print("Request body is ", request.body)
return HttpResponse("Test request result!")
path("test_request",test_request)
无论是GET还是POST,统一由视图函数接受请求,用request.method判断
GET请求
GET 请求指定的页面信息,并返回实体主体。
能够产生GET请求的场景:
- 浏览器地址栏中输入URL,回车后
- <a href="地址?参数=值&参数=值"
- form表单中的method为get
if request.method == 'GET':
print(request.GET)
print(request.GET['a'])
print(request.GET.get('c', 'no c'))
print(request.GET.getlist('c'))
return HttpResponse(request.method)
http://127.0.0.1:8000/test_get_post?c=263&a=1000&c=24294的输出结果
POST请求
向指定资源提交数据进行处理请求,数据被包含在请求体中,POST请求可能会导致新的资源的建立和/或已有资源的修改
POST_FORM = '''
<form method='post' action='test_get_post'>
用户名:<input type='text' name='usname'>
<input type='submit' value='提交'>
</form>
'''
def test_get_post(request):
if request.method == 'GET':
return HttpResponse(POST_FORM)
elif request.method == 'POST':
print("usname is ", request.POST['usname'])
return HttpResponse("Post is ok!")
http://127.0.0.1:8000/test_get_post的运行结果:
首先GET请求获得空白表单,其次提交之后POST请求提交表单
响应
响应状态码:-200 请求成功
-301 永久重定向,资源被永久转移到其他URL
-302 临时重定向
-404 请求的资源不存在
-500 内部服务器错误
构造函数格式:HttpResponse(content = 响应体, content_type = 响应体数据类型, status = 状态码)
常用的Content_Type类型:
HttpResponse的子类:from django.http import HttpResponse, HttpResponseRedirect
Django的设计模式
传统的MVC(模型-视图-控制器)
# 降低模块之间的耦合度
# Model: 主要用于对数据库层的封装
# View: 用于向用户展示结果
# Controller: 用于处理请求、获取数据、返回结果
Django的MTV模式
# 降低模块之间的耦合度
# Model: 负责与数据库交互
# Template: 负责呈现内容到浏览器(HTML、CSS)
# View: 核心,负责接收请求、获取数据、返回结果
# 主路由相当于Controller
模板层
模板配置
- 创建模板文件夹<项目名>/templates
- 在settings.py中TEMPLATES配置项
- BACKEND:指定模板引擎
- DIRS:模板的搜索目录
- APP_DIRS:是否要在应用中的templates文件夹中搜索模板文件
- OPTIONS:有关模板的选项
- 配置项中需要修改的部分
设置DIRS:‘DIRS’: [os.path.join(BASE_DIR, ‘templates’)]
模板的加载方式
方案一:通过loader获取模板,通过HttpResponse进行响应
模板:
from django,template import loader
t = loader.get_template("模板文件名")
html = t.render(字典数据)
return HttpResponsse(html)
样例:
# loader对象的render方法
from django.template import loader
t = loader.get_template('test_html.html')
html = t.render()
return HttpResponsse(html)
方案二:使用render()直接加载响应模板
样例:
from django.shortcuts import render
dic = {
'username': 'paul',
'age': 21
}
# return render(request, '模板文件名', 字典)
return render(request, 'test_html.html', dic)
在视图函数中,直接使用locals()直接获得视图函数的变量字典
return render(request, 'test_html.html',locals())
在模板中,通过使用{{变量名}}的语法,调用视图函数中的变量
模板的变量
能传递到模板中的数据类型:str(字符串),int(整型),list(数组),tuple(元组),dict(字典),func(方法),obj(类实例化的对象)
<h3>int 是 {{int|add:'2'}} </h3> <!-- add:'n' 过滤器-->
<h3>str 是 {{str|upper}} </h3> <!-- upper 过滤器-->
<h3>lst 是 {{lst}} </h3>
<h3>lst 是 {{lst.0}} </h3>
<h3>dict 是 {{dict}} </h3>
<h3>dict['a'] 是 {{dict.a}} </h3>
<h3>function 是 {{func}} </h3>
<h3>class_obj 是 {{class_obj.say}} </h3>
<h3>Script 是 {{script|safe}} </h3><!-- safe 过滤器, 不对字符串进行html转译,Django默认开启字符串转译-->
from django.shortcuts import render
dic = {}
dic['int'] = 88
dic['str'] = 'username'
dic['lst'] = ['Tom', 'Jerry', 'Lily']
dic['dict'] = {'a': 9, 'b':7}
dic['func'] = say_hi
dic['class_obj'] = Dog()
dic['script'] = '<script>alter(1111)</script>'
return render(request, 'test_html_param.html', dic)
def say_hi():
return "hello"
class Dog:
def say(self):
return "nihao!"
模板的标签
if 标签
def test_if_for(request):
from django.shortcuts import render
dic = {}
dic['x'] = 10
return render(request, 'test_if_for.html', dic)
模板文件中
{% if x > 10 %}
今天天气很好
{% else %}
今天天气非常好
{% endif %}
<form action="/if_cal" method="post">
<input type="text" name="x" value={{x}}>
<option value="add" {% if op == 'add' %} selected {% endif %}> + 加</option>
<option value="sub" {% if op == 'sub' %} selected {% endif %}> - 减</option>
<option value="mul" {% if op == 'mul' %} selected {% endif %}> * 乘</option>
<option value="div" {% if op == 'div' %} selected {% endif %}> / 除</option>
<input type="text" name="y" value={{y}}> = <span>{{result}}</span>
<div>
<input type="submit" value="开始计算">
</div>
</form>
def if_cal(request):
from django.shortcuts import render
if request.method == 'GET':
return render(request, 'if_cal.html')
else:
x = int(request.POST['x'])
y = int(request.POST['y'])
op = request.POST['op']
if op == 'add':
result = x + y
elif op == 'sub':
result = x - y
elif op == 'mul':
result = x * y
else:
result = x / y
# locals() 把变量封装成一个字典
# dic = {'x': x, 'y': y, 'op': op, 'result': result}
return render(request, 'if_cal.html', locals())
for 标签
语法:
{% for 变量 in 可迭代对象 %}
循环语句
{% empty %}
可迭代对象无数据时填充的语句
{% endfor %}
def test_if_for(request):
from django.shortcuts import render
dic = {}
dic['lst'] = ['Tom','Jack','Jerry']
return render(request, 'test_if_for.html', dic)
{% for name in lst%}
{% if forloop.first %} ########### {%endif%}
<p>{{forloop.counter}} {{name}}</p>
{% if forloop.last %} ********** {%endif%}
{% empty %}
Now Empty!
{% endfor %}
内置变量 - forloop
模板过滤器
定义:在变量输出时对变量的值进行处理
作用:可以通过使用过滤器来改变变量的输出和显示
语法:{{变量 | 过滤器1:'参数值1'| 过滤器2:'参数值'2'}}
<h3>int 是 {{int|add:'2'}} </h3> <!-- add:'n' 过滤器-->
<h3>str 是 {{str|upper}} </h3> <!-- upper 过滤器-->
<h3>lst 是 {{lst}} </h3>
<h3>lst 是 {{lst.0}} </h3>
<h3>dict 是 {{dict}} </h3>
<h3>dict['a'] 是 {{dict.a}} </h3>
<h3>function 是 {{func}} </h3>
<h3>class_obj 是 {{class_obj.say}} </h3>
<h3>Script 是 {{script|safe}} </h3><!-- safe 过滤器, 不对字符串进行html转译,Django默认开启字符串转译-->
from django.shortcuts import render
dic = {}
dic['int'] = 88
dic['str'] = 'username'
dic['lst'] = ['Tom', 'Jerry', 'Lily']
dic['dict'] = {'a': 9, 'b':7}
dic['func'] = say_hi
dic['class_obj'] = Dog()
dic['script'] = '<script>alter(1111)</script>'
return render(request, 'test_html_param.html', dic)
def say_hi():
return "hello"
class Dog:
def say(self):
return "nihao!"
模板的继承
模板继承可以使父模板的内容重用,子模板直接继承父模板的全部内容并可以覆盖父模板中相对应的块。
语法:
- 父模板:
1. 定义父模板中的块block标签
2. 标识出哪些可以在子模板中是允许被修改的
3. block标签:在父模板中定义,可以在子模板中覆盖
- 子模板:
1. 继承模板extends标签(写在子模板文件的第一行)
2. 子模板重写父模板中的内容块
父模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
{% block mytitle %}
<title>主页</title>
{% endblock %}
</head>
<body>
<a href="/music">音乐</a>
<a href="/sport">体育</a>
<br>
{% block info %}
This is home.
{% endblock %}
</body>
</html>
子模板1:
{% extends 'home.html' %}
{% block mytitle %}
<title>音乐</title>
{% endblock %}
{% block info %}
This is music.
{% endblock %}
子模板2:
{% extends 'home.html' %}
{% block mytitle %}
<title>体育</title>
{% endblock %}
{% block info %}
This is sport.
{% endblock %}
子模板没有办法继承父模板中的变量,因为变量在父模板的视图函数中,子模板只能调用自己的视图函数中的变量
静态文件
静态文件配置 - settings.py
- 配置静态文件的访问路径[默认存在] STATIC_URL = ‘static’
- 配置静态文件的存储路径STATICFILES_DIRS(元组,保存的是静态文件在服务器端的存储位置)
STATICFILES_DIRS= (os.path.join(BASE_DIR,"static"), )
方法一
settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"),)
urls.py
from django.contrib import admin
from django.urls import path
from .views import *
urlpatterns = (
path('admin/', admin.site.urls),
path('test_static', test_static),
)
views.py
from django.shortcuts import render
def test_static(request):
return render(request, 'test_static.html')
test_static.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<img src="http://127.0.0.1:8000/static/image/2.jpg" width="200px" height="200px">
<img src="/static/image/2.jpg" width="100px" height="100px">
</body>
</html>
方法二
在模板中通过{% static %}标签访问静态文件
比相对路径和绝对路径更加动态
- 加载 static- {% load static %}
- 使用静态资源 - {% static ‘静态资源路径’ %}
eg: <img src = “{% static ‘image/2.jpg’%}”
<img src="{% static 'image/2.jpg' %}" width="150" height="150">
Django的应用
应用在Django项目中是一个独立的业务模块,包含自己的路由,视图,模板,模型,相当于一个小型的MTV框架.
创建应用:
- 用manage.py中的子命令startapp创建应用文件夹
python manage.py startapp music - 在settings.py的INSTALLED_APPS列表(数组)中配置安装此应用
INSTALL_APPS= [‘user’, ‘music’,]
分布式路由
Django中,主路由配置文件(urls.py)可以不处理用户具体路由,主路由配置文件可以做请求的分发(分布式请求处理).具体的请求可以由各自的应用来进行处理.
配置分布式路由
- 主路由中调用include函数(from django.urls import path,include)
- 语法: include(‘app名字.url模块名’)
- 作用:用于将当前路由转到各个应用的路由配置文件的urlpatterns进行分布式处理
- 应用下创建urls.py,结构与主路由一样
主路由
from django.contrib import admin
from django.urls import path,include
from .views import *
urlpatterns = (
path('admin/', admin.site.urls),
path('test_static', test_static),
path('music/',include('music.urls'))
)
music app 下的urls.py
from django.contrib import admin
from django.urls import path
from .views import *
urlpatterns = [
path('admin/',admin.site.urls),
path('index',index_view)
]
应用下的模板
- 在应用下手动添加templates文件夹
- settings.py中开启模板功能
TEMPLATE配置项中的'APP_DIRS'的值设为True
应用下的templates和外层的templates中都存在index.html时,django的查找模板的规则为:
① 优先查找外层templates目录下的模板
② 按照INSTALL_APPS配置下的应用顺序逐个查找
若两个应用的templates文件夹之间存在同名文件,通过在templates目录下添加与应用同名的文件夹,将模板放在与应用同名的文件夹下可以避免冲突.
修改前,输入http://127.0.0.1:8000/news/index会跳转到music下面的index.html
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'music',
'news',
]
from django.shortcuts import render
# Create your views here.
def index_view(request):
return render(request, 'index.html')
修改后,输入http://127.0.0.1:8000/news/index会跳转到news下面的index.html
views.py中的视图函数也需要修改
from django.shortcuts import render
def index_view(request):
return render(request, 'news/index.html')
模型层(负责与数据库进行通信)
配置DATABASE,init.py
import pymysql
pymysql.install_as_MySQLdb()
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'book', # 指定要连接的数据库名
'USER': 'root', # 指定登录到数据库的用户名
'PASSWORD': '123456', # 数据库密码
'HOST': '127.0.0.1', # 连接具体数据库的IP和端口
'PORT': '3306',
}
}
模型是一个Python类,是由django.db.model.Model派生出来的子类
一个模型类代表数据库中的一张数据表
模型类中每个类的属性都代表数据库中的一个字段
模型是数据交互的接口,表示和操作数据库的方法和方式
ORM框架(对象关系映射)
避免通过SQL语句操作数据库
作用:
1. 建立模型类和表之间的对应关系,允许我们通过面向对象的方式来操作数据库
2. 根据设计的模型类生成数据库中的表格
3. 通过简单的配置就能进行数据库之间的切换
4. 实现了数据模型和数据库的解耦,屏蔽不同数据库操作上的差异
在models.py
from django.db import models
# Create your models here.
class Book(models.Model):
name = models.CharField("书名", max_length=20, default='')
price = models.DecimalField("价格", max_digits=5, decimal_places=2, default=0.0)
数据库的迁移
python manage.py makemigrations 生成迁移文件
python manage.py migrate 执行迁移程序实现迁移(数据同步)
ORM字段类型
BooleanField()
CharField()对应varchar必须指定max_length参数值
DateField()表示日期:
- auto_now: 每次保存对象时,自动设置该字段为当前时间(取值:True/False)
- auto_now_add: 当对象第一次被创建时自动设置为当前时间(取值:True/False)
- default:设置当前时间(取值:字符串格式时间如:‘2019-6-1’)
- 三个参数只能三选一
DateTimeField(): 表示日期和时间
FloatField():double
DecimalField: 小数
- max_digits:位数总数,包括小数点后的位数。该值必须大于等于decimal_places
- decimal_places: 小数点后的数字位数
EmailField() : 数据库类型为varchar,存储邮箱
IntegerField():数据库类型为int
字段选项-定义创建的列的额外信息
primary_key: (取值:True/False,默认False)
blank:(取值:True/False)设置为True时,字段可为空,反之,字段必须填写
null:(取值:True/False)默认为False,如果为False建议加入default选项设置默认值,True,则可以字段为空
default:设置所在列的默认值,如果字段选项null=False建议添加此项
db_index:(取值:True/False)为True表示为该列增加索引
unique:(取值:True/False)True表示该字段在数据库中的值必须时唯一的(不能重复出现)
db_column:指定列的名称,如果不指定就采用属性名作为列名
verbose_name:设置此字段在admin界面上的显示名称
模型类-Meta类
使用内部Meta类来给模型赋予属性,比如改表名,
改前:
改后:
class Book(models.Model):
name = models.CharField("书名", max_length=20, default='')
price = models.DecimalField("价格", max_digits=5, decimal_places=2, default=0.0)
info = models.CharField("书籍信息", max_length= 100,default='')
class Meta:
db_table = 'book'
class Author(models.Model):
name = models.CharField("姓名",max_length=11)
age = models.IntegerField("年龄")
email = models.EmailField("邮箱")
class Meta:
db_table = 'author'
ORM创建数据
- MyModel.objects.create(属性1=值1,属性2=值2)
成功:返回创建好的实体对象
失败:抛出异常 - 创建MyModel实例对象,并调用save()进行保存
obj = MyModel(属性=值,属性=值,)
obj.属性 = 值
obj.save()
利用Django Shell 可以代替编写view的代码来进行操作,启动方式python manage.py shell
代码有修改,就需要重启shell
使用这两种方法需要引入model类,from book.models import Book
ORM查询数据
MyModel.objects.all(): 返回值是QuerySet容器对象,内部存放MyModel实例,相当于一个MyModel的数组
可以在MyModel类中自定义输出格式
def __str__(self):
return '%s_%s_%s_%s'%(self.title,self.pub,self.price,self.market_price)
python manage.py shell
>>> from book.models import *
>>> books = Book.objects.all()
>>> books
<QuerySet [<Book: Python_清华大学出版社_20.00_25.00>, <Book: C++_北京大学出版社_25.00_40
.00>, <Book: Django_清华大学出版社_70.00_75.00>, <Book: JQuery_机械工业出版社_90.00_85.0
0>, <Book: Linux_机械工业出版社_80.00_65.00>, <Book: HTML5_清华大学出版社_90.00_105.00>]
>
MyModel.objects.values(‘列1’,‘列2’): 类似于all()但是只查所需要的两列,返回的是一个字典
>>> books = Book.objects.values('title','pub')
>>> books
<QuerySet [{'title': 'Python', 'pub': '清华大学出版社'}, {'title': 'C++', 'pub': '北京大
学出版社'}, {'title': 'Django', 'pub': '清华大学出版社'}, {'title': 'JQuery', 'pub': '机
械工业出版社'}, {'title': 'Linux', 'pub': '机械工业出版社'}, {'title': 'HTML5', 'pub': '
清华大学出版社'}]>
>>> for book in books:
... print(book['title'])
...
Python
C++
Django
JQuery
Linux
HTML5
MyModel.objects.values_list(): 类似于values但是返回值是一个元组
>>> books = Book.objects.values_list('title','pub')
>>> books
<QuerySet [('Python', '清华大学出版社'), ('C++', '北京大学出版社'), ('Django', '清华大学
出版社'), ('JQuery', '机械工业出版社'), ('Linux', '机械工业出版社'), ('HTML5', '清华大学
出版社')]>
>>> for book in books:
... print(book[0])
...
Python
C++
Django
JQuery
Linux
HTML5
MyModel.objects.order_by(’-列1’,‘列2’):
默认正向排序,加了-则为逆向排序
返回值是QuerySet
>>> books = Book.objects.order_by('price')
>>> books
<QuerySet [<Book: Python_清华大学出版社_20.00_25.00>, <Book: C++_北京大学出版社_25.00_40
.00>, <Book: Django_清华大学出版社_70.00_75.00>, <Book: Linux_机械工业出版社_80.00_65.00
>, <Book: JQuery_机械工业出版社_90.00_85.00>, <Book: HTML5_清华大学出版社_90.00_105.00>]
>
>>> books = Book.objects.order_by('-price')
>>> books
<QuerySet [<Book: JQuery_机械工业出版社_90.00_85.00>, <Book: HTML5_清华大学出版社_90.00_
105.00>, <Book: Linux_机械工业出版社_80.00_65.00>, <Book: Django_清华大学出版社_70.00_75
.00>, <Book: C++_北京大学出版社_25.00_40.00>, <Book: Python_清华大学出版社_20.00_25.00>]
>
QuerySet后可继续使用方法:
>>> books = Book.objects.order_by('-price').values('title')
>>> books
<QuerySet [{'title': 'JQuery'}, {'title': 'HTML5'}, {'title': 'Linux'}, {'title': 'Djang
o'}, {'title': 'C++'}, {'title': 'Python'}]>
>>> print(books.query) // 得到SQL语句
SELECT `book`.`title` FROM `book` ORDER BY `book`.`price` DESC
MyModel.objects.filter(属性1=值1,属性2=值2)
条件查询,返回值QuerySet容器对象,内部存放MyModel实例,当有多个属性的时候,多个属性是"与"关系
PS D:\Python Project\Django test\Test3> python manage.py shell
Python 3.9.7 (tags/v3.9.7:1016ef3, Aug 30 2021, 20:19:38) [MSC v.1929 64 bit (AMD64)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from book.models import *
>>> books = Book.objects.filter(pub='清华大学出版社')
>>> for book in books:
... print(book.title)
...
Python
Django
HTML5
MyModel.objects.exclude(条件)
返回不包含此条件的全部数据集,返回QuerySet
MyModel.objects.get(条件)
返回满足条件的唯一一条数据,如果有多条符合条件或者没有一条符合条件都会报错.
// 北京大学出版社返回一条数据
>>> book1 = Book.objects.get(pub='北京大学出版社')
>>> book1
<Book: C++_北京大学出版社_25.00_40.00>
// 清华大学出版社返回三条数据
>>> book1 = Book.objects.get(pub='清华大学出版社')
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "D:\Python Project\Django test\Test3\venv\lib\site-packages\django\db\models\mana
ger.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "D:\Python Project\Django test\Test3\venv\lib\site-packages\django\db\models\quer
y.py", line 439, in get
raise self.model.MultipleObjectsReturned(
book.models.Book.MultipleObjectsReturned: get() returned more than one Book -- it return
ed 3!
查询谓词
__exact:等值查询
>>> Book.objects.filter(id__exact = 1)
<QuerySet [<Book: Python_清华大学出版社_20.00_25.00>]>
__contains:包含指定值
>>> Book.objects.filter(pub__contains = '大学')
<QuerySet [<Book: Python_清华大学出版社_20.00_25.00>, <Book: C++_北京大学出版社_25.00_40
.00>, <Book: Django_清华大学出版社_70.00_75.00>, <Book: HTML5_清华大学出版社_90.00_105.0
0>]>
__startswith: 以xxx开始
>>> Book.objects.filter(pub__startswith='清')
<QuerySet [<Book: Python_清华大学出版社_20.00_25.00>, <Book: Django_清华大学出版社_70.00
_75.00>, <Book: HTML5_清华大学出版社_90.00_105.00>]>
__endswith:以xxx结束
>>> Author.objects.filter(name__endswith='i')
<QuerySet [<Author: 3_Qi_30_qitx@tedu.cn_>]>
__gt:大于指定值
__gte: 大于等于指定值
__lt:小于指定值
__lte:小于等于指定值
__in: 查找数据是否在指定范围内
>>> Book.objects.filter(pub__in=['清华大学出版社','北京大学出版社'])
<QuerySet [<Book: Python_清华大学出版社_20.00_25.00>, <Book: C++_北京大学出版社_25.00_40.00>, <Book: Django_清华大学出版社_70.00_75.00>, <Book: HTML5_清华大学出版社_90.00_105.00>]>
__range:查找数据是否在指定区间范围内
>>> Book.objects.filter(price__range=(50,100))
<QuerySet [<Book: Django_清华大学出版社_70.00_75.00>, <Book: JQuery_机械工业出版社_90.00_85.00>, <Book: Linux_机械工业出版社_80.00_65.00>, <Book: HTML5_清华大学出版社_90.00_105.00>]>
>>> Book.objects.filter(price__range=(75,100))
<QuerySet [<Book: JQuery_机械工业出版社_90.00_85.00>, <Book: Linux_机械工业出版社_80.00_65.00>, <Book: HTML5_清华大学出版社_90.00_105.00>]>
ORM修改数据
单个数据的修改
- 查 - 通过get()得到要修改的实体对象
- 改 - 通过对象属性的方式修改数据
- 保存 - 通过对象.save()保存数据
>>> author = Author.objects.get(id = 1)
>>> author
<Author: 1_Wang_28_wangweichao@tedu.cn_>
>>> author.age = 49
>>> author.save()
>>> Author.objects.all()
<QuerySet [<Author: 1_Wang_49_wangweichao@tedu.cn_>, <Author: 2_Lv_31_lvze@tedu.cn_>, <Author: 3_Qi_30_qitx@tedu.cn_>]>
批量数据的修改
直接调用QuerySet的update(属性=值)实现批量修改
>>> authors = Author.objects.all()
>>> authors.update(age = 70)
3
>>> Author.objects.all()
<QuerySet [<Author: 1_Wang_70_wangweichao@tedu.cn_>, <Author: 2_Lv_70_lvze@tedu.cn_>, <A
uthor: 3_Qi_70_qitx@tedu.cn_>]>
ORM删除数据
单个数据删除
- 查找查询结果对应的一个数据对象
- 调用这个数据对象的delete()方法实现删除
>>> from book.models import *
>>> book = Book.objects.get(id=4)
>>> book
<Book: JQuery_机械工业出版社_90.00_85.00>
>>> book.delete
<bound method Model.delete of <Book: JQuery_机械工业出版社_90.00_85.00>>
>>> Book.objects.all()
<QuerySet [<Book: Django_清华大学出版社_70.00_75.00>, <Book: JQuery_机械工业出版社_90.00
_85.00>, <Book: Linux_机械工业出版社_80.00_65.00>, <Book: HTML5_清华大学出版社_90.00_105
.00>, <Book: Python_清华大学出版社_20.00_25.00>]>
批量删除数据
1. 查找查询结果集中满足条件的全部QuerySet查询集合对象
2. 调用查询集合对象的delete()方法实现删除
>>> books = Book.objects.filter(price__gte=85)
>>> books
<QuerySet [<Book: JQuery_机械工业出版社_90.00_85.00>, <Book: HTML5_清华大学出版社_90.00_
105.00>]>
>>> Book.objects.all()
<QuerySet [<Book: Django_清华大学出版社_70.00_75.00>, <Book: JQuery_机械工业出版社_90.00
_85.00>, <Book: Linux_机械工业出版社_80.00_65.00>, <Book: HTML5_清华大学出版社_90.00_105
.00>, <Book: Python_清华大学出版社_20.00_25.00>]>
>>> books.delete()
(2, {'book.Book': 2})
>>> Book.objects.all()
<QuerySet [<Book: Django_清华大学出版社_70.00_75.00>, <Book: Linux_机械工业出版社_80.00_
65.00>, <Book: Python_清华大学出版社_20.00_25.00>]>
>>> print(books.query)
SELECT `book`.`id`, `book`.`title`, `book`.`pub`, `book`.`price`, `book`.`market_price`,
`book`.`info` FROM `book` WHERE `book`.`price` >= 85
伪删除
在表中添加一个布尔型的字段(is_active),默认是True,执行删除操作,就是将需要删除的数据的is_active字段置为False
F 对象
一个F对象代表数据库中某条记录的字段的信息
作用:
通常是对数据库中的字段值在不获取的情况下进行操作
属于类属性之间的比较
以及方便多用户对数据进行操作,eg:微博一百人对同一条微博点赞,若先获取点赞值然后增加并重新赋值,会冲突
语法:from django.db.models import F
F(‘列名’)
所有的书籍售价增长10
Book.objects.all().update(market_price = F('market_price') + 10)
Q对象
当在获取查询结果集使用复杂的逻辑或 | 、逻辑非 ~等操作时可以借助Q对象进行操作
&与操作
| 或操作
~ 非操作
三种操作可以进行组合
&~与非
>>> from django.db.models import Q
>>> Book.objects.all()
<QuerySet [<Book: Django_清华大学出版社_70.00_75.00>, <Book: Linux_机械工业出版社_80.00_
65.00>, <Book: Python_清华大学出版社_20.00_25.00>]>
>>> Book.objects.filter(Q(price__lt=20) | Q(pub='清华大学出版社'))
<QuerySet [<Book: Django_清华大学出版社_70.00_75.00>, <Book: Python_清华大学出版社_20.00
_25.00>]>
>>> Book.objects.filter(Q(price__gt=20) &~ Q(pub='清华大学出版社'))
<QuerySet [<Book: Linux_机械工业出版社_80.00_65.00>]>