简体   繁体   English

如何在 Django Admin 中禁用事务?

[英]How to disable transaction in Django Admin?

I used @transaction.non_atomic_requests for the overridden save() in Person model as shown below:我在Person模型中使用@transaction.non_atomic_requests覆盖save() ,如下所示:

# "store/models.py"

from django.db import models
from django.db import transaction

class Person(models.Model):
    name = models.CharField(max_length=30)
    
    @transaction.non_atomic_requests # Here
    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)

And, I also used @transaction.non_atomic_requests for the overridden save_model() in Person admin as shown below:而且,我还在Person admin中使用@transaction.non_atomic_requests覆盖save_model() ,如下所示:

# "store/admin.py"

from django.contrib import admin
from .models import Person
from django.db import transaction

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):

    @transaction.non_atomic_requests # Here
    def save_model(self, request, obj, form, change):
        obj.save()

But, when adding data as shown below:但是,添加数据时如下所示:

在此处输入图像描述

Transaction is used as shown below.交易使用如下所示。 *I use PostgreSQL and these logs below are the queries of PostgreSQL and you can check On PostgreSQL, how to log queries with transaction queries such as "BEGIN" and "COMMIT" : *我使用PostgreSQL ,下面的这些日志是PostgreSQL 的查询,您可以检查On PostgreSQL,如何使用事务查询(例如“BEGIN”和“COMMIT”)记录查询

在此处输入图像描述

And, when changing data as shown below:并且,当如下所示更改数据时:

在此处输入图像描述

Transaction is used as shown below:事务使用如下所示:

在此处输入图像描述

And, when clicking Delete button of Change person as shown below:并且,当单击Change personDelete按钮时,如下所示:

在此处输入图像描述

Then clicking Yes, I'm sure button to delete data as shown below:然后单击Yes, I'm sure按钮删除数据,如下所示:

在此处输入图像描述

Transaction is used as shown below:事务使用如下所示:

在此处输入图像描述

And, when selecting Delete selected persons and clicking Go button of Select person to change as shown below:并且,选择Delete selected persons并单击“选择人员的Go按钮以更改如下:

在此处输入图像描述

Then clicking Yes, I'm sure button to delete data as shown below:然后单击Yes, I'm sure按钮删除数据,如下所示:

在此处输入图像描述

Transaction is used as shown below:事务使用如下所示:

在此处输入图像描述

So, how can I disable transaction in Django Admin ?那么,如何在Django Admin中禁用事务

First to disable transaction when adding and changing data, you need to override changeform_view() in Person admin as shown below:首先要在添加和更改数据时禁用事务,您需要在Person admin中覆盖changeform_view() ,如下所示:

# "store/admin.py"

from django.contrib import admin
from .models import Person
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_protect

csrf_protect_m = method_decorator(csrf_protect)

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):

    @csrf_protect_m # Here
    def changeform_view(self, request, object_id=None, form_url="", extra_context=None):
        return super()._changeform_view(request, object_id, form_url, extra_context)

Because by default, changeform_view() has with transaction.atomic(...): to use transaction when adding and changing data as shown below:因为默认情况下, changeform_view()具有with transaction.atomic(...):在添加和更改数据时使用事务,如下所示:

class ModelAdmin(BaseModelAdmin):
    
    # ...
    
    @csrf_protect_m
    def changeform_view(self, request, object_id=None, form_url="", extra_context=None):
        with transaction.atomic(using=router.db_for_write(self.model)): # Here
            return self._changeform_view(request, object_id, form_url, extra_context)

As a result, when adding data as shown below:结果,添加数据时如下图:

在此处输入图像描述

Transaction is not used as shown below:事务未使用如下所示:

在此处输入图像描述

And, when changing data as shown below:并且,当如下所示更改数据时:

在此处输入图像描述

Transaction is not used as shown below:事务未使用如下所示:

在此处输入图像描述

Next to disable transaction when clicking Delete button of Change person then clicking Yes, I'm sure button to delete data, you need to override delete_view() in Person admin as shown below:单击Change personDelete按钮然后单击Yes, I'm sure按钮删除数据时要禁用事务,您需要在Person admin中覆盖delete_view() ,如下所示:

# "store/admin.py"

from django.contrib import admin
from .models import Person
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_protect

csrf_protect_m = method_decorator(csrf_protect)

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):

    @csrf_protect_m # Here
    def delete_view(self, request, object_id, extra_context=None):
        return self._delete_view(request, object_id, extra_context)

Because by default, delete_view() has with transaction.atomic(...): to use transaction when clicking Delete button of Change person then clicking Yes, I'm sure button to delete data as shown below:因为默认情况下, delete_view()具有with transaction.atomic(...):在单击Change personDelete按钮然后单击Yes, I'm sure按钮删除数据时使用事务,如下所示:

class ModelAdmin(BaseModelAdmin):
    
    # ...
    
    @csrf_protect_m
    def delete_view(self, request, object_id, extra_context=None):
        with transaction.atomic(using=router.db_for_write(self.model)): # Here
            return super()._delete_view(request, object_id, extra_context)

As a result, when clicking Delete button of Change person as shown below:结果,当点击Change personDelete按钮时,如下图:

在此处输入图像描述

Then clicking Yes, I'm sure button to delete data as shown below:然后单击Yes, I'm sure按钮删除数据,如下所示:

在此处输入图像描述

Transaction is not used as shown below:事务未使用如下所示:

在此处输入图像描述

Next to disable transaction when selecting Delete selected persons and clicking Go button of Select person to change then clicking Yes, I'm sure button to delete data, you need to override delete_queryset() in Person admin then run a raw query with cursor.execute() as shown below:在选择“ Delete selected persons ”并单击“选择人员”的Go按钮进行更改然后单击Yes, I'm sure按钮删除数据时要禁用事务,您需要在Person管理中覆盖delete_queryset() ,然后使用cursor.execute()运行原始查询cursor.execute()如下图:

# "store/admin.py"

from django.contrib import admin
from .models import Person
from django.db import connection

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):

    def delete_queryset(self, request, queryset): # Here
        ids = ()
        
        if len(queryset) > 1:
            for obj in queryset:
                ids += (obj.id,)
            ids = str(ids)
        else:
            ids = "(" + str(queryset[0].id) + ")"

        with connection.cursor() as cursor:
            query = 'DELETE FROM "store_person" WHERE "store_person"."id" IN ' + ids
            cursor.execute(query)

Because by default, delete_queryset() has queryset.delete() which runs DELETE query with transaction when selecting Delete selected persons and clicking Go button of Select person to change then clicking Yes, I'm sure button to delete data as shown below:因为默认情况下, delete_queryset()具有queryset.delete() ,它在选择Delete selected persons并单击选择人员的Go按钮进行更改时使用事务运行DELETE查询,然后单击Yes, I'm sure按钮删除数据,如下所示:

class ModelAdmin(BaseModelAdmin):
    
    # ...
    
    def delete_queryset(self, request, queryset):
        """Given a queryset, delete it from the database."""
        queryset.delete() # Here

As a result, when selecting Delete selected persons and clicking Go button of Select person to change as shown below:结果,选择Delete selected persons并单击“选择人的Go按钮,如下所示:

在此处输入图像描述

Then clicking Yes, I'm sure button to delete data as shown below:然后单击Yes, I'm sure按钮删除数据,如下所示:

在此处输入图像描述

Transaction is not used as shown below:事务未使用如下所示:

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM