这篇笔记次要介绍 Django 一些实例办法。
什么是 实例,咱们晓得通过 filter() 的一些筛选办法,失去的是 QuerySet,而 QuerySet 取单条数据,通过索引,或者 first() 或者 last() 等办法,失去的单条数据,就是一个 model 的实例。
咱们接下来要介绍的就是这种单条实例的一些办法。
- save() 的继承操作
- refresh from db,从数据库中更新实例数据
- 自增的主键
- 指定字段更新 save()
1、save() 的继承操作
对于一个 model,咱们能够通过 save() 的形式创立一条数据,比方:
from blog.models import Blog
blog = Blog(name="blog_1", tagline="tagline_1")
blog.save()
对于下面的 blog,咱们就称其为 Blog 的一个实例。
咱们能够通过继承笼罩原有的 save() 办法,而后新增一些咱们须要的操作,比方打印日志,发送揭示等。
办法如下:
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” 的记录。
除此之外,Django 的文档提出了一种形式,在 model 中定义一个类办法,能够不便咱们对数据进行解决:
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() 操作能力保留到数据库。
除了这种办法,还有一种官网文档更举荐的办法,就是应用 manager,这个的用法咱们在前面几篇笔记中波及,这里只做一个展现:
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,从数据库中更新实例数据
办法为 refresh_from_db()
作用为从数据库中获取实例数据的最新值。
blog = Blog.objects.first()
# 其余中央可能会对 blog 数据进行一些更改
# 而后从数据库中拉取 blog 的最新数据
blog.refresh_from_db()
这个操作我集体经常用在写单元测试,比方通过一系列操作之后,想要查看这个 obj 的数据有没有更改,这种状况下就能够应用这个函数。
说一下 refresh_from_db() 这个函数的性能问题,refresh_from_db() 的底层函数也是应用的 get() 办法
所以应用 refresh_from_db() 和 get(pk=xx) 这两者在性能上可能差异不会很大,然而 refresh_from_db() 则更为简洁。
3、自增的主键
如果咱们没有为 model 设置 PrimaryKey,那么零碎则会主动为 model 设置自增主键为 id 的字段,创立数据的时候,不指定该字段,零碎会主动为其赋值。
而当咱们想要复制一条数据记录的时候,咱们能够将 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 字段进行的更新操作还原。
那么这个时候,为了防止这种状况产生,咱们在 save() 的时候指定咱们要更新的字段来保留数据:
blog.name = "test_1"
blog.save(update_fields=["name"])
以上就是本篇笔记全部内容,下一篇笔记将介绍 manager 的用法。
本文首发于自己微信公众号:Django 笔记。
原文链接:Django 笔记十八之 save 函数的继承操作和指定字段更新等实例办法
如果想获取更多相干文章,可扫码关注浏览: