在Django模型中重写保存()方法时使用事务.atomic?

qxgroojn  于 2023-02-10  发布在  Go
关注(0)|答案(1)|浏览(205)

我正在覆盖模型中的默认save()方法,并在那里创建一个相关的模型示例:

def save(self, *args, **kwargs):
    super().save(*args, **kwargs)
    parent_folder = None
    if self.parent:
        parent_folder = self.parent.task_folders.all().first()

    folder, created = Folder.objects.get_or_create(
        project=self.project,
        task=self,
        parent=parent_folder,
        defaults={'name': self.name,
                  'project': self.project,
                  'task': self,
                  'creator': self.creator,
                  'parent': parent_folder,
                  'is_root': True
                  })

问题是-我应该在这里使用transaction.atomic吗?它如何与save()方法一起工作?

von4xj4u

von4xj4u1#

不,您不需要使用原子事务,例如**"@transaction. atomic "" with transaction. atomic():"explicitly foroverried" save()"Django Model中,因为原子事务默认情况下隐式用于overried" save()"
使用
PostgreSQL**,我试验了Atomic Transaction是否隐式用于默认覆盖的"save()"或不使用下面的代码。*"SELECT"、"INSERT"、"UPDATE"和"DELETE"查询由**"Animal"类代码"www.example.com"上的覆盖的"save()"**中运行,如下所示:models.py"**as shown below:

# "store/models.py"

from django.db import models

class Animal(models.Model):
    name = models.CharField(max_length=30)

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    
    def save(self, *args, **kwargs):
        
        animal = Animal.objects.all() # For "SELECT" query
        print(animal) # Needed to run "SELECT" query

        Animal(name='Dog').save() # For "INSERT" query

        Animal.objects.filter(name="Dog").update(name="Cat") # For "UPDATE" query

        Animal.objects.filter(name="Cat").delete() # For "DELETE" query

    def __str__(self):
        return self.first_name + " " + self.last_name

然后,我在**"Person"类中添加一个人来运行被覆盖的"save()",如下所示。* 实际上,没有添加人"John Smith",因为被覆盖的"save()"没有"super(). save(* args,kwargs)"

现在,在**"BEGIN"和"COMMIT"查询之间,"SELECT"、"INSERT"、"UPDATE"和"DELETE"查询"Animal"类代码覆盖的"save"中运行()"。因此,* * 原子事务隐式用于覆盖的存储()默认 * 下面这些日志是PostgreSQL的查询日志,您可以勾选在PostgreSQL上,如何记录带有事务查询的SQL查询,如"BEGIN"和"COMMIT"

此外,在被覆盖的"save()"末尾,我添加了"super(). save( args,kwargs)",它运行*"INSERT"查询**,如下所示:

# "store/models.py"

from django.db import models

class Animal(models.Model):
    name = models.CharField(max_length=30)

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    
    def save(self, *args, **kwargs):
        
        animal = Animal.objects.all() # For "SELECT" query
        print(animal) # Needed to run "SELECT" query

        Animal(name='Dog').save() # For "INSERT" query

        Animal.objects.filter(name="Dog").update(name="Cat") # For "UPDATE" query

        Animal.objects.filter(name="Cat").delete() # For "DELETE" query

        super().save(*args, **kwargs) # For "INSERT" query

    def __str__(self):
        return self.first_name + " " + self.last_name

然后,我在**"Person"类中添加一个人来运行被覆盖的"save()",如下所示。* 这次,添加了人"John Smith",因为被覆盖的"save()"具有"super(). save(* args,kwargs)"

现在,"INSERT"查询由**"super(). save(* args,kwargs)""DELETE"查询之后在**"BEGIN"和"COMMIT"查询**之间运行,如下所示:

接下来,在被覆盖的"save()"的开头,我添加"super(). save( args,kwargs)",它运行*"INSERT"查询**,如下所示:

# "store/models.py"

from django.db import models

class Animal(models.Model):
    name = models.CharField(max_length=30)

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    
    def save(self, *args, **kwargs):

        super().save(*args, **kwargs) # For "INSERT" query
        
        animal = Animal.objects.all() # For "SELECT" query
        print(animal) # Needed to run "SELECT" query

        Animal(name='Dog').save() # For "INSERT" query

        Animal.objects.filter(name="Dog").update(name="Cat") # For "UPDATE" query

        Animal.objects.filter(name="Cat").delete() # For "DELETE" query

    def __str__(self):
        return self.first_name + " " + self.last_name

然后,我在**"Person"类中添加一个人来运行被覆盖的"save()",如下所示。* 这次,添加了人"John Smith",因为被覆盖的"save()"具有"super(). save(* args,kwargs)"

现在,"INSERT"查询由**"super(). save(* args,kwargs)""SELECT"查询之前运行,位于**"BEGIN"和"COMMIT"查询**之间,如下所示:

