一个建立好的模型,django会生成一套完整的API,以便对对象进行crud操作,下面就详细介绍crud操作。

先说一下操作环境: python2.7, django1.11.8, win7系统,借助于pycharm工具。

from django.db import models

# Create your models here.

class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField() def __unicode__(self): # __self__ on Python 3
return self.name class Author(models.Model):
name = models.CharField(max_length=200)
email = models.EmailField() def __unicode__(self): # __self__ on Python 3
return self.name class Entry(models.Model):
blog = models.ForeignKey(Blog)
headline = models.CharField(max_length=255)
body_text = models.TextField()
pub_date = models.DateField()
mod_date = models.DateField()
authors = models.ManyToManyField(Author)
n_comments = models.IntegerField()
n_pingbacks = models.IntegerField()
rating = models.IntegerField() def __unicode__(self): # __self__ on Python 3
return self.headline

创建对象

Django 使用一种直观的方式把数据库表中的数据表示成Python 对象:一个模型类代表数据库中的一个表,一个模型类的实例代表这个数据库表中的一条特定的记录。

首先讲述单一对象(也就是不跨模型的crud操作)。

增加对象数据

使用关键字参数实例化模型实例来创建一个对象,然后调用save() 把它保存到数据库中。

>>> from mysite import models                #首先导入models模块

#第一种创建一个Blog对象,传参,调用save函数,需要注意只有在调用save函数的时候,才会与数据库交互。
>>> b = models.Blog(name="first", tagline="one")
>>> b.save() #第二种: 创建一个objects对象直接调用create方法,保存数据
>>> models.Blog.objects.create(name="second", tagline="two")
<Blog: second>

#第三种方法和第一种差不多,只不过把传参过程单独写了出来
>>> bg = models.Blog()
>>> bg.name = "third"
>>> bg.tagline = "three"
>>> bg.save() #第四种:会尝试着先获取数据,若是数据不存在,则再创建。返回结果是一个布尔值,创建成功返回True,若是值已经存在则返回的是False。
>>> models.Blog.objects.get_or_create(name="fourth", tagline="four")
(<Blog: fourth>, True) #上面的四种方法都是向数据库中写入了数据,实质均是转为insert语句而已。

查看数据

获取全部的数据:

>>> models.Blog.objects.all()
<QuerySet [<Blog: first>, <Blog: second>, <Blog: third>, <Blog: fourth>, <Blog: first>, <Blog: second>]>
>>> models.Blog.objects.all()[:2]
<QuerySet [<Blog: first>, <Blog: second>]> #all():方法会获取对象中所有的数据,但是返回的结果是一个QuerySet对象。
#返回的结果是一个列表,因此支持切片操作。

过滤查询: 就像select语句一样,通常我们的查询都是有条件限制,不可能是获取全部的所有数据。

QuerySet查询有两个过滤设置:

  • filter(**kwargs):返回一个新的QuerySet,它包含满足查询参数的对象。
  • exclude(**kwargs):返回一个新的QuerySet,它包含满足查询参数的对象。
>>> models.Blog.objects.all().filter(name="first")      #返回符合条件的数据
<QuerySet [<Blog: first>, <Blog: first>]>
>>> models.Blog.objects.all().exclude(name="first") #返回不符合条件的数据
<QuerySet [<Blog: second>, <Blog: third>, <Blog: fourth>, <Blog: second>]> #链式过滤,先过滤出不包含name="first"的对象,然后再过滤出tagline="three"的对象
>>> models.Blog.objects.all().exclude(name="first").filter(tagline="three")
<QuerySet [<Blog: third>]>

QuerySet是惰性的,创建QuerySet对象不会造成任何数据库的访问,只有在使用这个QuerySet对象才会通过数据库访问获取数据。

get返回一个QuerySet对象:

上面的查询返回的QuerySet对象一般都不是一个结果,若是想要获取一个结果,可以使用get方法。

>>> models.Blog.objects.get(name="third")           #返回一个结果
<Blog: third>
>>> models.Blog.objects.get(name="first") #若是查询出来的结果又多个,则get会报错
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "C:\Python27\lib\site-packages\django-1.10.8-py2.7.egg\django\db\models\manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "C:\Python27\lib\site-packages\django-1.10.8-py2.7.egg\django\db\models\query.py", line 389, in get
(self.model._meta.object_name, num)
MultipleObjectsReturned: get() returned more than one Blog -- it returned 2!

查询结果的values方法与value_list方法。

  • values(*fields, **expression): 正常的查询返回的是一个模型实例的可迭代对象,values返回的是一个模型字典的可迭代对象。
>>> models.Blog.objects.values()    #返回的是一个每个记录的key-value构成的字典。注意多了一个id字段,这个id是django自动创建的主键。
<QuerySet [{'tagline': u'one', u'id': 1, 'name': u'first'}, {'tagline': u'two', u'id': 2, 'name': u'second'}, {'tagline': u'three', u'id': 3, 'name': u'third'}, {'tagline': u'four', u'id': 4, 'name': u'fourth'}, {'tagline': u'one', u'id': 5, 'name': u'first'}, {'tagline': u'two', u'id': 6, 'name': u'second'}]> >>> models.Blog.objects.values("id","name") #fields参数,类似于select查询中要查询的字段,也就是显示指定的字段。
<QuerySet [{'id': 1, 'name': u'first'}, {'id': 2, 'name': u'second'}, {'id': 3, 'name': u'third'}, {'id': 4, 'name': u'fourth'}, {'id': 5, 'name': u'first'}, {'id': 6, 'name': u'second'}]>

values还有一个**expression参数,这是一个关键字参数,values会把关键字参数传递给annotate()方法。django1.11之后支持**expression参数。

  • values_llist(*fields, flat=False): 与values类似,只不过返回的是元组而不是字典。

    >>> models.Blog.objects.values_list()
    <QuerySet [(1, u'first', u'one'), (2, u'second', u'two'), (3, u'third', u'three'), (4, u'fourth', u'four'), (5, u'first', u'one'), (6, u'second', u'two'), (7, u'SECOND', u'ABC')]>
    >>> models.Blog.objects.values_list("id","name")
    <QuerySet [(1, u'first'), (2, u'second'), (3, u'third'), (4, u'fourth'), (5, u'first'), (6, u'second'), (7, u'SECOND')]> 当只查询一个字段时,设置flat为True,返回的结果不再是一个元组,而是单个值。若设置为False,则返回的仍然是元组。但是,查询有多个字段时,设置为True会报错。
    >>> models.Blog.objects.values_list("id", flat=True)
    <QuerySet [1, 2, 3, 4, 5, 6, 7]>
    >>> models.Blog.objects.values_list("id", flat=False)
    <QuerySet [(1,), (2,), (3,), (4,), (5,), (6,), (7,)]> >>> models.Blog.objects.values_list("id","name", flat=False)
    <QuerySet [(1, u'first'), (2, u'second'), (3, u'third'), (4, u'fourth'), (5, u'first'), (6, u'second'), (7, u'SECOND')]>
    >>> models.Blog.objects.values_list("id","name", flat=True) #报错
    Traceback (most recent call last):
      File "<input>", line 1, in <module>
      File "C:\Python27\lib\site-packages\django-1.10.8-py2.7.egg\django\db\models\manager.py", line 85, in manager_method
        return getattr(self.get_queryset(), name)(*args, **kwargs)
      File "C:\Python27\lib\site-packages\django-1.10.8-py2.7.egg\django\db\models\query.py", line 729, in values_list
        raise TypeError("'flat' is not valid when values_list is called with more than one field.")
    TypeError: 'flat' is not valid when values_list is called with more than one field.
  • 查询中的一些关键字使用以及正则表达式简单使用。
    #exact精确匹配,默认的就是这种匹配方式。
    >>> models.Blog.objects.all().filter(name="second")
    <QuerySet [<Blog: second>, <Blog: second>]>
    >>> models.Blog.objects.all().filter(name__exact="second") #这里是双下划线
    <QuerySet [<Blog: second>, <Blog: second>]> #iexact忽略大小写
    >>> models.Blog.objects.all().filter(name__iexact="second")
    <QuerySet [<Blog: second>, <Blog: second>, <Blog: SECOND>]> #contains大小写敏感,包含关系测试;icontains大小写不敏感,不包含关系测试
    在数据库中修改数据,方便做测试。
    >>> models.Blog.objects.all().filter(name__contains="second")
    <QuerySet [<Blog: second>, <Blog: one second >]>
    >>> models.Blog.objects.all().filter(name__icontains="second")
    <QuerySet [<Blog: second>, <Blog: one second >, <Blog: one SECOND >]> #startwith和endwith分别表示以“xxx”开始和以“xxx”结尾。 Person.objects.filter(name__regex="^abc") # 正则表达式查询
    Person.objects.filter(name__iregex="^abc")# 正则表达式不区分大小写

