ORM操作数据库的增删改查

1. model类的属性参数

比如:models.CharField(null=True,blank=True)

(1)null
 
    如果为True,Django 将用NULL 来在数据库中存储空值。 默认值是 False.
 
(1)blank
 
如果为True,该字段允许不填。默认为False。
要注意,这与 null 不同。null纯粹是数据库范畴的,而 blank 是数据验证范畴的。
如果一个字段的blank=True,表单的验证将允许该字段是空值。如果字段的blank=False,该字段就是必填的。
 
(2)default
 
字段的默认值。可以是一个值或者可调用对象。如果可调用 ,每有新对象被创建它都会被调用,如果你的字段没有设置可以为空,那么将来如果我们后添加一个字段,这个字段就要给一个default值
 
(3)primary_key
 
如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key=True,
Django 就会自动添加一个IntegerField字段做为主键,所以除非你想覆盖默认的主键行为,
否则没必要设置任何一个字段的primary_key=True。
 
(4)unique
 
如果该值设置为 True, 这个数据字段的值在整张表中必须是唯一的
 
(5)choices
由二元组组成的一个可迭代对象(例如,列表或元组),用来给字段提供选择项。 如果设置了choices ,默认的表单将是一个选择框而不是标准的文本框,<br>而且这个选择框的选项就是choices 中的选项。
(6)db_index
  如果db_index=True 则代表着为此字段设置数据库索引。


DatetimeField、DateField、TimeField这三个时间字段,都可以设置如下属性。

(7)auto_now_add
    配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。

(8)auto_now
    配置上auto_now=True,每次更新数据记录的时候会更新该字段,标识这条记录最后一次的修改时间。
    只能在save方式时触发自动更新时间的动作

models中的FIeld类对应类型和对应的mysql的数据类型对比

(在pycharm里面External Libraries/<Python 3.6>/site-packages/django/db/backends/mysql/base.py 中可以查看)

AutoField: integer AUTO_INCREMENT,
    BigAutoField: bigint AUTO_INCREMENT,
    BinaryField: longblob,
    BooleanField: bool,
    CharField: varchar(%(max_length)s),
    CommaSeparatedIntegerField: varchar(%(max_length)s),
    DateField: date,
    DateTimeField: datetime,
    DecimalField: numeric(%(max_digits)s, %(decimal_places)s),
    DurationField: bigint,
    FileField: varchar(%(max_length)s),
    FilePathField: varchar(%(max_length)s),
    FloatField: double precision,
    IntegerField: integer,
    BigIntegerField: bigint,
    IPAddressField: char(15),
    GenericIPAddressField: char(39),
    NullBooleanField: bool,
    OneToOneField: integer,
    PositiveIntegerField: integer UNSIGNED,
    PositiveSmallIntegerField: smallint UNSIGNED,
    SlugField: varchar(%(max_length)s),
    SmallIntegerField: smallint,
    TextField: longtext,
    TimeField: time,
    UUIDField: char(32),

 

ORM数据库增删改查动作

 

添加单条数据

from django.shortcuts import render,HttpResponse
from app01 import models
def add_book(request):
    import datetime
    # 添加数据
    # 方式一
    book_obj = models.Mybook(
        title=看不见的光,
        state=True,
        pub_date=2010-03-04,
        price=45.5,
        publish=人民出版社
    )
    print(book_obj.title)
    print(book_obj.price)
    book_obj.save() # 这是保存数据

    return HttpResponse(已添加)

    # 方式二:
    book_obj = models.Mybook.objects.create(
        title=激荡十年,
        state=True,
        # 日期时间类型数据,通过字符串或者日期时间类型数据作为参数数据,都是可以的
        pub_date=datetime.datetime.now(),
        price=39.9,
        publish=北京出版社
    )
    print(book_obj)
    print(book_obj.title)
    print(book_obj.price)
    # 重点记录:create方法会返回新添加的这条记录的类对象,通过这个对象.属性的方式能够获取到对应字段的数据
    return HttpResponse(操作成功)

 

批量添加数据: 使用bulk_create

