一、数据库的配置

1. 数据库支持

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

 <1> sqlite

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

<2> mysql

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

2. mysql驱动程序

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

3. setting配置

在django的项目中会默认使用sqlite数据库,在settings里有如下设置:

如果我们想要更改数据库,需要修改如下:

DATABASES = {'default': {'ENGINE': 'django.db.backends.mysql', 'NAME': 'books',    #你的数据库名称'USER': 'root',   #你的数据库用户名'PASSWORD': '', #你的数据库密码'HOST': '', #你的数据库主机,留空默认为localhost'PORT': '3306', #你的数据库端口}
}

NAME即数据库的名字,在mysql连接前该数据库必须已经创建,而上面的sqlite数据库下的db.sqlite3则是项目自动创建USER和PASSWORD分别是数据库的用户名和密码。设置完后,再启动我们的Django项目前,我们需要激活我们的mysql。然后,启动项目,会报错:no module named MySQLdb这是因为django默认你导入的驱动是MySQLdb,可是MySQLdb对于py3有很大问题,所以我们需要的驱动是PyMySQL所以,我们只需要找到项目名文件下的__init__,在里面写入:
import pymysql
pymysql.install_as_MySQLdb()

4. 使用pycharm连接mysql数据库

<1> 开启mysql服务

<2> 下载驱动程序

<3> 测试并连接

常见错误:

08001 时区错误

解决方法:修改时区为“+8:00”

再次连接即可

二、Django的ORM(对象关系映射)

用于实现面向对象编程语言里不同类型系统的数据之间的转换,换言之,就是用面向对象的方式去操作数据库的创建表以及增删改查等操作

优点: 1 ORM使得我们的通用数据库交互变得简单易行,而且完全不用考虑该死的SQL语句。快速开发,由此而来。

          2 可以避免一些新手程序猿写sql语句带来的性能问题。

缺点:1  性能有所牺牲,不过现在的各种ORM框架都在尝试各种方法,比如缓存,延迟加载登来减轻这个问题。效果很显著。

         2  对于个别复杂查询,ORM仍然力不从心,为了解决这个问题,ORM一般也支持写raw sql。

表模型的创建

实例:我们来假定下面这些概念,字段和关系

作者模型:一个作者有姓名。

作者详细模型:把作者的详情放到详情表,包含性别,email地址和出生日期,作者详情模型和作者模型之间是一对一的关系(one-to-one)(类似于每个人和他的身份证之间的关系),在大多数情况下我们没有必要将他们拆分成两张表,这里只是引出一对一的概念。

出版商模型:出版商有名称,地址,所在城市,省,国家和网站。

书籍模型:书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many),一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many),也被称作外键。

from django.db import models
class Publish(models.Model):name = models.CharField(max_length=30, verbose_name="名称")address = models.CharField("地址", max_length=50)city = models.CharField('城市',max_length=60)state_province = models.CharField(max_length=30)country = models.CharField(max_length=50)website = models.URLField()class Meta:verbose_name = '出版商'verbose_name_plural = verbose_namedef __str__(self):return self.nameclass Author(models.Model):name = models.CharField(max_length=30)def __str__(self):return self.nameclass AuthorDetail(models.Model):sex = models.BooleanField(max_length=1, choices=((0, '男'),(1, '女'),))email = models.EmailField()address = models.CharField(max_length=50)birthday = models.DateField()author = models.OneToOneField(Author)class Book(models.Model):title = models.CharField(max_length=100)authors = models.ManyToManyField(Author)publish = models.ForeignKey(Publish)publication_date = models.DateField()price=models.DecimalField(max_digits=5,decimal_places=2,default=10)def __str__(self):return self.title

注意1:记得在settings里的INSTALLED_APPS中加入'app01',然后再同步数据库。

注意2: models.ForeignKey("Publish") & models.ForeignKey(Publish)

分析代码:

<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参数.

其他字段

    BigAutoField(AutoField)- bigint自增列,必须填入参数 primary_key=True注:当model中如果没有自增列,则自动会创建一个列名为id的列from django.db import modelsclass UserInfo(models.Model):# 自动创建一个列名为id的且为自增的整数列username = models.CharField(max_length=32)class Group(models.Model):# 自定义自增列nid = models.AutoField(primary_key=True)name = models.CharField(max_length=32)SmallIntegerField(IntegerField):- 小整数 -32768 ~ 32767PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)- 正小整数 0 ~ 32767IntegerField(Field)- 整数列(有符号的) -2147483648 ~ 2147483647PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)- 正整数 0 ~ 2147483647BigIntegerField(IntegerField):- 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807GenericIPAddressField(Field)- 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6- 参数:protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both"UUIDField(Field)- 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证TimeField(DateTimeCheckMixin, Field)- 时间格式      HH:MM[:ss[.uuuuuu]]DurationField(Field)- 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型DecimalField(Field)- 10进制小数- 参数:max_digits,小数总长度decimal_places,小数位长度BinaryField(Field)- 二进制类型

Field重要参数

    null                数据库中字段是否可以为空db_column           数据库中字段的列名default             数据库中字段的默认值primary_key         数据库中字段是否为主键db_index            数据库中字段是否可以建立索引unique              数据库中字段是否可以建立唯一索引unique_for_date     数据库中字段【日期】部分是否可以建立唯一索引unique_for_month    数据库中字段【月】部分是否可以建立唯一索引unique_for_year     数据库中字段【年】部分是否可以建立唯一索引verbose_name        Admin中显示的字段名称blank               Admin中是否允许用户输入为空editable            Admin中是否可以编辑help_text           Admin中该字段的提示信息choices             Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1)error_messages      自定义错误信息(字典类型),从而定制想要显示的错误信息;字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date如:{'null': "不能为空.", 'invalid': '格式错误'}validators          自定义错误验证(列表类型),从而定制想要的验证规则from django.core.validators import RegexValidatorfrom django.core.validators import EmailValidator,URLValidator,DecimalValidator,\MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator如:test = models.CharField(max_length=32,error_messages={'c1': '优先错信息1','c2': '优先错信息2','c3': '优先错信息3',},validators=[RegexValidator(regex='root_\d+', message='错误了', code='c1'),RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'),EmailValidator(message='又错误了', code='c3'), ])

多表关系字段参数

ForeignKey(ForeignObject) # ForeignObject(RelatedField)to,                         # 要进行关联的表名to_field=None,              # 要关联的表中的字段名称on_delete=None,             # 当删除关联表中的数据时,当前表与其关联的行的行为- models.CASCADE,删除关联数据,与之关联也删除- models.DO_NOTHING,删除关联数据,引发错误IntegrityError- models.PROTECT,删除关联数据,引发错误ProtectedError- models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)- models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)- models.SET,删除关联数据,a. 与之关联的值设置为指定值,设置:models.SET(值)b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)def func():return 10class MyModel(models.Model):user = models.ForeignKey(to="User",to_field="id"on_delete=models.SET(func),)related_name=None,          # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()related_query_name=None,    # 反向操作时,使用的连接前缀,用于替换【表名】     如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')limit_choices_to=None,      # 在Admin或ModelForm中显示关联数据时,提供的条件:# 如:- limit_choices_to={'nid__gt': 5}- limit_choices_to=lambda : {'nid__gt': 5}from django.db.models import Q- limit_choices_to=Q(nid__gt=10)- limit_choices_to=Q(nid=8) | Q(nid__gt=10)- limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')db_constraint=True          # 是否在数据库中创建外键约束parent_link=False           # 在Admin中是否显示关联数据OneToOneField(ForeignKey)to,                         # 要进行关联的表名to_field=None               # 要关联的表中的字段名称on_delete=None,             # 当删除关联表中的数据时,当前表与其关联的行的行为###### 对于一对一 ####### 1. 一对一其实就是 一对多 + 唯一索引# 2.当两个类之间有继承关系时,默认会创建一个一对一字段# 如下会在A表中额外增加一个c_ptr_id列且唯一:class C(models.Model):nid = models.AutoField(primary_key=True)part = models.CharField(max_length=12)class A(C):id = models.AutoField(primary_key=True)code = models.CharField(max_length=1)ManyToManyField(RelatedField)to,                         # 要进行关联的表名related_name=None,          # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()related_query_name=None,    # 反向操作时,使用的连接前缀,用于替换【表名】     如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')limit_choices_to=None,      # 在Admin或ModelForm中显示关联数据时,提供的条件:# 如:- limit_choices_to={'nid__gt': 5}- limit_choices_to=lambda : {'nid__gt': 5}from django.db.models import Q- limit_choices_to=Q(nid__gt=10)- limit_choices_to=Q(nid=8) | Q(nid__gt=10)- limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')symmetrical=None,           # 仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段# 做如下操作时,不同的symmetrical会有不同的可选字段models.BB.objects.filter(...)# 可选字段有:code, id, m1class BB(models.Model):code = models.CharField(max_length=12)m1 = models.ManyToManyField('self',symmetrical=True)# 可选字段有: bb, code, id, m1class BB(models.Model):code = models.CharField(max_length=12)m1 = models.ManyToManyField('self',symmetrical=False)through=None,               # 自定义第三张表时,使用字段用于指定关系表through_fields=None,        # 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表from django.db import modelsclass Person(models.Model):name = models.CharField(max_length=50)class Group(models.Model):name = models.CharField(max_length=128)members = models.ManyToManyField(Person,through='Membership',through_fields=('group', 'person'),)class Membership(models.Model):group = models.ForeignKey(Group, on_delete=models.CASCADE)person = models.ForeignKey(Person, on_delete=models.CASCADE)inviter = models.ForeignKey(Person,on_delete=models.CASCADE,related_name="membership_invites",)invite_reason = models.CharField(max_length=64)db_constraint=True,         # 是否在数据库中创建外键约束db_table=None,              # 默认创建第三张表时,数据库中表的名称

三、ORM对单表的操作

在setting文件里加入以下代码可以实时显示操作对应的SQL语句

LOGGING = {'version': 1,'disable_existing_loggers': False,'handlers': {'console': {'level': 'DEBUG','class': 'logging.StreamHandler',},},'loggers': {'django.db.backends': {'handlers': ['console'],'propagate': True,'level': 'DEBUG',},}
}

1. 增

from app01.models import *#create方式一:   Author.objects.create(name='Alvin')#create方式二:   Author.objects.create(**{"name":"alex"})#save方式一:     author=Author(name="alvin")author.save()#save方式二:     author=Author()author.name="alvin"author.save()

    # 方式一b = Book(name='python基础', price=99, author='alex', pub_date='2017-12-12')b.save()# 方式二Book.objects.create(name='Linux基础', price=49, author='lsf', pub_date='2015-03-12')

2. 改

    # 方式一Book.objects.filter(author='alex').update(price='999')  # 不能用get(author='alex')# 方式二b = Book.objects.get(author='lsf')b.price = 120b.save()

注意:

<1>第一种方式修改不能用get的原因是:update是QuerySet对象的方法,get返回的是一个model对象,它没有update方法,而filter返回的是一个QuerySet对象(filter里面的条件可能有多个条件符合,比如name='alvin',可能有两个name='alvin'的行数据)。

<2>save方法会将所有属性重新设定一遍,效率低,推荐使用第一种方式

3. 删

Book.objects.filter(author='lsf').delete()

4. 查

# 查询相关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。

    booklist = Book.objects.filter(author='alex')  # 得到一个集合booklist = Book.objects.all()booklist = Book.objects.all()[::2]booklist = Book.objects.all()[::2]booklist = Book.objects.get(name='Go')  # 只能取出一条结果时才不报错booklist = Book.objects.first()booklist = Book.objects.last()booklist = Book.objects.exclude(author='alex')print(booklist)  # <QuerySet [<Book: Book object (Linux基础)>, <Book: Book object (PHP)>]>booklist = Book.objects.filter(author='alex').reverse()  # 倒叙booklist = Book.objects.exclude(author='alex').order_by('price')  # 排序print(booklist)  # <QuerySet [<Book: Book object (PHP)>, <Book: Book object (Linux基础)>]>ret1 = Book.objects.filter(author='alex').values('name', 'price')print(ret1)  # <QuerySet [{'name': 'GO', 'price': 55}, {'name': 'python基础', 'price': 99}]>ret2 = Book.objects.filter(author='alex').values_list('name', 'price')print(ret2)  # <QuerySet [('GO', 55), ('python基础', 99)]>booklist = Book.objects.all().values('name').distinct()  # 去重book_count = Book.objects.exclude(author='alex').count()  # 返回查询结果的数量

模糊查询(双下划线)

        # 大于,小于## models.Tb1.objects.filter(id__gt=1)              # 获取id大于1的值# models.Tb1.objects.filter(id__gte=1)              # 获取id大于等于1的值# models.Tb1.objects.filter(id__lt=10)             # 获取id小于10的值# models.Tb1.objects.filter(id__lte=10)             # 获取id小于10的值# models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值# in## models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据# models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in# isnull# Entry.objects.filter(pub_date__isnull=True)# contains## models.Tb1.objects.filter(name__contains="ven")# models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感# models.Tb1.objects.exclude(name__icontains="ven")# range## models.Tb1.objects.filter(id__range=[1, 2])   # 范围bettwen and# 其他类似## startswith,istartswith, endswith, iendswith,# order by## models.Tb1.objects.filter(name='seven').order_by('id')    # asc# models.Tb1.objects.filter(name='seven').order_by('-id')   # desc# group by## from django.db.models import Count, Min, Max, Sum# models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))# SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"# limit 、offset## models.Tb1.objects.all()[10:20]# regex正则匹配,iregex 不区分大小写## Entry.objects.get(title__regex=r'^(An?|The) +')# Entry.objects.get(title__iregex=r'^(an?|the) +')# date## Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))# Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))# year## Entry.objects.filter(pub_date__year=2005)# Entry.objects.filter(pub_date__year__gte=2005)# month## Entry.objects.filter(pub_date__month=12)# Entry.objects.filter(pub_date__month__gte=6)# day## Entry.objects.filter(pub_date__day=3)# Entry.objects.filter(pub_date__day__gte=3)# week_day## Entry.objects.filter(pub_date__week_day=2)# Entry.objects.filter(pub_date__week_day__gte=2)# hour## Event.objects.filter(timestamp__hour=23)# Event.objects.filter(time__hour=5)# Event.objects.filter(timestamp__hour__gte=12)# minute## Event.objects.filter(timestamp__minute=29)# Event.objects.filter(time__minute=46)# Event.objects.filter(timestamp__minute__gte=29)# second## Event.objects.filter(timestamp__second=31)# Event.objects.filter(time__second=2)# Event.objects.filter(timestamp__second__gte=31)    

四、多表操作

如何处理外键关系的字段如一对多的publish和多对多的authors

1. 一对多

    # 方式一:由于绑定一对多的字段,比如publish,存到数据库中的字段名叫publish_id,所以我们可以直接给这个字段设定对应值:# Book.objects.create(name='Linux', price=80, pubdate='2017-12-12', publish_id=1) # 相当于绑定了Publish表中id为1的对象# 方式二:先获取要绑定的Publish对象,再绑定给publishpublish_obj = Publish.objects.filter(name='人民出版社')[0]Book.objects.create(name='Linux', price=80, pubdate='2017-12-12', publish=publish_obj)

查(通过对象)

    book_obj = Book.objects.get(name='python')print(book_obj.price)  # 99# 一对多:book_obj.publish一定是一个对象print(book_obj.publish)  # Publish object (3)print(book_obj.publish.name)  # 南方出版社# 查询人民出版社的所有书籍# 方法一(正向查找)pub_obj = Publish.objects.get(name='人民出版社')ret = Book.objects.filter(publish=pub_obj).values('name', 'price')print(ret)  # <QuerySet [{'name': 'Linux', 'price': 80}, {'name': 'Java', 'price': 150}]># 方法二(反向查找)pub_obj = Publish.objects.get(name='人民出版社')print(pub_obj.book_set.all().values('name', 'price'))  # <QuerySet [{'name': 'Linux', 'price': 80}, {'name': 'Java', 'price': 150}]># print(type(pub_obj.book_set.all()))  # <class 'django.db.models.query.QuerySet'>

查(通过双下划线)

    book_dic = Book.objects.filter(publish__name='人民出版社').values('name', 'price')print(book_dic)# 查找python的出版社名字ret1 = Publish.objects.get(book__name='python').nameret2 = Publish.objects.filter(book__name='python').values('name')ret3 = Book.objects.get(name='python').publish.nameret4 = Book.objects.filter(name='python').values('publish__name')print(ret1, ret2, ret3, ret4)# 查找出版社在北京的书籍ret5 = Publish.objects.filter(addr='北京').values('book__name')ret6 = Book.objects.filter(publish__addr='北京').values('name')print(ret5, ret6)

2. 多对多

    book_obj = Book.objects.get(id=10)authors_objs = Author.objects.filter(age__lt=40)book_obj.authors.add(*authors_objs)author1=Author.objects.get(id=1)author2=Author.objects.filter(name='alvin')[0]book=Book.objects.get(id=1)book.authors.add(author1,author2)#等同于:book.authors.add(*[author1,author2])book.authors.remove(*[author1,author2])#-------------------book=Book.objects.filter(id__gt=1)authors=Author.objects.filter(id=1)[0]authors.book_set.add(*book)authors.book_set.remove(*book)#-------------------book.authors.add(1)book.authors.remove(1)authors.book_set.add(1)authors.book_set.remove(1)#注意: 如果第三张表是通过models.ManyToManyField()自动创建的,那么绑定关系只有上面一种方式
#     如果第三张表是自己创建的:class Book2Author(models.Model):author=models.ForeignKey("Author")Book=  models.ForeignKey("Book")
#     那么就还有一种方式:author_obj=models.Author.objects.filter(id=2)[0]book_obj  =models.Book.objects.filter(id=3)[0]s=models.Book2Author.objects.create(author_id=1,Book_id=2)s.save()s=models.Book2Author(author=author_obj,Book_id=1)s.save()

#正向
book = Book.objects.filter(id=1)book.author.clear()        #清空与book中id=1 关联的所有数据
book.author.remove(2)  #可以为id
book.author.remove(*[1,2,3,4])  #可以为列表,前面加*#反向
author = Author.objects.filter(id=1)
author.book_set.clear() #清空与boy中id=1 关联的所有数据

    obj=Book.objects.filter(id=1)[0]author=Author.objects.filter(id__gt=2)obj.author.clear()obj.author.add(*author)

# 多对多# 查找python的作者Book.objects.filter(name='python').values('authors__name')Author.objects.filter(book__name='python').values('name')# 查找出版社在北京的书籍的名字和作者Book.objects.filter(publish__addr='北京').values('name', 'authors__name')Author.objects.filter(book__publish__addr='北京').values('book__name', 'name')Publish.objects.filter(addr='北京').values('book__name', 'book__authors__name')# 查找作者为alex的书的出版社名字Author.objects.filter(name='alex').values('book__publish__name')Book.objects.filter(authors__name='alex').values('publish__name')Publish.objects.filter(book__authors__name='alex').values('name')

3. 聚合查询和分组查询

 <1>aggregate(*args, **kwargs)

通过对QuerySet进行计算,返回一个聚合值的字典。aggregate()中每一个参数都指定一个包含在字典中的返回值。即在查询集上生成聚合。

from django.db.models import Avg,Min,Sum,Max从整个查询集生成统计值。比如,你想要计算所有在售书的平均价钱。Django的查询语法提供了一种方式描述所有
图书的集合。>>> Book.objects.all().aggregate(Avg('price'))
{'price__avg': 34.35}aggregate()子句的参数描述了我们想要计算的聚合值,在这个例子中,是Book模型中price字段的平均值aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的
标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。如果你想要为聚合值指定
一个名称,可以向聚合子句提供它:
>>> Book.objects.aggregate(average_price=Avg('price'))
{'average_price': 34.35}如果你也想知道所有图书价格的最大值和最小值,可以这样查询:
>>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price'))
{'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')}

<2>annotate(*args, **kwargs)

可以通过计算查询结果中每一个对象所关联的对象集合,从而得出总计值(也可以是平均值或总和),即为查询集的每一项生成聚合。

查询alex出的书总价格

查询各个作者出的书的总价格,这里就涉及到分组了,分组条件是authors__name

查询各个出版社最便宜的书价是多少

4. F查询和Q查询

仅仅靠单一的关键字参数查询已经很难满足查询要求。此时Django为我们提供了F和Q查询:

# F 使用查询条件的值,专门取对象中某列值的操作# from django.db.models import F# models.Tb1.objects.update(num=F('num')+1)# Q 构建搜索条件from django.db.models import Q#1 Q对象(django.db.models.Q)可以对关键字参数进行封装,从而更好地应用多个查询q1=models.Book.objects.filter(Q(title__startswith='P')).all()print(q1)#[<Book: Python>, <Book: Perl>]# 2、可以组合使用&,|操作符,当一个操作符是用于两个Q的对象,它产生一个新的Q对象。Q(title__startswith='P') | Q(title__startswith='J')# 3、Q对象可以用~操作符放在前面表示否定,也可允许否定与不否定形式的组合Q(title__startswith='P') | ~Q(pub_date__year=2005)# 4、应用范围:# Each lookup function that takes keyword-arguments (e.g. filter(),#  exclude(), get()) can also be passed one or more Q objects as# positional (not-named) arguments. If you provide multiple Q object# arguments to a lookup function, the arguments will be “AND”ed# together. For example:Book.objects.get(Q(title__startswith='P'),Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))#sql:# SELECT * from polls WHERE question LIKE 'P%'#     AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')# import datetime# e=datetime.date(2005,5,6)  #2005-05-06# 5、Q对象可以与关键字参数查询一起使用,不过一定要把Q对象放在关键字参数查询的前面。# 正确:Book.objects.get(Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),title__startswith='P')# 错误:Book.objects.get(question__startswith='P',Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))

5. 其他操作

def select_related(self, *fields)性能相关:表之间进行join连表操作,一次性获取关联的数据。model.tb.objects.all().select_related()model.tb.objects.all().select_related('外键字段')model.tb.objects.all().select_related('外键字段__外键字段')def prefetch_related(self, *lookups)性能相关:多表连表操作时速度会慢,使用其执行多次SQL查询在Python代码中实现连表操作。# 获取所有用户表# 获取用户类型表where id in (用户表中的查到的所有用户ID)models.UserInfo.objects.prefetch_related('外键字段')from django.db.models import Count, Case, When, IntegerFieldArticle.objects.annotate(numviews=Count(Case(When(readership__what_time__lt=treshold, then=1),output_field=CharField(),)))students = Student.objects.all().annotate(num_excused_absences=models.Sum(models.Case(models.When(absence__type='Excused', then=1),default=0,output_field=models.IntegerField())))def distinct(self, *field_names)# 用于distinct去重models.UserInfo.objects.values('nid').distinct()# select distinct nid from userinfo注:只有在PostgreSQL中才能使用distinct进行去重def order_by(self, *field_names)# 用于排序models.UserInfo.objects.all().order_by('-id','age')def extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)# 构造额外的查询条件或者映射,如:子查询Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))Entry.objects.extra(where=['headline=%s'], params=['Lennon'])Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])# select id, select id from tb where id > 1 as new_id order by nid descdef reverse(self):# 倒序models.UserInfo.objects.all().order_by('-nid').reverse()# 注:如果存在order_by,reverse则是倒序,如果多个排序则一一倒序def defer(self, *fields):models.UserInfo.objects.defer('username','id')或models.UserInfo.objects.filter(...).defer('username','id')#映射中排除某列数据def only(self, *fields):#仅取某个表中的数据models.UserInfo.objects.only('username','id')或models.UserInfo.objects.filter(...).only('username','id')# 与values的区别:# 使用only得到的列表里封装的是对象 [obj{id,name},obj,obj],使用obj.age依然可以拿到值,但会重新发起一次sql请求# values得到的列表是字典 [{id, name},{id,name}]def using(self, alias):指定使用的数据库,参数为别名(setting中的设置)#

def raw(self, raw_query, params=None, translations=None, using=None):# 执行原生SQLmodels.UserInfo.objects.raw('select * from userinfo')# 如果SQL是其他表时,必须将名字设置为当前UserInfo对象的主键列名models.UserInfo.objects.raw('select id as nid from 其他表')# 为原生SQL设置参数models.UserInfo.objects.raw('select id as nid from userinfo where nid>%s', params=[12,])# 将获取的到列名转换为指定列名name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'}Person.objects.raw('SELECT * FROM some_other_table', translations=name_map)# 指定数据库models.UserInfo.objects.raw('select * from userinfo', using="default")################### 原生SQL ###################from django.db import connection, connectionscursor = connection.cursor()  # cursor = connections['default'].cursor()cursor.execute("""SELECT * from auth_user where id = %s""", [1])row = cursor.fetchone() # fetchall()/fetchmany(..)

def none(self):# 空QuerySet对象def dates(self, field_name, kind, order='ASC'):# 根据时间进行某一部分进行去重查找并截取指定内容# kind只能是:"year"(年), "month"(年-月), "day"(年-月-日)# order只能是:"ASC"  "DESC"# 并获取转换后的时间- year : 年-01-01- month: 年-月-01- day  : 年-月-日models.DatePlus.objects.dates('ctime','day','DESC')def datetimes(self, field_name, kind, order='ASC', tzinfo=None):# 根据时间进行某一部分进行去重查找并截取指定内容,将时间转换为指定时区时间# kind只能是 "year", "month", "day", "hour", "minute", "second"# order只能是:"ASC"  "DESC"# tzinfo时区对象models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.UTC)models.DDD.objects.datetimes('ctime','hour',tzinfo=pytz.timezone('Asia/Shanghai'))"""pip3 install pytzimport pytzpytz.all_timezonespytz.timezone(‘Asia/Shanghai’)"""

def bulk_create(self, objs, batch_size=None):# 批量插入# batch_size表示一次插入的个数objs = [models.DDD(name='r11'),models.DDD(name='r22')]models.DDD.objects.bulk_create(objs, 10)def get_or_create(self, defaults=None, **kwargs):# 如果存在,则获取,否则,创建# defaults 指定创建时,其他字段的值obj, created = models.UserInfo.objects.get_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 2})def update_or_create(self, defaults=None, **kwargs):# 如果存在,则更新,否则,创建# defaults 指定创建时或更新时的其他字段obj, created = models.UserInfo.objects.update_or_create(username='root1', defaults={'email': '1111111','u_id': 2, 't_id': 1})def in_bulk(self, id_list=None):# 根据主键ID进行查找id_list = [11,21,31]models.DDD.objects.in_bulk(id_list)

转载于:https://www.cnblogs.com/lsf123456/p/11376251.html

Django-07-Model操作相关推荐

  1. Django之Model操作

    Django之Model操作 本节内容 字段 字段参数 元信息 多表关系及参数 ORM操作 1. 字段 字段列表 AutoField(Field)- int自增列,必须填入参数 primary_key ...

  2. Python之路【第二十二篇】:Django之Model操作

    Django之Model操作 一.字段 AutoField(Field)- int自增列,必须填入参数 primary_key=TrueBigAutoField(AutoField)- bigint自 ...

  3. python Django Session,CSRF,Model操作,Form验证,中间件,缓存,信号

    Django Session,CSRF,Model操作,Form验证,中间件,缓存,信号 Session CSRF Model 操作 Form 验证 中间件 缓存 信号 1,Session 基于coo ...

  4. Django的model查询操作 与 查询性能优化

    Django的model查询操作 与 查询性能优化 1 如何 在做ORM查询时 查看SQl的执行情况 (1) 最底层的 django.db.connection 在 django shell 中使用 ...

  5. Django中model新建数据表操作后admin页面不更新问题

    Django中model新建数据表操作后admin页面不更新问题 这种情况一般是没有在admin.py文件中进行模型的注册所导致的,打开应用文件夹下的admin.py,然后添加代码: from .mo ...

  6. Django中Model模块的操作-创建各种表结构(上)

    Django框架功能齐全自带数据库操作功能,本文主要介绍Django的ORM框架 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLd ...

  7. 西游之路——python全栈——Django之ORM操作

    Django之ORM操作 前言 Django框架功能齐全自带数据库操作功能,本文主要介绍Django的ORM框架 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计 ...

  8. django中model模型

    python manage.py dumpdata blog       # 导出blog数据 python manage.py loaddata blog_dump.json   # 导入数据  m ...

  9. Django中Model继承的三种方式

    Django中Model继承的三种方式 Django中Model的继承有三种: 1.抽象继承 2.多表继承 3.proxy model(代理model) 1.抽象继承 第一种抽象继承,创建一个通用父类 ...

  10. 【Django】ORM操作#2

    目录 必知必会的13条查询方法 单表查询之神奇的双下划线 一对多 ForeignKey 多对多 ManyToManyField 在Python脚本中调用Django环境 Django终端打印SQL语句 ...

最新文章

  1. python连接oracle批量写入_oracle大数据量python导入实践-1w/s
  2. 100. Same Tree同样的树
  3. Json序列化提示缺少编译器要求的成员“ystem.Runtime.CompilerServices.ExtensionAttribute..ctor”...
  4. linux上yum最简方法安装,yum轻松简单安装配置GCC等
  5. AX2009 的EP开发要点
  6. 详解Java动态代理机制
  7. linux网关管理,利用Linux打造安全的管理型网关
  8. SQL Server修改表结构时,不允许保存更改,阻止保存要求重新创建表的更改
  9. AD快捷键,及一些基本操作设置总结
  10. 英语报纸计算机类,报纸和电脑英语作文
  11. 广电行业编码传输系统调研
  12. H5纯页面方式手机端实现“扫一扫”功能(不是直接调起摄像头)
  13. win7锁定计算机自动关机,windows7怎么设置电脑自动关机_win7如何自动关机
  14. ndis协议驱动开发
  15. Web项目经理手册之项目经理需要铭记在心的话
  16. 分布式系统的CAP原理及其应用
  17. ERDAS 9.2安装教程
  18. 定时器输出PWM原理
  19. [论文]自主水下机器人垂直面路径跟踪静态输出反馈控制设计
  20. Python 结合Ansible 把管理资产信息自动插入到CMDB中

热门文章

  1. 多思计算机组成原理实验:模型机课程设计
  2. Android svg矢量图实现心跳动画
  3. uni-app app定位当前地理位置
  4. 今日头条如何申请优质科技领域创作者
  5. 转-如何绘制业务流程图(二)
  6. 【数字图像处理】图像信息基本概念
  7. 雷达的最大距离和雷达的非模糊距离
  8. 计算机在医院管理方面的应用,计算机在医院管理的应用
  9. 深入理解用户态和系统态
  10. 微型计算机电路基础第四版答案,微型计算机电路基础期末试卷2B