更新对象数据

更新数据和sql语句类似,查找到某一条数据更新,查找到某类型数据的集合更新。

>>> models.Blog.objects.all().filter(name__icontains="second")
<QuerySet [<Blog: second>, <Blog: one second >, <Blog: one SECOND >]>
>>> models.Blog.objects.values().filter(name="third")
<QuerySet [{'tagline': u'three', u'id': 3, 'name': u'third'}]>
>>> models.Blog.objects.values().filter(name="third").update(tagline="Fuck") #更新一个特定的记录
1
>>> models.Blog.objects.values().filter(name="third")
<QuerySet [{'tagline': u'Fuck', u'id': 3, 'name': u'third'}]> >>> models.Blog.objects.all().update(tagline="Wonderful") #批量更新,慎用!
7
>>> models.Blog.objects.values("tagline")
<QuerySet [{'tagline': u'Wonderful'}, {'tagline': u'Wonderful'}, {'tagline': u'Wonderful'}, {'tagline': u'Wonderful'}, {'tagline': u'Wonderful'}, {'tagline': u'Wonderful'}, {'tagline': u'Wonderful'}]>

删除数据

删除数据和更新一样,批量删除,和删除特定的数据。

>>> models.Blog.objects.all().filter(name="fourth").delete()
(1, {u'mysite.Blog': 1}) >>> models.Blog.objects.all().filter(name="first").delete()
(2, {u'mysite.Blog': 2})

django中自带的QuerySet API还是蛮多的,不太可能一一列举完成,这里给出文档连接:QuerySet API

跨模型操作

上面的crud操作都是针对单个模型的,下面来说明跨模型的操作。

有下面的model,我们根据下面的model来说明夸模型操作的应用。

class Business(models.Model):  # django中会默认创建主键id
caption = models.CharField(max_length=32)
code = models.CharField(max_length=32) class Host(models.Model):
nid = models.AutoField(primary_key=True)
hostname = models.CharField(max_length=50, db_index=True)
ip = models.GenericIPAddressField(protocol="IPV4")
port = models.IntegerField()
b = models.ForeignKey(to="Business", to_field="id") class Application(models.Model):
name = models.CharField(max_length=64)
r = models.ManyToManyField("Host")

多对一关系的查询与添加:

插入外键的数据:

上面的models可知,host的字段b关联到Business中的隐藏主键(id),Business中的数据如下:

我们向host表中写入数据如下:

>>> from mysite import models
>>> h1 = models.Host()
>>> h1.hostname = "nginx-one"
>>> h1.ip = "10.0.102.110"
>>> h1.port = 80 #到这里为止一切都是美好的,然后开始向外键b写入数据。
>>> h1.b = 1
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "C:\Python27\lib\site-packages\django-1.10.8-py2.7.egg\django\db\models\fields\related_descriptors.py", line 211, in __set__
self.field.remote_field.model._meta.object_name,
ValueError: Cannot assign "": "Host.b" must be a "Business" instance.
因为外键b关联到Business表,因此这里报错说b必须是一个Business实例。
>>> id1 = models.Business.objects.get(caption="web") #主机名是nginx自然归类到web中
>>> h1.b = id1
>>> h1.save() #查看插入的数据
>>> models.Host.objects.values()
<QuerySet [{'ip': u'10.0.102.110', u'b_id': 1, 'hostname': u'nginx-one', 'port': 80, 'nid': 3}]> #跨表查询,这个查询从子表----->父表
#这里仅查出了外键的数字值为1,因为Business中id字段值是数字,但是数字看起来没有任何的意义,我们想同时查处来,这个主机对应的caption值是多少?
>>> models.Host.objects.values("hostname","ip","port","b__caption") #注意这里的写法b后面是双下划线然后才是caption。
<QuerySet [{'b__caption': u'web', 'ip': u'10.0.102.110', 'hostname': u'nginx-one', 'port': 80}]> #跨表查询,我们要从父表----->子表
>>> models.Business.objects.get(caption="web").host_set.values()
<QuerySet [{'ip': u'10.0.102.110', u'b_id': 1, 'hostname': u'nginx-one', 'port': 80, 'nid': 3}]>
Django默认每个主表对象都有一个外键的属性。 可以通过它来查询所有属于主表的子表信息, 查询方式:主表.子表_set(), 返回值为一个queryset对象
#在定义外键的时候也可以使用参数related_name指定这个外键关系的名字,在反向查询的时候可以直接使用这个名字。 #删除操作时根据on_delete参数的值,来确定如何删除数据。