接下来,对于被覆盖的"save()",我放置了**"@transaction. atomic "装饰器**,如下所示:

# "store/models.py"

from django.db import models

class Animal(models.Model):
    name = models.CharField(max_length=30)

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    
    @transaction.atomic # Here
    def save(self, *args, **kwargs):
        
        animal = Animal.objects.all() # For "SELECT" query
        print(animal) # Needed to run "SELECT" query

        Animal(name='Dog').save() # For "INSERT" query

        Animal.objects.filter(name="Dog").update(name="Cat") # For "UPDATE" query

        Animal.objects.filter(name="Cat").delete() # For "DELETE" query

    def __str__(self):
        return self.first_name + " " + self.last_name

或者,对于被覆盖的"save()",我将**"与transaction. atomic():"**放在一起,如下所示:

# "store/models.py"

from django.db import models

class Animal(models.Model):
    name = models.CharField(max_length=30)

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    
    def save(self, *args, **kwargs):
        
        with transaction.atomic(): # Here

            animal = Animal.objects.all() # For "SELECT" query
            print(animal) # Needed to run "SELECT" query

            Animal(name='Dog').save() # For "INSERT" query

            Animal.objects.filter(name="Dog").update(name="Cat") # For "UPDATE" query

            Animal.objects.filter(name="Cat").delete() # For "DELETE" query

    def __str__(self):
        return self.first_name + " " + self.last_name

然后,我在**"Person"类中添加一个人来运行被覆盖的"save()"**,如下所示:

现在,"SAVEPOINT"和"RELEASE SAVEPOINT"查询由**"@transaction. atomic "装饰器"使用transaction. atomic()运行:"分别在" BEGIN "查询之后和" DELETE "查询之后,位于" BEGIN "和" COMMIT "查询**之间,如下所示:

接下来,对于**,覆盖"save()"**,如下所示:

# "store/models.py"

from django.db import models

class Animal(models.Model):
    name = models.CharField(max_length=30)

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    
    def save(self, *args, **kwargs):
        
        animal = Animal.objects.all() # For "SELECT" query
        print(animal) # Needed to run "SELECT" query

        Animal(name='Dog').save() # For "INSERT" query

        Animal.objects.filter(name="Dog").update(name="Cat") # For "UPDATE" query

        Animal.objects.filter(name="Cat").delete() # For "DELETE" query

    def __str__(self):
        return self.first_name + " " + self.last_name

我输入**"原子请求":* * 对**"www.example.com"中的我的PostgreSQL设置正确:settings.py":

# "core/settings.py"

DATABASES = {
    'default':{
        'ENGINE':'django.db.backends.postgresql',
        'NAME':'postgres',
        'USER':'postgres',
        'PASSWORD':'admin',
        'HOST':'localhost',
        'PORT':'5432',
        'ATOMIC_REQUESTS': True, # Here
    }
}

然后,我在**"Person"类中添加一个人来运行被覆盖的"save()"**,如下所示:

现在,"保存点"和"释放保存点"查询由**"原子请求"运行:"Animal"类代码运行的"SELECT"查询之前和**"COMMIT"查询之前分别为真,在**"BEGIN"和"COMMIT"查询之间添加2个蓝色的"SELECT"查询**,如下所示:

接下来,对于被覆盖的"save()",我放置了**"@transaction. atomic "装饰器" with transaction. atomic():"**,如下所示:

# "store/models.py"

from django.db import models

class Animal(models.Model):
    name = models.CharField(max_length=30)

