Django之Models(一) Django之Models(一) 数据库配置 模型代码参数解析 分析代码  模型常用的字段类型参数    Field重要参数 ORM对单表的增删改查  添加数据 删除数据 修改数据 简单查询 具体演示   查询的补充 扩展查询

目录

数据库的配置

模型代码与参数解析

ORM对单表的增删改查

查询的补充

数据库配置

django默认支持sqlite,mysql, oracle,postgresql数据库。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

django默认使用sqlite的数据库,默认自带sqlite的数据库驱动 , 引擎名称:django.db.backends.sqlite3

mysql引擎名称:django.db.backends.mysql

其他数据引擎名

'django.db.backends.postgresql'
'django.db.backends.postgresql_psycopg2'
'django.db.backends.oracle'
View Code

 

mysql驱动程序

MySQLdb(mysql python)
mysqlclient
MySQL
PyMySQL(纯python的mysql驱动程序)

 
View Code

 数据库配置

我们现在连接mysql数据库。

1.MySQL需要安装pyMySQL、mysqlclient

pip install pyMySQL

pip install mysqlclient

  

2.setting.py文件下DATABASES下

DATABASES = {

'default': {

'ENGINE': 'django.db.backends.mysql',

'NAME': 'books', #你的数据库名称

'USER': 'root', #你的数据库用户名

'PASSWORD': '', #你的数据库密码

'HOST': '', #你的数据库主机,留空默认为localhost

'PORT': '3306', #你的数据库端口

}

}
View Code

 3.项目名文件下的__init__.py

import pymysql
pymysql.install_as_MySQLdb()

4.应用文件下的models.py

现在我们创建书籍模型:书籍有书名和出版日期,作者。

class Book(models.Model):
	name=models.CharFiled(max_length=20)
	price=models.InterFiled()
	pub_date=models.DateFiled()
	author=models.CharField(max_length=32,null=False)

  

5 .settings里的INSTALLED_APPS中加入应用文件名,我的应用文件名为blog

INSTALLED_APPS = [
    'blog',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
View Code

6.生成同步数据库的脚本与同步数据库

python manage.py makemigrations

python manage.py migrate

  

Django之Models(一)
Django之Models(一)
数据库配置
模型代码参数解析
分析代码
 模型常用的字段类型参数
 
 Field重要参数
ORM对单表的增删改查
 添加数据
删除数据
修改数据
简单查询
具体演示
 
查询的补充
扩展查询

查询结果:

本来test数据库只有一张account表

最后会生成除了book表以外(以应用文件名开头),还会生成其他自带的表

 Django之Models(一)
Django之Models(一)
数据库配置
模型代码参数解析
分析代码
 模型常用的字段类型参数
 
 Field重要参数
ORM对单表的增删改查
 添加数据
删除数据
修改数据
简单查询
具体演示
 
查询的补充
扩展查询

Django之Models(一)
Django之Models(一)
数据库配置
模型代码参数解析
分析代码
 模型常用的字段类型参数
 
 Field重要参数
ORM对单表的增删改查
 添加数据
删除数据
修改数据
简单查询
具体演示
 
查询的补充
扩展查询

还会在应用文件下自动生成:migrations文件夹

在文件下可以查看表的结构等信息。

 Django之Models(一)
Django之Models(一)
数据库配置
模型代码参数解析
分析代码
 模型常用的字段类型参数
 
 Field重要参数
ORM对单表的增删改查
 添加数据
删除数据
修改数据
简单查询
具体演示
 
查询的补充
扩展查询

模型代码参数解析

分析代码

       <1>  每个数据模型都是django.db.models.Model的子类,它的父类Model包含了所有必要的和数据库交互的方法。并提供了一个简介漂亮的定义数据库字段的语法。

       <2>  每个模型相当于单个数据库表(多对多关系例外,会多生成一张关系表),每个属性也是这个表中的字段。属性名就是字段名,它的类型(例如CharField)相当于数据库的字段类型(例如varchar)
。大家可以留意下其它的类型都和数据库里的什么字段对应。 <3> 模型之间的三种关系:一对一,一对多,多对多。 一对一:实质就是在主外键(author_id就是foreign key)的关系基础上,给外键加了一个UNIQUE=True的属性; 一对多:就是主外键关系;(foreign key) 多对多:(ManyToManyField) 自动创建第三张表(当然我们也可以自己创建第三张表:两个foreign key)

  

 模型常用的字段类型参数

<1> CharField
        #字符串字段, 用于较短的字符串.
        #CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的最大字符数.

<2> IntegerField
       #用于保存一个整数.

<3> FloatField
        # 一个浮点数. 必须 提供两个参数:
        #
        # 参数    描述
        # max_digits    总位数(不包括小数点和符号)
        # decimal_places    小数位数
                # 举例来说, 要保存最大值为 999 (小数点后保存2位),你要这样定义字段:
                #
                # models.FloatField(..., max_digits=5, decimal_places=2)
                # 要保存最大值一百万(小数点后保存10位)的话,你要这样定义:
                #
                # models.FloatField(..., max_digits=19, decimal_places=10)
                # admin 用一个文本框(<input type="text">)表示该字段保存的数据.

<4> AutoField
        # 一个 IntegerField, 添加记录时它会自动增长. 你通常不需要直接使用这个字段; 
        # 自定义一个主键:my_id=models.AutoField(primary_key=True)
        # 如果你不指定主键的话,系统会自动添加一个主键字段到你的 model.

<5> BooleanField
        # A true/false field. admin 用 checkbox 来表示此类字段.

<6> TextField
        # 一个容量很大的文本字段.
        # admin 用一个 <textarea> (文本区域)表示该字段数据.(一个多行编辑框).

<7> EmailField
        # 一个带有检查Email合法性的 CharField,不接受 maxlength 参数.

<8> DateField
        # 一个日期字段. 共有下列额外的可选参数:
        # Argument    描述
        # auto_now    当对象被保存时,自动将该字段的值设置为当前时间.通常用于表示 "last-modified" 时间戳.
        # auto_now_add    当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间.
        #(仅仅在admin中有意义...)

<9> DateTimeField
        #  一个日期时间字段. 类似 DateField 支持同样的附加选项.

<10> ImageField
        # 类似 FileField, 不过要校验上传对象是否是一个合法图片.#它有两个可选参数:height_field和width_field,
        # 如果提供这两个参数,则图片将按提供的高度和宽度规格保存.     
<11> FileField
     # 一个文件上传字段.
     #要求一个必须有的参数: upload_to, 一个用于保存上载文件的本地文件系统路径. 这个路径必须包含 strftime #formatting, 
     #该格式将被上载文件的 date/time 
     #替换(so that uploaded files don't fill up the given directory).
     # admin 用一个<input type="file">部件表示该字段保存的数据(一个文件上传部件) .

     #注意:在一个 model 中使用 FileField 或 ImageField 需要以下步骤:
            #(1)在你的 settings 文件中, 定义一个完整路径给 MEDIA_ROOT 以便让 Django在此处保存上传文件. 
            # (出于性能考虑,这些文件并不保存到数据库.) 定义MEDIA_URL 作为该目录的公共 URL. 要确保该目录对 
            #  WEB服务器用户帐号是可写的.
            #(2) 在你的 model 中添加 FileField 或 ImageField, 并确保定义了 upload_to 选项,以告诉 Django
            # 使用 MEDIA_ROOT 的哪个子目录保存上传文件.你的数据库中要保存的只是文件的路径(相对于 MEDIA_ROOT). 
            # 出于习惯你一定很想使用 Django 提供的 get_<#fieldname>_url 函数.举例来说,如果你的 ImageField 
            # 叫作 mug_shot, 你就可以在模板中以 {{ object.#get_mug_shot_url }} 这样的方式得到图像的绝对路径.

<12> URLField
      # 用于保存 URL. 若 verify_exists 参数为 True (默认), 给定的 URL 会预先检查是否存在( 即URL是否被有效装入且
      # 没有返回404响应).
      # admin 用一个 <input type="text"> 文本框表示该字段保存的数据(一个单行编辑框)

<13> NullBooleanField
       # 类似 BooleanField, 不过允许 NULL 作为其中一个选项. 推荐使用这个字段而不要用 BooleanField 加 null=True 选项
       # admin 用一个选择框 <select> (三个可选择的值: "Unknown", "Yes""No" ) 来表示这种字段数据.

<14> SlugField
       # "Slug" 是一个报纸术语. slug 是某个东西的小小标记(短签), 只包含字母,数字,下划线和连字符.#它们通常用于URLs
       # 若你使用 Django 开发版本,你可以指定 maxlength. 若 maxlength 未指定, Django 会使用默认长度: 50.  #在
       # 以前的 Django 版本,没有任何办法改变50 这个长度.
       # 这暗示了 db_index=True.
       # 它接受一个额外的参数: prepopulate_from, which is a list of fields from which to auto-#populate 
       # the slug, via JavaScript,in the object's admin form: models.SlugField
       # (prepopulate_from=("pre_name", "name"))prepopulate_from 不接受 DateTimeFields.

<13> XMLField
        #一个校验值是否为合法XML的 TextField,必须提供参数: schema_path, 它是一个用来校验文本的 RelaxNG schema #的文件系统路径.

<14> FilePathField
        # 可选项目为某个特定目录下的文件名. 支持三个特殊的参数, 其中第一个是必须提供的.
        # 参数    描述
        # path    必需参数. 一个目录的绝对文件系统路径. FilePathField 据此得到可选项目. 
        # Example: "/home/images".
        # match    可选参数. 一个正则表达式, 作为一个字符串, FilePathField 将使用它过滤文件名.  
        # 注意这个正则表达式只会应用到 base filename 而不是
        # 路径全名. Example: "foo.*.txt^", 将匹配文件 foo23.txt 却不匹配 bar.txt 或 foo23.gif.
        # recursive可选参数.要么 True 要么 False. 默认值是 False. 是否包括 path 下面的全部子目录.
        # 这三个参数可以同时使用.
        # match 仅应用于 base filename, 而不是路径全名. 那么,这个例子:
        # FilePathField(path="/home/images", match="foo.*", recursive=True)
        # ...会匹配 /home/images/foo.gif 而不匹配 /home/images/foo/bar.gif

<15> IPAddressField
        # 一个字符串形式的 IP 地址, (i.e. "24.124.1.30").
<16># CommaSeparatedIntegerField
        # 用于存放逗号分隔的整数值. 类似 CharField, 必须要有maxlength参数.
View Code

 

 Field重要参数

<1> null : 数据库中字段是否可以为空

    <2> blank: django的 Admin 中添加数据时是否可允许空值

    <3> default:设定缺省值

    <4> editable:如果为假,admin模式下将不能改写。缺省为真

    <5> primary_key:设置主键,如果没有设置django创建表时会自动加上:
        id = meta.AutoField('ID', primary_key=True)
        primary_key=True implies blank=False, null=False and unique=True. Only one
        primary key is allowed on an object.

    <6> unique:数据唯一

    <7> verbose_name  Admin中字段的显示名称

    <8> validator_list:有效性检查。非有效产生 django.core.validators.ValidationError 错误


    <9> db_column,db_index 如果为真将为此字段创建索引

    <10>choices:一个用来选择值的2维元组。第一个值是实际存储的值,第二个用来方便进行选择。
                如SEX_CHOICES= (( ‘F’,'Female’),(‘M’,'Male’),)
                gender = models.CharField(max_length=2,choices = SEX_CHOICES)
View Code

 Date字段类型的补充

date
根据给定格式对一个日期变量进行格式化。

可用的格式字符串:

格式化字符    描述    示例输出
a    'a.m.''p.m.'    'a.m.'
A    'AM''PM'    'AM'
b    月份,文字形式,3个字母,小写。    “jan”
B    未实现。     
c    ISO 8601格式    2008-01-02T10:30:00.000123+02:00
d    月的日子,带前导零的2位数字。    '01''31'
D    周几的文字表述形式,3个字母。    'Fri'
e    时区名称    '''GMT''-500''US/Eastern'等
E    月份,分地区。     
f    时间    '1''1:30'
F    月,文字形式。    'January'
g    12小时格式,无前导零。    '1''12'
G    24小时格式,无前导零。    '0''23'
h    12小时格式。    '01''12'
H    24小时格式。    '00''23'
i    分钟    '00''59'
I    夏令时间,无论是否生效。    '1''0'
j    没有前导零的月份的日子。    '1''31'
l    星期几,完整英文名    'Friday'
L    布尔值是否是一个闰年。    True或False
m    月,2位数字带前导零。    '01''12'
M    月,文字,3个字母。    “Jan”
n    月无前导零。    '1''12'
N    美联社风格的月份缩写。    'Jan.''Feb.''March''May'
o    ISO-8601周编号    '1999'
O    与格林威治时间的差,单位小时。    '+0200'
P    时间为12小时    '1 am''1:30 pm''midnight''noon''12:30 pm'>
r    RFC 5322格式化日期。    'Thu, 21 Dec 2000 16:01:07 +0200'
s    秒,带前导零的2位数字。    '00''59'
S    一个月的英文序数后缀,2个字符。    'st''nd''rd''th'
t    给定月份的天数。    28 to 31
T    本机的时区。    'EST''MDT'
u    微秒。    000000 to 999999
U    自Unix Epoch以来的秒数(1970年1月1日00:00:00 UTC)。     
w    星期几,数字无前导零。    '0'(星期日)至'6'(星期六)
W    ISO-8601周数,周数从星期一开始。    1,53
y    年份,2位数字。    '99'
Y    年,4位数。    '1999'
z    一年中的日子    0到365
Z    时区偏移量,单位为秒。    -43200到43200
范例:

{{ value|date:"D d M Y" }}

如果value是一个datetime对象,比如datetime.datetime.now(),输出将是字符串'Wed 09 Jan 2008'。

可以将date与time过滤器结合使用,以呈现datetime值的完整表示形式。 例如。:

{{ value|date:"D d M Y" }} {{ value|time:"H:i" }}
date类型补充

  

ORM对单表的增删改查

 添加数据

方式一:
b=Book(name="PHP",price=80,pub_date="2019-2-20",author="lili")
b.save()
return HttpResponse("添加成功")


方式二:
Book.objects.create(name="python",price=88,pub_date="2019-2-21",author="alex")
return HttpResponse("添加成功")

  

删除数据

 #删除数据肯定需要查询数据,我们使用filter进行过滤,只选择作者为lili的记录,然后删除
    Book.objects.filter(author="lili").delete()
    return HttpResponse("删除成功")

  

修改数据

 # 方式一:
    Book.objects.filter(author="yuan").update(price=999)
    return HttpResponse("修改成功")

    # 方式二:
    b = Book.objects.get(author="yuan")
    b.price = 100
    b.save()
    return HttpResponse("修改成功")

  

 注意:

get与filter的区别
get只取一条记录,如果数据库里面只有一条符合的数据,不会报错,如果有多条或者零条,则会报错。
filter返回一组数据,可迭代。

update一定是对一个集合整体的修改,所以get得到是一个实例化对象,是没有update方法的,只能使用类方法操作。
View Code

简单查询

查询API

# 查询相关API:

#  <1>filter(**kwargs):      它包含了与所给筛选条件相匹配的对象

#  <2>all():                 查询所有结果

#  <3>get(**kwargs):         返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。

#-----------下面的方法都是对查询的结果再进行处理:比如 objects.filter.values()--------

#  <4>values(*field):        返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一系列 model的实例化对象,而是一个可迭代的字典序列
                                     
#  <5>exclude(**kwargs):     它包含了与所给筛选条件不匹配的对象

#  <6>order_by(*field):      对查询结果排序

#  <7>reverse():             对查询结果反向排序

#  <8>distinct():            从返回结果中剔除重复纪录

#  <9>values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列

#  <10>count():              返回数据库中匹配查询(QuerySet)的对象数量。

# <11>first():               返回第一条记录

# <12>last():                返回最后一条记录

#  <13>exists():             如果QuerySet包含数据,就返回True,否则返回False。
View Code

例子

 # 选择作者为lili的记录,只输出name字段(元组的形式输出)
    ret1 = Book.objects.filter(author="lili").values("name")

    # 选择作者为Tom的记录,输出name,price字段
    ret2 = Book.objects.filter(author="Tom").values("name","price")

    # 选择作者为alex的记录,输出name,price字段(以列表的形式输出)
    ret3 = Book.objects.filter(author="alex").values_list("name","price")

    # 选择排除作者为lili的记录,输出name,price字段
    ret4 = Book.objects.exclude(author="lili").values("name","price")

    # 选择作者为yuan的记录,进行去重
    book_list = Book.objects.all().values("name").distinct()

    # 查询数据库所以记录行数
    book_count = Book.objects.all().count()

  

具体演示

html代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div class="header">
    <div>
        <a href="/adddate/">添加数据</a><br>
        <a href="/deletedate/">删除数据</a><br>
        <a href="/alterdate/">修改数据</a><br>
        <a href="/enquiredate/">查询数据</a><br>
    </div>
    <div>
        {% for obj in book_list %}
            <li>{{ obj.name }} {{ obj.price }} {{ obj.pub_date }} {{ obj.author}}</li>
        {% endfor %}

    </div>

</div>
</body>
</html>
View Code

 

urls.py

from django.contrib import admin
from django.urls import path
from blog import  views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/',views.index),
    path('adddate/',views.adddate),
    path('deletedate/',views.deletedate),
    path('alterdate/',views.alterdate),
    path('enquiredate/',views.enquiredate),


]
View Code

views.py

from django.shortcuts import render,HttpResponse,redirect
from blog.models import *
# Create your views here.


def index(req):
    return render(req,'index.html')

def adddate(req):

    # 方式一:
    b = Book(name="C#", price=75, pub_date="2019-2-18",author = "Ken")
    b.save()
    return HttpResponse("添加成功")

    # 方式二:
    # Book.objects.create(name="python", price=88, pub_date="2019-2-21",author = "alex")
    # return HttpResponse("添加成功")


def deletedate(req):
    #删除数据肯定需要查询数据,我们使用filter进行过滤,只选择作者为lili的记录,然后删除
    Book.objects.filter(author="lili").delete()
    return HttpResponse("删除成功")


def alterdate(req):
    # 方式一:
    Book.objects.filter(author="lili").update(price=999)
    return HttpResponse("修改成功")

    # 方式二:
    # b = Book.objects.get(author="yuan")
    # b.price = 100
    # b.save()
    # return HttpResponse("修改成功")
def enquiredate(req):
    # 选择作者为lili的记录,只输出name字段(元组的形式输出)
    ret1 = Book.objects.filter(author="lili").values("name")

    # 选择作者为Tom的记录,输出name,price字段
    ret2 = Book.objects.filter(author="Tom").values("name","price")

    # 选择作者为alex的记录,输出name,price字段(以列表的形式输出)
    ret3 = Book.objects.filter(author="alex").values_list("name","price")

    # 选择排除作者为lili的记录,输出name,price字段
    ret4 = Book.objects.exclude(author="lili").values("name","price")

    # 选择作者为yuan的记录,进行去重
    book_list = Book.objects.all().values("name").distinct()

    # 查询数据库所以记录行数
    book_count = Book.objects.all().count()

    print(ret1)
    print(ret2)
    print(ret3)
    print(ret4)
    print(book_list)
    print(book_count)
    book_list = Book.objects.all()
    return render(req, "index.html", {"book_list": book_list})
View Code

Django之Models(一)
Django之Models(一)
数据库配置
模型代码参数解析
分析代码
 模型常用的字段类型参数
 
 Field重要参数
ORM对单表的增删改查
 添加数据
删除数据
修改数据
简单查询
具体演示
 
查询的补充
扩展查询

Django之Models(一)
Django之Models(一)
数据库配置
模型代码参数解析
分析代码
 模型常用的字段类型参数
 
 Field重要参数
ORM对单表的增删改查
 添加数据
删除数据
修改数据
简单查询
具体演示
 
查询的补充
扩展查询

 Django之Models(一)
Django之Models(一)
数据库配置
模型代码参数解析
分析代码
 模型常用的字段类型参数
 
 Field重要参数
ORM对单表的增删改查
 添加数据
删除数据
修改数据
简单查询
具体演示
 
查询的补充
扩展查询

Django之Models(一)
Django之Models(一)
数据库配置
模型代码参数解析
分析代码
 模型常用的字段类型参数
 
 Field重要参数
ORM对单表的增删改查
 添加数据
删除数据
修改数据
简单查询
具体演示
 
查询的补充
扩展查询

 

查询的补充

扩展查询

#扩展查询,有时候DJANGO的查询API不能方便的设置查询条件,提供了另外的扩展查询方法extra:
#extra(select=None, where=None, params=None, tables=None,order_by=None, select_params=None

(1)  Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
(2)  Blog.objects.extra(
        select=SortedDict([('a', '%s'), ('b', '%s')]),
        select_params=('one', 'two'))

(3)  q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
     q = q.extra(order_by = ['-is_recent'])

(4)  Entry.objects.extra(where=['headline=%s'], params=['Lennon'])  

extra

  

惰性机制:

所谓惰性机制:Publisher.objects.all()或者.filter()等都只是返回了一个QuerySet(查询结果集对象),它并不会马上执行sql,而是当调用QuerySet的时候才执行。

QuerySet特点:

       <1>  可迭代的

       <2>  可切片

#objs=models.Book.objects.all()#[obj1,obj2,ob3...]

    #QuerySet:   可迭代

    # for obj in objs:#每一obj就是一个行对象
    #     print("obj:",obj)
    # QuerySet:  可切片

    # print(objs[1])
    # print(objs[1:4])
    # print(objs[::-1])
View Code

QuerySet的高效使用

<1>Django的queryset是惰性的

     Django的queryset对应于数据库的若干记录(row),通过可选的查询来过滤。例如,下面的代码会得
     到数据库中名字为‘Dave’的所有的人:person_set = Person.objects.filter(first_name="Dave")
     上面的代码并没有运行任何的数据库查询。你可以使用person_set,给它加上一些过滤条件,或者将它传给某个函数,
     这些操作都不会发送给数据库。这是对的,因为数据库查询是显著影响web应用性能的因素之一。

<2>要真正从数据库获得数据,你可以遍历queryset或者使用if queryset,总之你用到数据时就会执行sql.
   为了验证这些,需要在settings里加入 LOGGING(验证方式)
        obj=models.Book.objects.filter(id=3)
        # for i in obj:
        #     print(i)

        # if obj:
        #     print("ok")

<3>queryset是具有cache的
     当你遍历queryset时,所有匹配的记录会从数据库获取,然后转换成Django的model。这被称为执行
    (evaluation).这些model会保存在queryset内置的cache中,这样如果你再次遍历这个queryset,
     你不需要重复运行通用的查询。
        obj=models.Book.objects.filter(id=3)

        # for i in obj:
        #     print(i)
                          ## models.Book.objects.filter(id=3).update(title="GO")
                          ## obj_new=models.Book.objects.filter(id=3)
        # for i in obj:
        #     print(i)   #LOGGING只会打印一次

<4>
     简单的使用if语句进行判断也会完全执行整个queryset并且把数据放入cache,虽然你并不需要这些
     数据!为了避免这个,可以用exists()方法来检查是否有数据:

            obj = Book.objects.filter(id=4)
            #  exists()的检查可以避免数据放入queryset的cache。
            if obj.exists():
                print("hello world!")

<5>当queryset非常巨大时,cache会成为问题

     处理成千上万的记录时,将它们一次装入内存是很浪费的。更糟糕的是,巨大的queryset可能会锁住系统
     进程,让你的程序濒临崩溃。要避免在遍历数据的同时产生queryset cache,可以使用iterator()方法
     来获取数据,处理完数据就将其丢弃。
        objs = Book.objects.all().iterator()
        # iterator()可以一次只从数据库获取少量数据,这样可以节省内存
        for obj in objs:
            print(obj.name)
        #BUT,再次遍历没有打印,因为迭代器已经在上一次遍历(next)到最后一次了,没得遍历了
        for obj in objs:
            print(obj.name)

     #当然,使用iterator()方法来防止生成cache,意味着遍历同一个queryset时会重复执行查询。所以使
     #用iterator()的时候要当心,确保你的代码在操作一个大的queryset时没有重复执行查询

总结:
    queryset的cache是用于减少程序对数据库的查询,在通常的使用下会保证只有在需要的时候才会查询数据库。
使用exists()和iterator()方法可以优化程序对内存的使用。不过,由于它们并不会生成queryset cache,可能
会造成额外的数据库查询。
View Code

对象查询,单表条件查询

   # 正向查找
    ret1=models.Book.objects.first()
    print(ret1.title)
    print(ret1.price)
    print(ret1.publisher)
    print(ret1.publisher.name)  #因为一对多的关系所以ret1.publisher是一个对象,而不是一个queryset集合

    # 反向查找
    ret2=models.Publish.objects.last()
    print(ret2.name)
    print(ret2.city)
    #如何拿到与它绑定的Book对象呢?
    print(ret2.book_set.all()) #ret2.book_set是一个queryset集合

#---------------了不起的双下划线(__)之单表条件查询----------------

#    models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值
#
#    models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
#    models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
#
#    models.Tb1.objects.filter(name__contains="ven")
#    models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
#
#    models.Tb1.objects.filter(id__range=[1, 2])   # 范围bettwen and
#
#    startswith,istartswith, endswith, iendswith,

#----------------了不起的双下划线(__)之多表条件关联查询---------------

# 正向查找(条件)

#     ret3=models.Book.objects.filter(title='Python').values('id')
#     print(ret3)#[{'id': 1}]
View Code
注意:除first,last,get取到的是一个实例对象,其他查询方法获得的是一个QuerySet的集合对象。