Django笔记十八之save函数的继承操作和指定字段更新等实例方法

科技资讯 投稿 13100 0 评论

Django笔记十八之save函数的继承操作和指定字段更新等实例方法

原文链接:Django笔记十八之save函数的继承操作和指定字段更新等实例方法

什么是 实例,我们知道通过filter( 的一些筛选方法,得到的是 QuerySet,而 QuerySet 取单条数据,通过索引,或者 first( 或者 last( 等方法,得到的单条数据,就是一个 model 的实例。

    save( 的继承操作
  1. refresh from db,从数据库中更新实例数据
  2. 自增的主键
  3. 指定字段更新 save(

1、save( 的继承操作

对于一个 model,我们可以通过 save( 的方式创建一条数据,比如:

from blog.models import Blog

blog = Blog(name="blog_1", tagline="tagline_1"
blog.save(

对于上面的 blog,我们就称其为 Blog 的一个实例。

方法如下:

class Blog(models.Model:
    name = models.CharField(max_length=100
    tagline = models.TextField(


    def save(self, *args, **kwargs:
        print("save"
        super(Blog, self.save(*args, **kwargs

这样,我们在对 Blog 数据进行 save( 操作的时候,就可以看到控制台会输出 "save" 的记录。

class Blog(models.Model:
    name = models.CharField(max_length=100
    tagline = models.TextField(


    @classmethod
    def create(cls, name, tagline:
        blog = cls(name=name, tagline=tagline
        print("get an unsaved Blog instance"
        return blog

然后通过调用该方法,传入参数,可以得到一个未保存的实例:

from blog.models import Blog
blog = Blog.create(name='test_create', tagline='test_tagline'
blog.save(

注意: 在我们执行 create( 方法的时候,程序还没有操作数据库,只是得到一个未保存的实例,我们仍然需要执行 save( 操作才能保存到数据库。

class BlogManager(models.Manager:
    def create_blog(self, name, tagline:
        blog = self.create(name=name, tagline=tagline
        # do something with the blog
        print("get an unsaved Blog instance"
        return blog


class Blog(models.Model:
    name = models.CharField(max_length=100
    tagline = models.TextField(


    objects = BlogManager(

需要注意的是,这里调用的是 create( 方法,所以直接保存到了数据库,不用再执行 save( 方法了。

2、refresh from db,从数据库中更新实例数据

作用为从数据库中获取实例数据的最新值。

blog = Blog.objects.first(

# 其他地方可能会对 blog 数据进行一些更改

# 然后从数据库中拉取 blog 的最新数据

blog.refresh_from_db(

这个操作我个人常常用在写单元测试,比如经过一系列操作之后,想要查看这个 obj 的数据有没有更改,这种情况下就可以使用这个函数。

所以使用 refresh_from_db( 和 get(pk=xx 这两者在性能上可能差别不会很大,但是 refresh_from_db( 则更为简洁。

3、自增的主键

而当我们想要复制一条数据记录的时候,我们可以将 id 字段置为 None,然后 save(,系统则会将其视为一条新数据,从而自动保存为新数据并为 id 字段赋值。

b = Blog.objects.first(
b.id = None
b.save(
b.id

4、指定字段更新 save(

假设有一个 TestModel,有一个 number 字段,我们想要对其执行 +1 的操作,大概行为可能如下:

obj = TestModel.objects.get(id=1
obj.number += 1
obj.save(

我们也可以通过 F( 函数这种稍微快一点和避免竞争的方式(竞争的意思是,其他的进程可能也在使用这条数据):

from django.db.models import F
obj = TestModel.objects.get(id=1
obj.number = F('number' + 1
obj.save(

指定字段保存
单纯的使用 save( 操作可能会造成一个问题,比如说,我们在某一个 get 了一条数据,对 name 字段进行了更改,但同时另一个进程对同一条数据也进行了更改,我们对这条数据进行 save( 操作,那么就可能造成数据不一致的情况。

blog = Blog.objects.get(id=1
blog.name = "test_1"

# 在这个期间,另一个进程对 tagline 字段进行了更改
# 假设该操作为 Blog.objects.filter(id=1.update(tagline="new_tagline"

# 然后执行 save( 操作
blog.save(

那么这个时候,blog 的数据因为已经从数据库中获取了出来,再执行 save( 则会保存之前获取的数据,这样会导致在此期间对 tagline 字段进行的更新操作还原。

blog.name = "test_1"
blog.save(update_fields=["name"]

以上就是本篇笔记全部内容,下一篇笔记将介绍 manager 的用法。

编程笔记 » Django笔记十八之save函数的继承操作和指定字段更新等实例方法

赞同 (72) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