class Person(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    
    @transaction.atomic # Here
    def save(self, *args, **kwargs):
        
        with transaction.atomic(): # Here

            animal = Animal.objects.all() # For "SELECT" query
            print(animal) # Needed to run "SELECT" query

            Animal(name='Dog').save() # For "INSERT" query

            Animal.objects.filter(name="Dog").update(name="Cat") # For "UPDATE" query

            Animal.objects.filter(name="Cat").delete() # For "DELETE" query

    def __str__(self):
        return self.first_name + " " + self.last_name

而且,我还输入了**"原子请求":真"www.example.com"中的我的PostgreSQL设置**,如下所示:settings.py"**as shown below:

# "core/settings.py"

DATABASES = {
    'default':{
        'ENGINE':'django.db.backends.postgresql',
        'NAME':'postgres',
        'USER':'postgres',
        'PASSWORD':'admin',
        'HOST':'localhost',
        'PORT':'5432',
        'ATOMIC_REQUESTS': True, # Here
    }
}

然后,我在**"Person"类中添加一个人来运行被覆盖的"save()"**,如下所示:

现在,在**"BEGIN"和"COMMIT"查询之间,3个"SAVEPOINT"和3个"RELEASE SAVEPOINT"查询"@transaction. atomic "装饰器**,"使用transaction. atomic():"" ATOMIC_REQUEST "运行:添加蓝色的True2 "SELECT"查询,如下所示:

此外,再次使用PostgreSQL,我还试验了Atomic Transaction是否默认隐式用于视图,或不使用下面的代码。*"SELECT"、"INSERT"、"UPDATE"和"DELETE"查询由**"Animal"类代码"www.example.com"上的"test()"视图**中运行,如下所示:views.py"**as shown below:

# "store/views.py"

from django.http import HttpResponse
from .models import Animal

def test(request):

    animal = Animal.objects.all() # For "SELECT" query
    print(animal) # Needed to run "SELECT" query

    Animal(name='Dog').save() # For "INSERT" query

    Animal.objects.filter(name="Dog").update(name="Cat") # For "UPDATE" query

    Animal.objects.filter(name="Cat").delete() # For "DELETE" 

    return HttpResponse("Test")

这是**"www.example.com"**下面的网址:urls.py"**below:

# "store/urls.py"

from django.urls import path
from . import views

app_name = "store"

urlpatterns = [
    path('test/', views.test, name="test"),
]

然后,我打开url "http://localhost:8000/store/test/"以运行"测试"视图,如下所示:

现在,在**"BEGIN"和"COMMIT"查询之间,只有"DELETE"查询"test()"视图中的"Animal"类代码运行。因此,默认情况下,原子事务不会隐式用于视图 以下这些日志是PostgreSQL的查询日志:

接下来,对于**"test()"视图**,我放置了**"@transaction. atomic "装饰器**,如下所示:

# "store/views.py"

from django.http import HttpResponse
from .models import Animal

@transaction.atomic # Here
def test(request):
    
    animal = Animal.objects.all() # For "SELECT" query
    print(animal) # Needed to run "SELECT" query

    Animal(name='Dog').save() # For "INSERT" query

    Animal.objects.filter(name="Dog").update(name="Cat") # For "UPDATE" query

    Animal.objects.filter(name="Cat").delete() # For "DELETE" 

    return HttpResponse("Test")

或者,对于**"test()"视图**,我将**"与transaction. atomic():"**放在一起,如下所示:

# "store/views.py"

from django.http import HttpResponse
from .models import Animal

def test(request):

    with transaction.atomic(): # Here
    
        animal = Animal.objects.all() # For "SELECT" query
        print(animal) # Needed to run "SELECT" query

        Animal(name='Dog').save() # For "INSERT" query

        Animal.objects.filter(name="Dog").update(name="Cat") # For "UPDATE" query

        Animal.objects.filter(name="Cat").delete() # For "DELETE" 

        return HttpResponse("Test")

或者,对于**"test()"视图**,我将**"原子请求":真"www.example.com"中的我的PostgreSQL设置**,如下所示:settings.py"**as shown below:

# "core/settings.py"

DATABASES = {
    'default':{
        'ENGINE':'django.db.backends.postgresql',
        'NAME':'postgres',
        'USER':'postgres',
        'PASSWORD':'admin',
        'HOST':'localhost',
        'PORT':'5432',
        'ATOMIC_REQUESTS': True, # Here
    }
}

然后,我打开url "http://localhost:8000/store/test/"以运行"测试"视图,如下所示:

现在,在**"BEGIN"和"COMMIT"查询之间,"SELECT"、"INSERT"、"UPDATE"和"DELETE"查询"Test()"视图中的"Animal"类代码**运行。因此,现在,原子事务工作:

接下来,对于**"test()"视图**,我将**"@transaction. atomic "装饰器"与transaction. atomic():"**放在一起,如下所示:

# "store/views.py"

from django.http import HttpResponse
from .models import Animal

@transaction.atomic # Here
def test(request):
    
    with transaction.atomic(): # Here
        
        animal = Animal.objects.all() # For "SELECT" query
        print(animal) # Needed to run "SELECT" query

        Animal(name='Dog').save() # For "INSERT" query

        Animal.objects.filter(name="Dog").update(name="Cat") # For "UPDATE" query

        Animal.objects.filter(name="Cat").delete() # For "DELETE" 

        return HttpResponse("Test")

而且,我还输入了**"原子请求":真"www.example.com"中的我的PostgreSQL设置**,如下所示:settings.py"**as shown below:

# "core/settings.py"

DATABASES = {
    'default':{
        'ENGINE':'django.db.backends.postgresql',
        'NAME':'postgres',
        'USER':'postgres',
        'PASSWORD':'admin',
        'HOST':'localhost',
        'PORT':'5432',
        'ATOMIC_REQUESTS': True, # Here
    }
}

然后,我打开url "http://localhost:8000/store/test/"以运行"测试"视图,如下所示:

现在,在**"BEGIN"和"COMMIT"查询之间,运行2个"SAVEPOINT"和2个"RELEASE SAVEPOINT"查询**,如下所示:

相关问题