Django之Model(一)--基础篇
0、数据库配置
django默认支持sqlite,mysql, oracle,postgresql数据库。Django连接数据库默认编码使用UTF8,使用中文不需要特别设置。
- sqlite
- django默认使用sqlite的数据库,默认自带sqlite的数据库驱
- 引擎名称:django.db.backends.sqlite3
- mysql
- 引擎名称:django.db.backends.mysql
mysql引擎配置:
'defaults': {
'ENGINE': 'django.db.backends.mysql',
'NAME':'127.0.0.1',
'USER':'root',
'PASSWORD':'',
}
mysql引擎底层驱动的py3支持问题:
- mysql驱动程序
- MySQLdb(mysql python),Django默认使用改驱动,但改驱动在python3下存在兼容性问题。因此使用PyMySQL。
- PyMySQL(纯python的mysql驱动程序)
- mysql驱动python3解决方法
- 找到项目名文件下的__init__,在里面写入:
- import pymysql
- pymysql.install_as_MySQLdb()
一、Model类定义
1、Model类创建
下面这个模型类将作为本篇博客的基础模型,所有的实例都基于此。
- from django.db import models
- class Publisher(models.Model):
- name = models.CharField(max_length=30, verbose_name="名称")
- website = models.URLField()
- # book_set 反向关联一对多字段的Book
- def __unicode__(self):
- return self.name
- class Author(models.Model):
- name = models.CharField(max_length=30)
- # authordetail 反向关联一对一字段AuthorDetail表
- # book_set 反向关联一对多字段的Book
- def __unicode__(self):
- return self.name
- class AuthorDetail(models.Model):
- sex = models.BooleanField(max_length=1, choices=((0, '男'),(1, '女'),))
- author = models.OneToOneField(Author)
- # author_id隐藏字段,正向关联一对一字段的Author对象的id
- class Book(models.Model):
- title = models.CharField(max_length=100)
- authors = models.ManyToManyField(Author)
- publisher = models.ForeignKey(Publisher,null=True)
- # publisher_id隐藏字段,正向关联一对多字段的Publisher对象的id
- price=models.DecimalField(max_digits=5,decimal_places=2,default=10)
- def __unicode__(self):
- return self.title
- #coding:utf-
- from __future__ import unicode_literals
- from django.db import models
- class Publisher(models.Model):
- name = models.CharField(max_length=, verbose_name="名称")
- website = models.URLField()
- def __unicode__(self):
- return self.name
- class Author(models.Model):
- name = models.CharField(max_length=)
- def __unicode__(self):
- return self.name
- class AuthorDetail(models.Model):
- sex = models.BooleanField(max_length=, choices=((, '男'),(, '女'),))
- author = models.OneToOneField(Author)
- class Book(models.Model):
- title = models.CharField(max_length=)
- authors = models.ManyToManyField(Author,through='Book2Author')
- publisher = models.ForeignKey(Publisher)
- price=models.DecimalField(max_digits=,decimal_places=,default=)
- def __unicode__(self):
- return self.title
- class Book2Author(models.Model):
- book = models.ForeignKey(Book)
- author = models.ForeignKey(Author)
- groupname = models.CharField(max_length=)
- #默认多对多关系Django自动为我们创建了一张中间表,仅提供3个字段,两个关联表的外键字段和一个id字段。
- #这种使用自定义中间表的方式,使得我们可以自定义的为中间表添加额外的字段。当我们需要为多对多关系提供额外字段时,用此方式。
自定义多对多中间表
2、同步数据库
模型表创建和更新的时候是要使用数据库迁移命令,使模型类的改变同步到数据库。
- makemigrations #创建变更记录
- migrate #同步到数据库
3、Model类(表)关系图:
名词说明:
正向查询,从定义关系字段的类中去查询关系对象的值或值的集合。举个栗子:从AuthorDetail类中查询关联字段author对象的值。
反向查询,从本类中查询被关联对象中的值或值的集合。举个栗子:从Author对象中查询被关联字段AuthorDetail对象的值。
4、字段类型:
- 1、models.AutoField 自增列 = int(11)
- 如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。
- 2、models.CharField 字符串字段
- 必须 max_length 参数
- 3、models.BooleanField 布尔类型=tinyint(1)
- 不能为空,Blank=True
- 4、models.ComaSeparatedIntegerField 用逗号分割的数字=varchar
- 继承CharField,所以必须 max_lenght 参数
- 5、models.DateField 日期类型 date
- 对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。
- 6、models.DateTimeField 日期类型 datetime
- 同DateField的参数
- 7、models.Decimal 十进制小数类型 = decimal
- 必须指定整数位max_digits和小数位decimal_places
- 8、models.EmailField 字符串类型(正则表达式邮箱) =varchar
- 对字符串进行正则表达式
- 9、models.FloatField 浮点类型 = double
- 10、models.IntegerField 整形
- 11、models.BigIntegerField 长整形
- integer_field_ranges = {
- 'SmallIntegerField': (-32768, 32767),
- 'IntegerField': (-2147483648, 2147483647),
- 'BigIntegerField': (-9223372036854775808, 9223372036854775807),
- 'PositiveSmallIntegerField': (0, 32767),
- 'PositiveIntegerField': (0, 2147483647),
- }
- 12、models.IPAddressField 字符串类型(ip4正则表达式)
- 13、models.GenericIPAddressField 字符串类型(ip4和ip6是可选的)
- 参数protocol可以是:both、ipv4、ipv6
- 验证时,会根据设置报错
- 14、models.NullBooleanField 允许为空的布尔类型
- 15、models.PositiveIntegerFiel 正Integer
- 16、models.PositiveSmallIntegerField 正smallInteger
- 17、models.SlugField 减号、下划线、字母、数字
- 18、models.SmallIntegerField 数字
- 数据库中的字段有:tinyint、smallint、int、bigint
- 19、models.TextField 字符串=longtext
- 20、models.TimeField 时间 HH:MM[:ss[.uuuuuu]]
- 21、models.URLField 字符串,地址正则表达式
- 22、models.BinaryField 二进制
- 23、models.ImageField 图片
- 24、models.FilePathField 文件
ORM字段类型
5、字段选项:
- 1、null=True
- 数据库中字段是否可以为空
- 2、blank=True
- django的 Admin 中添加数据时是否可允许空值
- 3、primary_key = False
- 主键,对AutoField设置主键后,就会代替原来的自增 id 列
- 4、auto_now 和 auto_now_add
- auto_now 自动创建---无论添加或修改,都是当前操作的时间
- auto_now_add 自动创建---永远是创建时的时间
- 5、choices 配置可选项
- GENDER_CHOICE = (
- (u'M', u'Male'),
- (u'F', u'Female'),
- )
- gender = models.CharField(max_length=2,choices = GENDER_CHOICE)
- 6、max_length 最大长度
- 7、default 默认值
- 8、verbose_name Admin中字段的显示名称
- 9、name|db_column 数据库中的字段名称
- 10、unique=True 不允许重复
- 11、db_index = True 数据库索引
- 12、editable=True 在Admin里是否可编辑
- 13、error_messages=None 错误提示
- 14、auto_created=False 自动创建
- 15、help_text 在Admin中提示帮助信息
- 16、validators=[] 自定义数据格式验证
- 17、upload-to 上传文件路径
字段选项
6、Model类的Meta(元数据)选项:
- abstract=False True就表示模型是抽象基类
- db_table = 'music_album' 自定义数库的表名称前缀
- get_latest_by = "datefield_name" 根据时间字段datefield_name排序,latest()和earliest()方法中使用的默认字段。
- db_tablespace 当前模型所使用的数据库表空间的名字。默认值是项目设置中的DEFAULT_TABLESPACE。如果后端并不支持表空间,这个选项可以忽略。
- ordering = ['-fieldname'] 对象默认的顺序,字段前面带有'-'符号表示逆序,否则正序。排序会增加查询额外开销。
- proxy = True 它作为另一个模型的子类,将会作为一个代理模型。
- unique_together 设置联合唯一。ManyToManyField不能包含在unique_together中。
- index_together 设置联合索引。
- index_together = [
- ["pub_date", "deadline"],
- ]
- 方便起见,处理单一字段的集合时index_together = ["pub_date", "deadline"]
- verbose_name 在Admin里,个易于理解的表名称,为单数:verbose_name = "pizza"
- verbose_name_plural 在Admin里显示的表名称,为复数:verbose_name_plural = "stories",一般同verbose_name一同设置。
Meta元数据选项
二、对象CURD操作
2.1 基础对象CURD(无关联字段)
1、增
- 方法一:
- author= Author(name="鲁迅")
- author.save()
- 方法二:
- 创建对象并同时保存对象的快捷方法,存在关系字段时无法用此方法创建。
- create(**kwargs)
- Author.objects.create(name=u"鲁迅")
- 方法三:
- 批量创建
- bulk_create(objs, batch_size=None) ret=Blog.objects.bulk_create([ Author(name="徐志摩"), Author(name="李白")])
- 方法四:
- 存在就获取,不存在就创建
- get_or_create(defaults=None,**kwargs),
- defaults必须为一个字典,在创建时生效的默认值;**kwargs为查询条件。
- 创建对象时,使用**kwargs和defaults共同作用,取交集,defaults优先。
- updated_values={"name":u"美猴王"}
- a、存在就获取,查询到结果多余一个出错MultipleObjectsReturned
- ret=Author.objects.get_or_create(name=u'徐志摩',defaults=updated_values)
- ret:(<Author: 徐志摩>, False)
- b、不存在就创建
- ret=Author.objects.get_or_create(name=u'徐志摩',defaults=updated_values)
- ret:(<Author: 美猴王>, True)
- 方法五:
- 存在就更新,不存在就创建
- update_or_create(defaults=None, **kwargs)
- a、存在就更新
- updated_values={"name":u"猴王"}
- ret=Author.objects.update_or_create(defaults=updated_values,name=u"猴子")
- ret:(<Author: 猴王>, False)
- 根据给出的查询条件name=u"猴子"查找对象,查询到结果就使用defaults字典去更新对象。
- b、不存在就创建
- ret=Author.objects.update_or_create(defaults=updated_values,name=u"猴子1")
- ret:(<Author: 猴王>, True)
- defaults必须为一个字典,在创建时生效的默认值;**kwargs为查询条件。
- 创建对象时,使用**kwargs和defaults共同作用,取交集,defaults优先。
- 2、删
- 使用delete会查找出相关表中的有关联的数据行一并删除
- 方法一:
- Author.objects.filter(name="徐志摩").delete()
- (1, {u'otest.Book_authors': 0, u'otest.AuthorDetail': 0, u'otest.Author': 1})
- 方法二:
- a9=Author.objects.get(name="鲁迅")
- a9.delete()
- 3、改
- 方法一:
- update(**kwargs)返回更新的行数,批量修改
- ret=Author.objects.filter(name='秋雨').update(name="陶渊明")
- 方法二:
- 单条修改
- a7=Author.objects.get(name="清风")
- a7.name=u"宋清风"
- a7.save()
- 4、查
a、查询结果非QuertSet
- get(**kwargs)
- 在使用 get() 时,如果符合筛选条件的对象超过一个,就会抛出 MultipleObjectsReturned 异常。
- 在使用 get() 时,如果没有找到符合筛选条件的对象,就会抛出 DoesNotExist 异常。
- from django.core.exceptions import ObjectDoesNotExist
- try:
- e = Entry.objects.get(id=3)
- b = Blog.objects.get(id=1)
- except ObjectDoesNotExist:
- print("Either the entry or blog doesn't exist.")
- in_bulk(id_list)
- 接收一个主键值列表,然后根据每个主键值所其对应的对象,返回一个主键值与对象的映射字典。
- Author.objects.in_bulk([1,2,3])
- {1: <Author: 苍松>, 2: <Author: 猴王>, 3: <Author: 宋清风>}
- first() 查询第一条,一般使用前先排序,或者确定其只有一条数据。
- last() 查询最后一条,同上
- count() 返回数据库中匹配查询(QuerySet)的对象数量。 count() 不会抛出任何异常。
- exists() 如果 QuerySet 包含有数据,就返回 True 否则就返回 False。这可能是最快最简单的查询方法了。
- latest(field_name=None) ,根据时间字段 field_name 得到最新的对象。
- earliest(field_name=None), 根据时间字段 field_name 得到最老的对象。
- #F使用查询条件的值,进行数值计算
- from django.db.models import F
- Book.objects.filter(id=1).update(price=F('price')+10)
b、查询结果为QuerySet
常用方法:
- 1、filter(**kwargs)
- 过滤,返回一个新的QuerySet,包含与给定的查询参数匹配的对象。
- >>>q=Author.objects.filter(name=u"苍松")
- >>> q
- [<Author: 苍松>]
- 2、exclude(**kwargs)
- 反过滤,返回一个新的QuerySet,它包含不满足给定的查找参数的对象。功能与filter相反。
- 3、values(*fields)
- 返回一个新的QuerySet,但迭代时返回字典而不是模型实例对象。
- *fields表示需要取哪些字段,空表示取所有字段。
- >>> q=Author.objects.values("id")
- >>> q
- [{'id': 1}, {'id': 2}, {'id': 3}, {'id': 4}, {'id': 18}, {'id': 22}, {'id': 24}]
- 4、values_list(*fields, flat=False)
- 返回一个新的QuerySet,但迭代时返回元组而不是模型实例对象。
- *fields表示需要取哪些字段,空表示取所有字段。flat=True表示返回的结果为单个值而不是元组,多个字段时不能使用flat。
- >>> q=Author.objects.values_list("id")
- >>> q
- [(1,), (2,), (3,), (4,), (18,), (22,), (24,)]
- >>> q=Author.objects.values_list("id",flat=True)
- >>> q
- [1, 2, 3, 4, 18, 22, 24]
- 5、all()
- 返回当前 QuerySet所有对象。
- 6、select_related(*field)
- 返回一个QuerySet,使用JOIN语句连表查询。它会在执行查询时自动跟踪外键关系,一次读取所有外键关联的字段,并尽可能地深入遍历外键连接,以减少数据库的查询。但数据关系链复杂的查询需要慎用。仅对外键生效。
- 7、prefetch_related(*field)
- prefetch_related()的解决方法是,分别查询每个表,然后用Python处理他们之间的关系。外键和多对多都生效。
- 8、order_by(*fields)
- 排序,返回一个新的QuerySet,隐式的是升序排序,-name表示根据name降序
- >>> q=Author.objects.order_by("name")
- >>> q
- [<Author: au>, <Author: 宋清风>, <Author: 猴王>, <Author: 美猴王>, <Author: 苍松>, <Author: 赵清风>, <Author: 陶渊明>]
- >>> q=Author.objects.order_by("-name")
- >>> q
- [<Author: 陶渊明>, <Author: 赵清风>, <Author: 苍松>, <Author: 美猴王>, <Author: 猴王>, <Author: 宋清风>, <Author: au>]
- 9、reverse()
- reverse()方法返回反向排序的QuerySet。
- 必须对一个已经排序过的queryset(也就是q.ordered=True)执行reverse()才有效果。
- 10、distinct([*fields])
- 去重复。返回一个在SQL 查询中使用SELECT DISTINCT 的新QuerySet。
- 1、dates(field, kind, order='ASC')
- field 是你的 model 中的 DateField 字段名称。
- kind 是 “year”, “month” 或 “day” 之一。 每个 datetime.date对象都会根据所给的 type 进行截减。
- “year” 返回所有时间值中非重复的年分列表。
- “month” 返回所有时间值中非重复的年/月列表。
- “day” 返回所有时间值中非重复的年/月/日列表。
- order, 默认是 ‘ASC’,只有两个取值 ‘ASC’ 或 ‘DESC’。它决定结果如何排序。
- 2、datetimes(field, kind, order=’ASC’)
- 返回一个 DateTimeQuerySet,参数与dates类似,多了"hour", "minute" ,"second"
- 3、none()
- 返回一个 EmptyQuerySet,它是一个运行时只返回空列表的 QuerySet。它经常用在这种场合:你要返回一个空列表,但是调用者却需要接收一个 QuerySet 对象。
- 4、defer(*fields)
- 将不想载入的字段的名称传给 defer() 方法,就可以做到延后载入。
- 在某些数据复杂的环境下,你的 model 可能包含非常多的字段,可能某些字段包含非常多的数据(比如,文档字段),或者将其转化为Python对象会消耗非常多的资源。在这种情况下,有时你可能并不需要这种字段的信息,那么你可以让 Django 不读取它们的数据。
- 5、only(*fields)
- only() 方法或多或少与 defer() 的作用相反。如果你在提取数据时希望某个字段不应该被延后载入,而应该立即载入,那么你就可以做使用 only()方法。
- 6、多数据库切换using(alias)
- 单独使用无意义,配合其他查询集方法一起使用。
- Author.objects.using('backup')
- 7、表锁定select_for_update(nowait=False)
- 单独使用无意义,配合其他查询集方法一起使用。
- 返回queryset,并将需要更新的行锁定,类似于SELECT … FOR UPDATE的操作。
- entries = Entry.objects.select_for_update().filter(author=request.user)
- 所有匹配的entries都会被锁定直到此次事务结束。
其他方法
- 特别的:QuerySet可以使用切片限制查询集。
- 切片后依旧获得QuerySet,并且不会触发数据库查询。
- >>> a=Author.objects.all()[0:2]
- >>> type(a)
- <class 'django.db.models.query.QuerySet'>
- 设置步长值后,获得到List类型值。触发数据库查询
- >>> a=Author.objects.all()[::2]
- >>> type(a)
- <type 'list'>
- 使用索引,数据对象,触发数据库查询
- >>> Author.objects.all()[0] #等价于Author.objects.all()[0:1].get()
<Author: 苍松>
- 查看QuerySet的原始SQL语句
- 关于查看QuerySet的原始SQL语句,使用查询集的query对象。
- >>> q=Author.objects.all()
- >>> print q.query
- SELECT "otest_author"."id", "otest_author"."name" FROM "otest_author"
c、查询条件(双下划线)
所有使用查询条件的查询和查询集过滤的方法(get,get_or_create,filter,exclude等)都可以使用双下划线组合出更复杂的查询条件。
另一种使用双下划线的情况就是跨表条件查询单情况,见下一节关联字段中跨表查询。
- 查询条件格式
- field__条件类型,例如a=Author.objects.get(id__exact=1)
- 默认为精确匹配
- 例如:Author.objects.get(id=1)等价于Author.objects.get(id__exact=1)
- 一、精确匹配
- exact 精确匹配: Blog.objects.get(id__exact=1)
- iexact 忽略大小写的精确匹配,Blog.objects.filter(name__iexact='blog7')
- 二、模糊匹配
- (模糊匹配,仅PostgreSQL 和 MySQL支持. SQLite的LIKE 语句不支持大小写敏感特性,因此模糊匹配对于 SQLite无法对大敏感)
- contains 大小写敏感的内容包含测试:Blog.objects.filter(name__contains='blog7')
- icontains 大小写不敏感的内容包含测试:
- startswith 大小写敏感的内容开头 Blog.objects.filter(name__startswith="blog")
- endswith 大小写敏感的内容结尾 endswith.
- istartswith 大小写不敏感的内容开头 startswith.
- iendswith 大小写不敏感的内容结尾 endswith.
- 三、正则匹配
- regex
- 大小写敏感的正则表达式匹配。
- 它要求数据库支持正则表达式语法,而 SQLite 却没有内建正则表达式支持,因此 SQLite 的这个特性是由一个名为 REGEXP 的 Python 方法实现的,所以要用到 Python 的正则库 re.
- Entry.objects.get(title__regex=r'^(An?|The) +')
- 等价于 SQL:
- SELECT ... WHERE title REGEXP BINARY '^(An?|The) +'; -- MySQL
- SELECT ... WHERE REGEXP_LIKE(title, '^(an?|the) +', 'c'); -- Oracle
- SELECT ... WHERE title ~ '^(An?|The) +'; -- PostgreSQL
- SELECT ... WHERE title REGEXP '^(An?|The) +'; -- SQLite
- iregex
- 忽略大小写的正则表达式匹配。
- 四、范围匹配
- gt 大于: Blog.objects.filter(id__gt=3)
- gte 大于等于.
- lt 小于.
- lte 小于等于.
- ne 不等于.
- in 位于给定列表中: Blog.objects.filter(id__in=[1,3,5])
- range 范围测试: Blog.objects.filter(name__range=('blog1','blog5'))
- 日期匹配:
- year 对 date/datetime 字段, 进行精确的 年 匹配:Polls.objects.filter(pub_date__year=2005).
- month
- day
- hour
- minute
- second
- 空值匹配
- isnull True/False; 做 IF NULL/IF NOT NULL 查询:Blog.objects.filter(name__isnull=True)
d、 复杂查询条件,使用Q 对象进行复杂的查询
filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果需要执行更复杂的查询(例如OR 语句),你可以使用Q 对象。
- Q对象有两种使用方式,一种使用Tree模式。另一种是使用"|"和"&"符号进行与或操作。
- Q构建搜索条件
- from django.db.models import Q
- con = Q()
- q1 = Q()
- q1.connector = 'OR'
- q1.children.append(('id', 1))
- q1.children.append(('id', 2))
- #等价于Q(id=1) | Q(id=2)
- q2 = Q()
- q2.connector = 'AND'
- q2.children.append(('id', 1))
- q2.children.append(('name__startswith', 'a'))
- #等价于Q(id=1) | Q(name__startswith='a')
- con.add(q1, 'AND')
- con.add(q2, 'AND')
- Q搜索可以和普通查询参数一起使用,但查询参数需要在最后。
- Author.objects.filter(q1,id=26)
2.2关联字段CURD操作(一对一,一对多,多对多表关系操作)
- 一对一和多对多的表关系的增删改查
- a1 = Author.objects.get(name="猴子")
- a2 = Author.objects.get(name="苍松")
- a3 = Author.objects.get(name="鲁迅")
- p1=Publisher.objects.get(name="机械出版社")
- p2=Publisher.objects.get(name="av")
- ==============正向关系操作===================================================
- 增
- b1=Book(title="红楼梦",price=10)
- b1.publisher=p1或者b1.publisher_id=1 #一对多
- b1.save() 先保存book对象之后才能添加多对多关系
- b1.authors.add(a1,a2)或者b1.authors=[a1,a2] #多对多
- b1.save()
- 删
- b1.publisher=None或者b1.publisher_id=None #一对多
- b1.authors.remove(a1,a2) 实际上是删除关系表otest_book_authors中的一条数据 #多对多
- b1.authors.clear() 清空所有关系 #多对多
- 查询
Book.objects.filter(publisher__name=u"机械出版社") #一对多,使用双下划线
Book.objects.filter(authors__name=u"苍松") #多对多,使用双下划线
- 获取字段值对象
- b2.publisher #一对多,对象下面的字段值继续使用.获取。例如b2.publisher.name
- b1.authors.all() #多对多
- ==============反向关系操作===================================================
- 增
- p1.book_set.add(b1) #一对多,会更新现有的关系。(一个对象只能有一个外键)
- a3.book_set.add(b1) #多对多
- 删
- p1.book_set.remove(b1) #一对多
- a3.book_set.remove(b1) #多对多
- a3.book_set.clear() #多对多,清空所有关系
- 获取字段值对象
- a2.book_set.all() #多对多
- p1.book_set.all() #一对多
- =============自定义中介模型方法===================================================
- 中介模型add、create 、remove方法不可用。但是clear() 方法却是可用的,它可以清空某个实例所有的多对多关系。
三、使用原始SQL语句
Django提供两种方法使用原始SQL进行查询:一种是使用Manager.raw()方法,进行原始查询并返回模型实例;另一种直接执行自定义的SQL语句。
1、使用Manager.raw()方法
- Manager.raw(raw_query, params=None, translations=None)
- raw_query SQL查询语句。
- params 查询条件参数,是list或者dict
- translations 字段映射表,是一个dict。
- Manager.raw()将查询结果映射到类字段,默认情况下映射到同名字段。返回结果是一个RawQuerySet。
- 如果在其他的表中有一些Author数据,你可以很容易地把它们映射成Author实例。
- 手动指定字段映射字典。
- 方法一:使用AS,其他字段自动应设至Author表中的同名字段。
- na=Author.objects.raw("select name AS newname, id from otest_author")
- >>> na[]
- <Author_Deferred_name: 苍松>
- .
- 方法二:使用translations
- name_map={"name":"newname}
- na=Author.objects.raw("select * from otest_author",translations=name_map)
- params参数防止SQL注入
- 方法一:使用list
- >>> na=Author.objects.raw("select * from otest_author where id =%s",[id])
- >>> na[]
- <Author: 苍松>
- 方法二:使用dict
- 注意:SQLite后端不支持字典,你必须以列表的形式传递参数。
- 字典使用%(key)s占位符(key替换成字典中相应的key值)
- p_dict={"id":}
- na=Author.objects.raw("select * from otest_author where id =%(id)s",p_dict)
2.直接执行自定义的SQL
有时Manager.raw()方法并不十分好用,你不需要将查询结果映射成模型,或者你需要执行UPDATE、 INSERT以及DELETE查询。
- #单数据库
- from django.db import connection
- def my_custom_sql(self):
- cursor = connection.cursor()
- cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz])
- cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])
- row = cursor.fetchone()
connection.close()- return row
- #多数据库
- from django.db import connections
- cursor = connections['my_db_alias'].cursor()
- # Your code here...
- 默认情况下,Python DB API会返回不带字段的结果,这意味着你得到的是一个列表,而不是一个字典。
- def dictfetchall(cursor):
- "Returns all rows from a cursor as a dict"
- desc = cursor.description
- return [
- dict(zip([col[] for col in desc], row))
- for row in cursor.fetchall()
- ]
- >>> cursor.execute("SELECT id, parent_id FROM test LIMIT 2");
- >>> cursor.fetchall()
- ((54360982L, None), (54360880L, None))
- >>> cursor.execute("SELECT id, parent_id FROM test LIMIT 2");
- >>> dictfetchall(cursor)
- [{'parent_id': None, 'id': 54360982L}, {'parent_id': None, 'id': 54360880L}]
四、分组和聚合
- Avg 平均值
- Count(expression, distinct=False) 计算个数。如果distinct=True,Count将只计算唯一的值。默认值为False。
- Max 最大值
- Min 最小值
- Sum 求和
- 方法一:使用annotate方法,先分组(group by)再聚合
- from django.db.models import Count, Min, Max, Sum,Avg
- >>> Book.objects.values('publisher').annotate(counts_num=Count("*"))
- [{'publisher': 1, 'counts_num': 2}, {'publisher': 3, 'counts_num': 1}]
- >>> Book.objects.values('publisher').annotate(Avg("price"))
- [{'publisher': 1, 'price__avg': 12.5}, {'publisher': 3, 'price__avg': 11.0}] #得到分组的多个值列表
- 使用values('publisher')进行group by分组后,在使用聚合函数才有意义。
- 默认聚合名称filedname__聚合函数名,作为聚合字段名。
- 方法二:使用aggregate方法,先过滤再聚合
- Book.objects.filter(publisher_id=1).aggregate(Count("id"))
- {'id__count': 2} #得到单个值
- 参考文档:
http://python.usyiyi.cn/django/index.html中文翻译1.8.2版中文不好的同学可以看这个
Django之Model(一)--基础篇的更多相关文章
- Django学习笔记(基础篇)
Django学习笔记(基础篇):http://www.cnblogs.com/wupeiqi/articles/5237704.html
- Django之Model操作进阶篇
常用参数 null 数据库中字段是否可以为空 db_column 数据库中字段的列名 default 数据库中字段的默认值 primary_key 数据库中字段是否为主键 db_index 数据库中字 ...
- Python之路【第十六篇】:Django【基础篇】
Python之路[第十六篇]:Django[基础篇] Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了O ...
- 01: Django基础篇
目录:Django其他篇 01:Django基础篇 02:Django进阶篇 03:Django数据库操作--->Model 04: Form 验证用户数据 & 生成html 05:Mo ...
- Django 【基础篇】
前戏 python Web程序 众所周知,对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. #!/usr/bin/env python #cod ...
- Python之路【第二十二篇】:Django之Model操作
Django之Model操作 一.字段 AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bi ...
- Django之Model组件
Model组件在django基础篇就已经提到过了,本章介绍更多高级部分. 一.回顾 1.定义表(类) ##单表 from django.db import models class user(mode ...
- Django之模型层第一篇:单表操作
Django之模型层第一篇:单表操作 一 ORM简介 我们在使用Django框架开发web应用的过程中,不可避免地会涉及到数据的管理操作(如增.删.改.查),而一旦谈到数据的管理操作,就需要用到数 ...
- Django之模型层第二篇:多表操作
Django之模型层第二篇:多表操作 一 表关系回顾 在讲解MySQL时,我们提到,把应用程序的所有数据都放在一张表里是极不合理的. 比如我们开发一个员工管理系统,在数据库里只创建一张员工信息 ...
- DOM系列---基础篇
DOM系列---基础篇 DOM (Document Object Model) 即文档对象模型, 针对 HTML 和 XML 文档的 API (应用程序接口) .DOM 描绘了一个层次化的节点树, ...
随机推荐
- [转]epoll技术
在linux的网络编程中,很长的时间都在使用select来做事件触发.在linux新的内核中,有了一种替换它的机制,就是epoll. 相比于select,epoll最大的好处在于它不会随着监听fd数目 ...
- .NET中的Queue和Stack
1.ArrayList类 ArrayList类主要用于对一个数组中的元素进行各种处理.在ArrayList中主要使用Add.Remove.RemoveAt.Insert四个方法对栈进行操作.Add方法 ...
- 怒刷DP之 HDU 1257
最少拦截系统 Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Statu ...
- System.Data.OracleClient requires Oracle client software version 8.1.7 or greater
It is a security issue, so to fix it simply do the following: Go to the Oracle folder. 1- Right Clic ...
- 如果AlertView输入框为空,则禁止点击确定按钮
//UIAlertView的代理方法(创建UIAlertView之后,copy此代理方法即可) - (BOOL)alertViewShouldEnableFirstOtherButton:(UIAle ...
- BZOJ 2456
Description 给你一个n个数的数列,其中某个数出现了超过n div 2次即众数,请你找出那个数. Input 第1行一个正整数n.第2行n个正整数用空格隔开. Output 一行一个正整数表 ...
- C#的三大特性
每个新手基本上都知道C#的三大特性,但是今天我给自己总结了一下这三大特性 1.封装 被定义为"把一个或多个项目封闭在一个物理的或者逻辑的包中".在面向对象程序设计方法论中,封装是为 ...
- 【CSS3】---练习制作导航菜单
练习题 根据所学知识,使用CSS3实现下图的导航菜单效果 任务 1.制作导航圆角 提示:使用border-radius实现圆角 2.制作导航立体风格 提示:使用box-shadow实现立体风格 3.制 ...
- HttpURLConnection&HttpClient网络通信
一:HttpURLConnection简介: 用于发送或者接受HTTP协议请求的类,获得的数据可以是任意类型和长度,这个类可以用于发送和接收流数据,其长度事先不知道. 使用这个类遵循一下模式: 获得一 ...
- 关于近期需要学习sqlserver2008
在胜利油田物探院借了一本书叫做 sqlserver2008宝典 第二版,但是看不下去 下面打算直接安装数据库上手了,边练边学