from django.shortcuts import render,HttpResponse
from app01 import models
def add_book(request):
    obj_list = []
    for i in range(1,10):
        obj = models.Mybook(
            title=f大国的博弈{i},
            state=True,
            pub_date=f2018-07-{i},
            price=35+i,
            publish=云出版社
        )
        obj_list.append(obj)
    models.Mybook.objects.bulk_create((obj_list))
    return HttpResponse(已批量添加)

 

更新或添加: Update_or_create()

  # 有就更新的操作
    models.Mybook.objects.update_or_create(
        id=5,
        defaults={
            title:边城,
            state:True,
            pub_date:2018-07-05,
            price:29.9,
            publish:人民出版社
        }
    )

    # 没有就创建的案例
    models.Mybook.objects.update_or_create(
        id=20,
        defaults={
            title: 边城,
            state: True,
            pub_date: 2018-07-05,
            price: 29.9,
            publish: 人民出版社
        }
    )

    # 查询为多条记录: 报错,因为update_or_create内部进行查询时用的get方法
    # get() returned more than one Mybook -- it returned 8!
    models.Mybook.objects.update_or_create(
        publish=人民出版社,
        defaults={
            title: 三三,
            state: True,
            pub_date: 2018-07-05,
            price: 29.9,
            publish: 人民出版社
        }
    )

    return HttpResponse(ok)

 

查询或添加: get_or_create()

ret = models.Mybook.objects.get_or_create(
        id=15,
        defaults={
            title: 三三,
            state: True,
            pub_date: 2018-07-05,
            price: 29.9,
            publish: 人民出版社
        }
    )
    print(ret) # (<Mybook: 大国的博弈7>, False)  id为15是有数据的, 所以直接返回数据了, 没有创建, 返回结果元祖中第二个值为False
    # 没数据创建数据
    ret = models.Mybook.objects.get_or_create(
        id=50,
        defaults={
            title: 三三,
            state: True,
            pub_date: 2018-07-05,
            price: 29.9,
            publish: 人民出版社
        }
    )
    print(ret) # (<Mybook: 三三>, True)  id为50是没有数据的, 所以创建数据了,  返回结果元祖中第二个值为True

    return HttpResponse(ok)

 

(2) 几种查询方法

all()查询所有的数据,返回结果为QuerySet类型数据,QuerySet类似于列表,里面存放的是model类的实例化对象,每个对象表示一条记录,对象中的对应数据有着该行记录的字段数据

def get_book(request):
    obj_list = models.Mybook.objects.all()
    print(obj_list[0]) # 索引取值
    print(obj_list[1:4]) # 切片取值

    return HttpResponse(OK)
# QuerySet类似于列表,但是比列表还多一些其他的功能,这是orm封装出来的新的数据类型
# <QuerySet [<Mybook: 看不见的光>, <Mybook: 看不见的光>, <Mybook: 看不见的光>]>

filter() 过滤查询 ,结果也是queryset类型数据,里面的每一项也是模型类对象, 查找不到内容时, 返回空的查询结果集

obj_list = models.Mybook.objects.filter(id=9)
    print(obj_list) # <QuerySet [<Mybook: 大国的博弈1>]>
obj_list = models.Mybook.objects.filter(publish=北京出版社)
    print(obj_list) # <QuerySet [<Mybook: 看不见的光>, <Mybook: 激荡十年>]> 查找内容可以是多项

get() 过滤查询,但是结果有且只能有一条,结果不是queryset类型数据,而是一个模型类对象

obj = models.Mybook.objects.get(id=5)
    print(obj) # Mybook object
    print(obj.price) # 29.90000

    # 当查询结果有多项时, 报错
    obj = models.Mybook.objects.get(publish=北京出版社)
    print(obj)
    # get() returned more than one Mybook -- it returned 2!

    # 当查询不到数据时 也会报错
    obj = models.Mybook.objects.get(id=80)
    print(obj)
    # Mybook matching query does not exist.

 

修改

