Django 学习笔记 1

这篇博客详细介绍了Django中的URL和视图函数,包括URL的组成和书写规范,视图函数的作用,以及如何处理GET和POST请求。此外,还涵盖了Django的响应、设计模式、模板层、静态文件管理和ORM框架等内容,深入探讨了模型层的字段类型、查询数据和数据操作。
摘要由CSDN通过智能技术生成

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请求

  1. Django从配置文件中跟据ROOT_URLCONF找到主路由文件;默认情况下为urls.py
  2. Django 加载主路由文件中的urlpatterns变量【包含很多路由的数组】
  3. 依次匹配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')
  1. 匹配成功 - 调用对应的视图函数处理请求,返回响应
  2. 匹配失败 - 返回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配置项
    1. BACKEND:指定模板引擎
    2. DIRS:模板的搜索目录
    3. APP_DIRS:是否要在应用中的templates文件夹中搜索模板文件
    4. 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

  1. 配置静态文件的访问路径[默认存在] STATIC_URL = ‘static’
  2. 配置静态文件的存储路径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 %}标签访问静态文件
比相对路径和绝对路径更加动态

  1. 加载 static- {% load static %}
  2. 使用静态资源 - {% static ‘静态资源路径’ %}
    eg: <img src = “{% static ‘image/2.jpg’%}”
<img src="{% static 'image/2.jpg' %}" width="150" height="150">

Django的应用

应用在Django项目中是一个独立的业务模块,包含自己的路由,视图,模板,模型,相当于一个小型的MTV框架.
创建应用:

  1. 用manage.py中的子命令startapp创建应用文件夹
    python manage.py startapp music
  2. 在settings.py的INSTALLED_APPS列表(数组)中配置安装此应用
    INSTALL_APPS= [‘user’, ‘music’,]

分布式路由

Django中,主路由配置文件(urls.py)可以不处理用户具体路由,主路由配置文件可以做请求的分发(分布式请求处理).具体的请求可以由各自的应用来进行处理.

配置分布式路由
  1. 主路由中调用include函数(from django.urls import path,include)
    • 语法: include(‘app名字.url模块名’)
    • 作用:用于将当前路由转到各个应用的路由配置文件的urlpatterns进行分布式处理
  2. 应用下创建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)
]
应用下的模板
  1. 在应用下手动添加templates文件夹
  2. 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创建数据
  1. MyModel.objects.create(属性1=值1,属性2=值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修改数据

单个数据的修改

  1. 查 - 通过get()得到要修改的实体对象
  2. 改 - 通过对象属性的方式修改数据
  3. 保存 - 通过对象.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删除数据

单个数据删除

  1. 查找查询结果对应的一个数据对象
  2. 调用这个数据对象的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>]>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值