多对多关系的操作

在上面的模型中Application应用与主机之间的关系是多对多的。上面的测试中,我们在Host表中插入了一条数据,继续再插入多条数据。

多对多关系的数据插入,分为两步。我们知道在多对多关系中,django另外创建一张表维护多对多的关系。因此插入数据时,先插入多对多的数据表,然后在插入多对多的关系表。
>>> app1 = models.Application() #创建一个Application对象
>>> app1.name = "test_app" #这个模型有个字段,先插入这个字段的值,然后再插入关系字段的值。
>>> app1.save() >>> value_r = models.Host.objects.get(hostname="redis1") #创建一个Host对象,然后把这个对象附加到app1上面。
>>> app1.r.add(value_r) add方法可以接受多个参数,每个参数用逗号分隔,可以一次性添加多个关系。

多对多关系的查询:

#本质上是转化为一对多关系的查询。
>>> app2 = models.Application.objects.get(name="test_app")
>>> app2.r.all()
<QuerySet [<Host: Host object>]>
>>> app2.r.values()
<QuerySet [{'ip': u'10.0.104.66', u'b_id': 3, 'hostname': u'redis1', 'port': 6379, 'nid': 3}]> #反向查询:【和上面的多对一的反向查询一样】
>>> h1 = models.Host.objects.get(hostname="redis1")
>>> h1.application_set.values()
<QuerySet [{u'id': 3, 'name': u'test_app'}]>

在关联对象时有几个方法可以使用:

https://yiyibooks.cn/xx/Django_1.11.6/ref/models/relations.html#django.db.models.fields.related.RelatedManager.add

add方法:

上面已经使用过了add方法:

add(*obj, bulk=True)
#添加一指定的模型对象到关联的对象集中。bulk的值请使用默认的!

create方法: 创建一个新的对象,将它保存并放在关联的对象集中。 返回新创建的对象:

>>> b = Blog.objects.get(id=1)
>>> e = b.entry_set.create(
... headline='Hello',
... body_text='Hi',
... pub_date=datetime.date(2005, 1, 1)
... ) # 这里不需要调用e.save() — 它已经被保存。
# 这完全等价于下面的(不过更加简洁于):
>>> b = Blog.objects.get(id=1)
>>> e = Entry(
... blog=b,
... headline='Hello',
... body_text='Hi',
... pub_date=datetime.date(2005, 1, 1)
... )
>>> e.save(force_insert=True)

django模型的crud操作的更多相关文章

  1. Django学习(三) Django模型创建以及操作

    在Django中可以建立自己的模型Model,这里对应Java里的实体类,跟数据库表是对应的.其中用到了django.db模块中的models.如下图所示: mysite/news/models.py ...

  2. Django 模型层 ORM 操作

    运行环境 1. Django:2.1.3 version 2. PyMysql: 0.9.3 version 3. pip :19.0.3 version 4. python : 3.7 versio ...

  3. Django1.11模型类数据库操作

    django模型类数据库操作 数据库操作 添加数据 1,创建类对象,属性赋值添加 book= BookInfo(name='jack',pub_date='2010-1-1') book.save() ...

  4. Django模型-数据库操作

    前言 前边记录的URLconf和Django模板全都是介绍页面展示的东西,也就是表现层的内容.由于Python先天具备简单而强大的数据库查询执行方法,Django 非常适合开发数据库驱动网站. 这篇开 ...

  5. django——模型层之多表操作

    django的多表操作 1.使用场景 在实际生产过程多,我们面对的数据纷繁复杂,此时就需要良好的数据结构设计,多表之间的约束关系为我们提供了数据管理以及查询的便利.在MYsql中我们利用外键(fore ...

  6. [Beego模型] 二、CRUD 操作

    [Beego模型] 一.ORM 使用方法 [Beego模型] 二.CRUD 操作 [Beego模型] 三.高级查询 [Beego模型] 四.使用SQL语句进行查询 [Beego模型] 五.构造查询 [ ...

  7. {django模型层(二)多表操作}一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询、分组查询、F查询和Q查询

    Django基础五之django模型层(二)多表操作 本节目录 一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询.分组查询.F查询和Q查询 六 xxx 七 ...

  8. Django项目的ORM操作之--模型类数据查询

    1.查询基本格式及理解: 类名.objects.[查询条件] 例如我们要查询数据库中一张表(bookinfo)的所有数据,sql语句为:select * from bookinfo, 对应模型类的操作 ...

  9. Django 08 Django模型基础3(关系表的数据操作、表关联对象的访问、多表查询、聚合、分组、F、Q查询)

    Django 08 Django模型基础3(关系表的数据操作.表关联对象的访问.多表查询.聚合.分组.F.Q查询) 一.关系表的数据操作 #为了能方便学习,我们进入项目的idle中去执行我们的操作,通 ...

随机推荐

  1. OpenVPN简介及架构详解

    OpenVPN简介 1 简介    VPN(Virtual Private Network)直译就是虚拟专用通道,是提供给企业之间或者个人与公司之间安全数据传输的隧道. OpenVPN无疑是Linux ...

  2. Django 框架 django的请求生命周期

    概述 首先我们知道HTTP请求及服务端响应中传输的所有数据都是字符串,同时http请求是无状态的,可以通过session和cookie来辅助. 浏览器通过ip和端口及路由方式访问服务端. 在Djang ...

  3. GitHub上个最有意思的项目合集(技术清单系列)

    没有1K以上的星星都不好意思推荐给大家!林子大了,啥项目都有,这里给大家搜罗了10个Github上有趣的项目.如果你就着辣椒食用本文,一定会激动的流下泪来...... 1.一行代码没有 | 18k s ...

  4. CentOS6.5配置MYSQL一主多从详解

    一.环境 操作系统 :CentOS 6.5 数据库版本:MySQL 主机A:192.168.1.1 (Master) 从机B:192.168.1.2 (Slave) 从机B:192.168.1.3 ( ...

  5. easyui combobox 动态加载数据C#

    <script type="text/javascript" src="Scripts/jquery-1.8.2.min.js"></scri ...

  6. Appium基础(三)对象抓取

    一.启动Android模拟器 二.打开App应用,这里以计算器为例子 三.打开uiautomatorviewer.bat 这个文件在Android SDK-->Tool目录下 双击uiautom ...

  7. QT自定义消息

    1.派生QAbstractNativeEventFilter,重写nativeEventFilter()函数 #ifndef CMYMESSAGEHANDLER_H #define CMYMESSAG ...

  8. Python之装饰器的实例

    1.1装饰器的应用:参数类型检查 函数参数的检查,一定是在函数外 函数应该作为参数,传入到检查函数中 检查函数拿到函数传入的实际参数,与形参声明对比 __annotations__属性是一个字典,其中 ...

  9. ArrayList与List性能测试

    理论:由于ArrayList存储数据存在装箱(读取数据存在拆箱),而泛型List<T>直接对T类型数据进行存储,不存在装箱与拆箱拆箱操作,理论上速度应该快一些. 废话少说,上代码. pub ...

  10. sitecore系统教程之内容编辑器

    内容编辑器   内容编辑器是一种编辑工具,可用于管理和编辑网站上的所有内容.它专为熟悉Sitecore及其包含的功能的经验丰富的内容作者而设计. 内容编辑器的外观和功能取决于用户的角色,本地安全设置以 ...