def update_book(request):
    # 方式一: 模型类对象修改数据
    obj = models.Mybook.objects.get(id=5)
    obj.title = 我的前半生
    obj.price = 49
    obj.save()

    # 方式二: update方法, 调用者可以是objects控制器, 也可以是queryset类型数据, 但是不能是模型类对象
    # (1) objects调用, 整列更新
    models.Mybook.objects.update(
        state = False
    )
    # (2) queryset调用, 整列更新
    models.Mybook.objects.all().update(
        state = True
    )

    # (3) queryset类型数据调用, 更新部分数据
    obj = models.Mybook.objects.filter(publish=云出版社).update(
        price = 19.9
    )
    print(obj) # 9 返回受影响的行数


    # 模型类数据调用update方法的错误演示如下
    models.Mybook.objects.get(id=7).update(
        price = 66
    )
    # ‘Mybook‘ object has no attribute ‘update‘

 

删除: delete

def del_book(request):
    # 调用者可以是model对象, 也可以是queryset对象
    obj = models.Mybook.objects.get(id=5).delete()
    print(obj) # (1, {‘app01.Mybook‘: 1}) 返回结果是受影响的行数

    obj = models.Mybook.objects.filter(publish=人民出版社).delete()
    print(obj) # (7, {‘app01.Mybook‘: 7})

    # 错误演示:
    obj = models.Mybook.objects.delete()
    # ‘Manager‘ object has no attribute ‘delete‘
    # 控制器没有delete方法,原因就是怕一下子删除了所有数据

    # obj = models.Mybook.objects.all().delete()
    # 这个是删除所有数据

    return HttpResponse(OK)

 

查询的13个API接口

(1)  all():       查询所有结果,结果是queryset类型

(2)  filter(**kwargs):       它包含了与所给筛选条件相匹配的对象,结果也是queryset类型,可以被queryset类型数据调用,也可以直接通过objects控制器进行调用:

models.Book.objects.filter(id=5) #filter(id!=5)  不能直接写不等于,想做不等于排除查询使用下面的exclude方法
models.Book.objects.all().filter(id=5)
models.Book.objects.filter(title=linux,price=100) 

#里面的多个条件用逗号分开,并且这几个条件必须都成立,是and的关系,or关系的在这里写是搞不定的

(3)  get(**kwargs):          返回与所给筛选条件相匹配的对象,结果不是queryset类型,是行记录(模型类对象)对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。用的时候最好带上捕获异常try, get方法调用者可以是queryset类型数据,也可以是objects控制器。 

models.Book.objects.get(id=1)
models.Book.objects.all().get(id=8)

(4)  exclude(**kwargs):      排除的意思,它包含了与所给筛选条件不匹配的对象,没有不等于的操作昂,用这个exclude,返回值是queryset类型 ,调用者可以是queryset类型数据,也可以是objects控制器。 

obj = models.Mybook.objects.exclude(id=4)
    print(obj)

(5) order_by(*field):   对查询结果排序, 返回值还是queryset类型,调用者可以是queryset类型数据,也可以是objects控制器。

models.Book.objects.order_by(price) #获取所有数据,并且按照price字段升序排列
models.Book.objects.order_by(-price) #获取所有数据,并且按照price字段降序排列
models.Book.objects.all().order_by(-price) #queryset类型数据调用
    
多条排序示例:
models.Book.objects.all().order_by(price,id) 

#直接写price,默认是按照price升序排列,按照字段降序排列,就写个负号就行了order_by(‘-price‘),order_by(‘price‘,‘id‘)是多条件排序,按照price进行升序,price相同的数据,按照id进行升序

(6) reverse(): 可以是queryset类型的数据来调用,也可以是objects控制器调用,对查询结果反向排序,返回值还是queryset类型

方式1:
order_by(*field)方法进行排序
obj_list = models.Book.objects.all().order_by(‘id‘).reverse() 方式2: 在模型类中通过Meta类来执行排序规则
class Book(models.Model): id = models.AutoField(primary_key=True) #自增、主键 title = models.CharField(max_length=64,null=True) # state = models.BooleanField(default=True) pub_date = models.DateField(null=True) # price = models.DecimalField(max_digits=20,decimal_places=5,null=True) price = models.DecimalField(max_digits=8,decimal_places=2,null=True) publish = models.CharField(max_length=32) def __str__(self): return self.title + 价格 + str(self.price) class Meta: ordering = [id,] #制定了它之后,所有的本表的查询结果,都按照id进行升序排列,还可进行多条件排序规则的指定
obj_list = models.Book.objects.reverse()
reverse()翻转,必须在上面两者的基础上,才能进行结果顺序翻转

 (7) count():   queryset类型的数据来调用,也可以是objects控制器调用,返回数据库中匹配查询(QuerySet)的对象数量。返回结果是个数字。

obj_list = models.Book.objects.count() #默认统计的整表的所有数据量
obj_list = models.Book.objects.all().count()

(8)  first():  queryset类型的数据来调用,也可以是objects控制器调用,返回第一条记录对象,结果得到的都是model对象,不是queryset

Book.objects.all().first()  #同:Book.objects.all()[0] 
Book.objects.first()

(9)  last():    queryset类型的数据来调用,也可以是objects控制器调用,返回最后一条记录对象,结果得到的都是model对象,不是queryset

Book.objects.all().last()  
#同:Book.objects.all()[-1] ,但是负数索引取值会报错,错误信息为: Negative indexing is not supported. queryset类型数据,不支持负数索引取值的形式 Book.objects.last()

(10)  exists():   queryset类型的数据来调用,也可以是objects控制器调用,如果QuerySet包含数据,就返回True,否则返回False

obj_list = models.Book.objects.exists() #判断表中是否有数据
obj_list = models.Book.objects.filter(id=100).exists()  #判断查询结果集中是否有数据,有得到True,没有得到False
    
注意:
空的queryset类型数据布尔值为False,但是一般不用它来判断数据库里面是不是有数据,如果有大量的数据,那么就需要查询出所有的数据,效率太差了,用count或者exists

#‘select * from book where name="xx";‘
# if obj_list:  会将满足条件的所有数据进行一次查询,效率低

#select count(id) from book where name=‘xx‘;
# if obj_list.count(): 效率较高,按照查询结果对象的id值进行个数统计,

#select id from book where name=‘xx‘ limit 1; 查询一条数据,不用扫描所有数据
# if obj_list.exists(): #效率高
    
例:all_books = models.Book.objects.all().exists() 
#翻译成的sql是SELECT (1) AS `a` FROM `app01_book` LIMIT 1,就是通过limit 1,取一条来看看是不是有数据

(11)  values(*field):        用的比较多,queryset类型的数据来调用,也可以是objects调用,返回一个特殊的QuerySet,运行后得到的并不是一系列model的实例化对象,返回的queryset类型,里面的元素是字典数据,既然是queryset类型数据,那么就可以继续链式调用queryset类型的其他的查找方法,其他方法也是一样的。

# obj_list = models.Book.objects.values() #默认获取的表中所有记录的字典数据,字典中的键是字段名称(模型类属性名称),值是每个字段的对应数据
# obj_list = models.Book.objects.all().values()
# 取指定字段数据
obj_list = models.Mybook.objects.all().values(id,title)
    print(obj_list)
# <QuerySet [{‘id‘: 7, ‘title‘: ‘看不见的光‘}, {‘id‘: 8, ‘title‘: ‘激荡十年‘},{...}

(12)  values_list(*field):   它与values()非常相似,它返回的是一个包含元组queryset序列,values返回的是一个包含字典queryset序列

obj_list = models.Mybook.objects.all().values_list(id,title)
    print(obj_list)
    # <QuerySet [(7, ‘看不见的光‘), (8, ‘激荡十年‘),(...)]

(13)  distinct():       去重, values和values_list得到的queryset类型的数据来调用,从返回结果中剔除重复纪录

 

关键字传参

两种方式:
方式1
filter(id=5, publish=腾讯出版社)
create(id=5, publish=腾讯出版社)
    ...

方式2
filter(**{id:5, publish:腾讯出版社})
    ...

 

ORM操作数据库的增删改查

上一篇:java.sql.SQLSyntaxErrorException: ORA-00932: 数据类型不一致: 应为 BINARY, 但却获得 CHAR


下一篇:Python连接Redis数据库插入数据出现错误:DataError: Invalid input of type: 'NoneType'