如何在按id过滤后更新Django模型字段?

问题描述 投票:0回答:1

我想编写一个函数,当执行

"GET"
请求时,会将以下字段更改为:
"inaction"
"lastAction"
2
datetime.now()
。但是当我第一次编写代码时,遇到了错误:
TypeError: cannot unpack non-iterable int object

此代码:

def update(self, res_id: str):
        user, updated = User.objects.filter(id=res_id).update(inaction="2", lastAction=datetime.now())
        code_status = HTTPStatus.ACCEPTED if updated else HTTPStatus.OK.value
        return user, code_status

因此,我将代码重写为以下内容并开始工作:

def update(self, res_id: str):
        updated_rows = User.objects.filter(id=res_id).update(inaction="2", lastAction=datetime.now())
        user = User.objects.filter(id=res_id).first()
        code_status = HTTPStatus.ACCEPTED if updated_rows else HTTPStatus.OK.value
        return user, code_status

但是在这段代码中,我担心以下形式的重复:

User.objects.filter(id=res_id)
。我怎样才能避免它们?

models.py:

class User(models.Model):
    operatorId = models.CharField(max_length=64, null=False)
    createdAt = models.DateTimeField(auto_now_add=True, null=True)
    operator = models.CharField(max_length=10, null=True)
    inaction = models.IntegerField(default=1)
    lastAction = models.DateTimeField(null=True)

    class Meta:
        verbose_name = 'user'
        verbose_name_plural = 'users'
        db_table = "users"
        ordering = ('-createdAt',)

    def __str__(self) -> str:
        return UsersEntity.to_string(self)

实体.py

class UsersEntity:
    id: int
    operatorId: str = None
    createdAt: date = None
    operator: str = None
    inaction: int = 1

    @staticmethod
    def to_string(user: 'UsersEntity') -> str:
        operatorId = f"({user.operatorId}):" if user.operatorId else ValueError
        return f'{user.id} -> {operatorId}'
python mysql django get
1个回答
0
投票

要优化 Django 代码并避免重复

User.objects.filter(id=res_id)
查询,您应该有效地利用 Django 的查询集和事务。

你可以这样做:

from django.db import transaction
from django.utils import timezone

def update(self, res_id: str):
    with transaction.atomic():
        # Lock the rows for update and get the user instance
        user = User.objects.select_for_update().filter(id=res_id).first()

        # Check if the user exists
        if not user:
            code_status = HTTPStatus.NOT_FOUND.value
            return None, code_status

        # Update the fields
        user.inaction = 2
        user.lastAction = timezone.now()
        user.save(update_fields=['inaction', 'lastAction'])

        code_status = HTTPStatus.ACCEPTED.value
        return user, code_status

通过在此 Django 代码中使用

transaction.atomic()
,我确保所有数据库更改都粘在一起。这是一种全有或全无的方法。我还使用
select_for_update()
锁定正在处理的行,以避免两个更新同时发生时出现任何混淆。在更新之前,我检查用户是否确实存在以避免不必要的步骤。一旦找到用户,我就当场更新他们的“inaction”和“lastAction”,这更简单。另外,我使用
django.utils.timezone.now()
来正确处理时间。最后,我使用适当的代码返回用户信息,例如如果用户不存在,则显示“未找到用户”。

© www.soinside.com 2019 - 2024. All rights reserved.