【Python百日进阶-Web开发-Peewee】Day255 - Peewee 更新、删除记录

news/2024/10/22 9:49:29/

文章目录

    • 8.3 更新现有记录
    • 8.4 Atomic updates原子更新
      • 8.4.1 Upsert
    • 8.5 删除记录

8.3 更新现有记录

一旦模型实例具有主键,任何后续调用都 save()将导致UPDATE而不是另一个INSERT。模型的主键不会改变:

>>> user.save()  # save() returns the number of rows modified.
1
>>> user.id
1
>>> user.save()
>>> user.id
1
>>> huey.save()
1
>>> huey.id
2

如果要更新多条记录,请发出UPDATE查询。以下示例将更新所有Tweet对象,将它们标记为已发布,如果它们是在今天之前创建的。Model.update()接受关键字参数,其中键对应于模型的字段名称:

>>> today = datetime.today()
>>> query = Tweet.update(is_published=True).where(Tweet.creation_date < today)
>>> query.execute()  # Returns the number of rows that were updated.
4

有关详细信息,请参阅有关Model.update()和 Update的文档Model.bulk_update()。

笔记

如果您想了解有关执行原子更新的更多信息(例如增加列的值),请查看原子更新 配方。

8.4 Atomic updates原子更新

Peewee 允许您执行原子更新。假设我们需要更新一些计数器。天真的方法是这样写:

>>> for stat in Stat.select().where(Stat.url == request.url):
...     stat.counter += 1
...     stat.save()

不要这样做!这不仅速度慢,而且如果多个进程同时更新计数器,它也容易受到竞争条件的影响。

相反,您可以使用以下方法自动更新计数器update():

>>> query = Stat.update(counter=Stat.counter + 1).where(Stat.url == request.url)
>>> query.execute()

您可以根据需要使这些更新语句变得复杂。让我们给所有员工的奖金等于他们之前的奖金加上他们工资的 10%:

>>> query = Employee.update(bonus=(Employee.bonus + (Employee.salary * .1)))
>>> query.execute()  # Give everyone a bonus!

我们甚至可以使用子查询来更新列的值。假设我们在模型上有一个非规范化列,User用于存储用户发布的推文数量,并且我们会定期更新此值。以下是编写此类查询的方法:

>>> subquery = Tweet.select(fn.COUNT(Tweet.id)).where(Tweet.user == User.id)
>>> update = User.update(num_tweets=subquery)
>>> update.execute()

8.4.1 Upsert

Peewee 提供对不同类型的 upsert 功能的支持。对于 3.24.0 之前的 SQLite 和 MySQL,Peewee 提供了replace(),它允许您插入记录,或者在违反约束的情况下替换现有记录。

使用replace()and的例子on_conflict_replace():

class User(Model):username = TextField(unique=True)last_login = DateTimeField(null=True)# Insert or update the user. The "last_login" value will be updated
# regardless of whether the user existed previously.
user_id = (User.replace(username='the-user', last_login=datetime.now()).execute())# This query is equivalent:
user_id = (User.insert(username='the-user', last_login=datetime.now()).on_conflict_replace().execute())

笔记

除了replace之外,如果您只想插入并忽略任何潜在的约束违规,SQLite、MySQL 和 Postgresql 还提供忽略
操作(请参阅:)。on_conflict_ignore()

MySQL通过ON DUPLICATE KEY UPDATE子句支持 upsert 。例如:

class User(Model):username = TextField(unique=True)last_login = DateTimeField(null=True)login_count = IntegerField()# Insert a new user.
User.create(username='huey', login_count=0)# Simulate the user logging in. The login count and timestamp will be
# either created or updated correctly.
now = datetime.now()
rowid = (User.insert(username='huey', last_login=now, login_count=1).on_conflict(preserve=[User.last_login],  # Use the value we would have inserted.update={User.login_count: User.login_count + 1}).execute())

在上面的示例中,我们可以安全地多次调用 upsert 查询。登录计数将自动增加,最后登录列将被更新,并且不会创建重复的行。

Postgresql 和 SQLite(3.24.0 和更新版本)提供了不同的语法,允许更精细地控制哪些约束违反应该触发冲突解决,以及应该更新或保留哪些值。

on_conflict()用于执行 Postgresql 样式的 upsert(或 SQLite 3.24+)的示例:

class User(Model):username = TextField(unique=True)last_login = DateTimeField(null=True)login_count = IntegerField()# Insert a new user.
User.create(username='huey', login_count=0)# Simulate the user logging in. The login count and timestamp will be
# either created or updated correctly.
now = datetime.now()
rowid = (User.insert(username='huey', last_login=now, login_count=1).on_conflict(conflict_target=[User.username],  # Which constraint?preserve=[User.last_login],  # Use the value we would have inserted.update={User.login_count: User.login_count + 1}).execute())

在上面的示例中,我们可以安全地多次调用 upsert 查询。登录计数将自动增加,最后登录列将被更新,并且不会创建重复的行。

笔记

MySQL 和 Postgresql/SQLite 之间的主要区别在于 Postgresql 和 SQLite
要求您指定一个conflict_target.

这是一个使用命名空间的更高级(如果是人为的)示例EXCLUDED 。EXCLUDED帮助器允许我们引用冲突数据中的值。对于我们的示例,我们将假设一个简单的表将唯一键(字符串)映射到值(整数):

class KV(Model):key = CharField(unique=True)value = IntegerField()# Create one row.
KV.create(key='k1', value=1)# Demonstrate usage of EXCLUDED.
# Here we will attempt to insert a new value for a given key. If that
# key already exists, then we will update its value with the *sum* of its
# original value and the value we attempted to insert -- provided that
# the new value is larger than the original value.
query = (KV.insert(key='k1', value=10).on_conflict(conflict_target=[KV.key],update={KV.value: KV.value + EXCLUDED.value},where=(EXCLUDED.value > KV.value)))# Executing the above query will result in the following data being
# present in the "kv" table:
# (key='k1', value=11)
query.execute()# If we attempted to execute the query *again*, then nothing would be
# updated, as the new value (10) is now less than the value in the
# original row (11).

有关详细信息,请参阅Insert.on_conflict()和 OnConflict。

8.5 删除记录

要删除单个模型实例,您可以使用 Model.delete_instance()快捷方式。delete_instance() 将删除给定的模型实例,并且可以选择递归地删除任何依赖对象(通过指定recursive=True)。

>>> user = User.get(User.id == 1)
>>> user.delete_instance()  # Returns the number of rows deleted.
1>>> User.get(User.id == 1)
UserDoesNotExist: instance matching query does not exist:
SQL: SELECT t1."id", t1."username" FROM "user" AS t1 WHERE t1."id" = ?
PARAMS: [1]

要删除任意一组行,您可以发出DELETE查询。以下将删除所有Tweet超过一年的对象:

>>> query = Tweet.delete().where(Tweet.creation_date < one_year_ago)
>>> query.execute()  # Returns the number of rows deleted.
7

有关更多信息,请参阅以下文档:

  • Model.delete_instance()
  • Model.delete()
  • DeleteQuery

http://www.ppmy.cn/news/743571.html

相关文章

将机械硬盘换成固态硬盘的装机过程

1&#xff1a;首先将固态硬盘装进笔记本电脑中 2&#xff1a;打开电脑下载系统迁移工具&#xff0c;&#xff08;我用的是傲梅工具&#xff09; 3&#xff1a;跟着傲梅的教程走完之后&#xff0c;等待系统进入PE系统进行迁移系统。 4&#xff1a;完成之后&#xff0c;系统开机之…

加装机械硬盘后如何给磁盘分区

笔记本新加了西数的2T机械硬盘&#xff0c;但是在此电脑中无法查看到&#xff0c;因为还没有给磁盘分区。 参考教程&#xff1a;https://docs.microsoft.com/zh-cn/windows-server/storage/disk-management/initialize-new-disks 首先在开始菜单右键&#xff0c;选择磁盘管理。…

计算机机械硬盘系统安装,笔记本如何安装机械硬盘?笔记本安装机械硬盘的操作步骤...

很对电脑发烧友都会嫌自己的储存空间不够大不够用&#xff0c;这时就会在自己笔记本电脑里安装一个机械硬盘&#xff0c;因为机械硬盘相对廉价且空间也是非常大。那么笔记本如何安装机械硬盘&#xff1f;现在给大家演示一下操作步骤。 方法步骤&#xff1a; 1.将笔记本关机&…

攻防演练中红队常用的攻击方法之横向移动(中)

横向移动&#xff0c;是攻击者侵入企业系统时&#xff0c;获取相关权限及重要数据的常见攻击手法。了解横向移动的原理有助于个人和企业更好地维护网络安全。 中安网星特此推出了横向移动科普系列&#xff0c;本系列共有三篇文章。 横向移动是在复杂的内网攻击中被广泛应用的…

NacosConfig获取不到配置中心

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId><version>3.0.3</version></dependency> 版本说明 alibaba/spring-cloud-alibaba Wiki (github.com) …

写给Mac新手:用MacBook Pro办公的一些心得!

先来说说这段时间发现的一些问题&#xff0c;这些让人头疼的小毛病&#xff08;当然其中有些根本不是硬件或系统问题&#xff0c;只是和Windows不一样而已&#xff09;甚至一度让我觉得这东西并没有Windows系统的电脑好用。前后陆续求助了多次官方客服&#xff0c;也预约过天才…

dxSpreadSheet的报表demo-关于设计报表模板的Datagroup问题

看随机的报表DEMO&#xff0c;主从表也好&#xff0c;数据分组也好。呈现的非常到位。 问题&#xff1a;可是自己在实现数据分组时&#xff0c;一旦设定分组字段就出现了混乱的数据记录。 问题的原因&#xff1a; 看一下一个报表页面设计时需要理清的概念。 页头 Header&…

抖音关键词排名怎么做

抖音seo关键词搜索排名推广 产品及合作流程 了解抖音seo关键词搜索流量——用工具选择需要优化的关键词确认——预存套餐及服务——付款签约——开通关键词管理后台——建运营群流程化推进 如何选择优化的关键词? 先选3-5个主词 在工具分别输入主词 列出来的词&#xff0c…