我想优化一下性能,但是有一个地方有 2 种写法,我不知道哪种好一点,就是比如有条数据进来,我要先判断这条数据在不在,如果在就更新,不在就直接新建一条
伪代码如下:
方法 1 )
try:
article = Article.objects.get(id=9999)
触发:更新逻辑
except:
触发:新建逻辑
方法 2 )
article = Article.objects.filter(id=9999)
if article.exists():
exist_article = article[0]
触发:更新逻辑
else:
触发:新建逻辑
感觉方法 1 有点奇怪,但是似乎就访问一次数据库,方法二啰嗦一点,不知道有没有老鸟能提供帮助?
1
wuwukai007 2021-01-26 19:50:13 +08:00
get_or_create
|
2
youngce 2021-01-26 19:51:38 +08:00
Article.objects.update_or_create() ?
|
3
Phishion OP @wuwukai007 请问,这种分装好的底层又是怎么实现的呢?
|
4
renmu123 2021-01-26 19:51:58 +08:00 via Android
1 比较符合 Python 哲学
|
5
Phishion OP @wuwukai007
我看它文档里面还真是 try 出来的,真原始啊 |
6
zeroDev 2021-01-26 19:55:58 +08:00 via Android
应该用 try except 结构,避免判断
参考 Python 官方文档 https://docs.python.org/3.6/glossary.html#term-eafp |
10
wuwukai007 2021-01-26 20:04:18 +08:00
你可以这样理解,如果存在的可能新远远大于 不存在,那么使用 try 的性能不就会搞的多吗,不用 try,每次都要判断
|
11
Phishion OP @wuwukai007 有道理,谢谢!
|
12
Geek981108 2021-01-26 20:07:29 +08:00
文档如是说:
update_or_create() update_or_create(defaults=None, **kwargs) A convenience method for updating an object with the given kwargs, creating a new one if necessary. The defaults is a dictionary of (field, value) pairs used to update the object. The values in defaults can be callables. Returns a tuple of (object, created), where object is the created or updated object and created is a boolean specifying whether a new object was created. The update_or_create method tries to fetch an object from database based on the given kwargs. If a match is found, it updates the fields passed in the defaults dictionary. This is meant as a shortcut to boilerplatish code. For example: defaults = {'first_name': 'Bob'} try: obj = Person.objects.get(first_name='John', last_name='Lennon') for key, value in defaults.items(): setattr(obj, key, value) obj.save() except Person.DoesNotExist: new_values = {'first_name': 'John', 'last_name': 'Lennon'} new_values.update(defaults) obj = Person(**new_values) obj.save() This pattern gets quite unwieldy as the number of fields in a model goes up. The above example can be rewritten using update_or_create() like so: obj, created = Person.objects.update_or_create( first_name='John', last_name='Lennon', defaults={'first_name': 'Bob'}, ) For detailed description how names passed in kwargs are resolved see get_or_create(). As described above in get_or_create(), this method is prone to a race-condition which can result in multiple rows being inserted simultaneously if uniqueness is not enforced at the database level. Like get_or_create() and create(), if you’re using manually specified primary keys and an object needs to be created but the key already exists in the database, an IntegrityError is raised. |
13
lixuda 2021-01-26 20:10:52 +08:00
我用这样,不知道性能好不好
article = Article.objects.filter(id=9999).first() if(article): |
16
Austaras 2021-01-27 00:51:32 +08:00
有的数据库支持 upsert
|
17
chaleaoch 2021-01-27 09:21:57 +08:00
你看源码,其实这俩逻辑差不多. get 里面就是 filter + try catch
|
18
nonduality 2021-01-27 15:17:55 +08:00
你的方法 2 会引发两次查询,优化文档经常提到不要滥用 exists():如果后续仍需要使用到对象数据,就无须用 exists()去判断对象存在与否。
用 #13 的方法也可以。 |
19
Phishion OP |