Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Moved admin transaction handling from a decorator to AdminSite.admin_…

…view.
  • Loading branch information...
commit 6682fc31c810f763f08dcf14505c5762ab1d18a1 1 parent 58233e0
Dave Hall authored March 26, 2011
22  django/contrib/admin/options.py
@@ -6,10 +6,9 @@
6 6
 from django.contrib.admin import widgets, helpers
7 7
 from django.contrib.admin.util import unquote, flatten_fieldsets, get_deleted_objects, model_format_dict
8 8
 from django.contrib import messages
9  
-from django.views.decorators.csrf import csrf_protect
10 9
 from django.core.exceptions import PermissionDenied, ValidationError
11 10
 from django.core.paginator import Paginator
12  
-from django.db import models, transaction, router
  11
+from django.db import models, router
13 12
 from django.db.models.related import RelatedObject
14 13
 from django.db.models.fields import BLANK_CHOICE_DASH, FieldDoesNotExist
15 14
 from django.db.models.sql.constants import LOOKUP_SEP, QUERY_TERMS
@@ -52,8 +51,6 @@ class IncorrectLookupParameters(Exception):
52 51
     models.FileField:       {'widget': widgets.AdminFileWidget},
53 52
 }
54 53
 
55  
-csrf_protect_m = method_decorator(csrf_protect)
56  
-
57 54
 class BaseModelAdmin(object):
58 55
     """Functionality common to both ModelAdmin and InlineAdmin."""
59 56
     __metaclass__ = forms.MediaDefiningClass
@@ -302,9 +299,9 @@ def __init__(self, model, admin_site):
302 299
     def get_urls(self):
303 300
         from django.conf.urls.defaults import patterns, url
304 301
 
305  
-        def wrap(view):
  302
+        def wrap(view, use_transaction=True):
306 303
             def wrapper(*args, **kwargs):
307  
-                return self.admin_site.admin_view(view)(*args, **kwargs)
  304
+                return self.admin_site.admin_view(view, use_transaction=True)(*args, **kwargs)
308 305
             return update_wrapper(wrapper, view)
309 306
 
310 307
         info = self.model._meta.app_label, self.model._meta.module_name
@@ -314,16 +311,16 @@ def wrapper(*args, **kwargs):
314 311
                 wrap(self.changelist_view),
315 312
                 name='%s_%s_changelist' % info),
316 313
             url(r'^add/$',
317  
-                wrap(self.add_view),
  314
+                wrap(self.add_view, use_transaction=True),
318 315
                 name='%s_%s_add' % info),
319 316
             url(r'^(.+)/history/$',
320 317
                 wrap(self.history_view),
321 318
                 name='%s_%s_history' % info),
322 319
             url(r'^(.+)/delete/$',
323  
-                wrap(self.delete_view),
  320
+                wrap(self.delete_view, use_transaction=True),
324 321
                 name='%s_%s_delete' % info),
325 322
             url(r'^(.+)/$',
326  
-                wrap(self.change_view),
  323
+                wrap(self.change_view, use_transaction=True),
327 324
                 name='%s_%s_change' % info),
328 325
         )
329 326
         return urlpatterns
@@ -847,8 +844,6 @@ def response_action(self, request, queryset):
847 844
             self.message_user(request, msg)
848 845
             return None
849 846
 
850  
-    @csrf_protect_m
851  
-    @transaction.commit_on_success
852 847
     def add_view(self, request, form_url='', extra_context=None):
853 848
         "The 'add' admin view for this model."
854 849
         model = self.model
@@ -937,8 +932,6 @@ def add_view(self, request, form_url='', extra_context=None):
937 932
         context.update(extra_context or {})
938 933
         return self.render_change_form(request, context, form_url=form_url, add=True)
939 934
 
940  
-    @csrf_protect_m
941  
-    @transaction.commit_on_success
942 935
     def change_view(self, request, object_id, extra_context=None):
943 936
         "The 'change' admin view for this model."
944 937
         model = self.model
@@ -1029,7 +1022,6 @@ def change_view(self, request, object_id, extra_context=None):
1029 1022
         context.update(extra_context or {})
1030 1023
         return self.render_change_form(request, context, change=True, obj=obj)
1031 1024
 
1032  
-    @csrf_protect_m
1033 1025
     def changelist_view(self, request, extra_context=None):
1034 1026
         "The 'change list' admin view for this model."
1035 1027
         from django.contrib.admin.views.main import ERROR_FLAG
@@ -1178,8 +1170,6 @@ def changelist_view(self, request, extra_context=None):
1178 1170
             'admin/change_list.html'
1179 1171
         ], context, context_instance=context_instance)
1180 1172
 
1181  
-    @csrf_protect_m
1182  
-    @transaction.commit_on_success
1183 1173
     def delete_view(self, request, object_id, extra_context=None):
1184 1174
         "The 'delete' admin view for this model."
1185 1175
         opts = self.model._meta
12  django/contrib/admin/sites.py
@@ -6,6 +6,7 @@
6 6
 from django.contrib.contenttypes import views as contenttype_views
7 7
 from django.views.decorators.csrf import csrf_protect
8 8
 from django.db.models.base import ModelBase
  9
+from django.db import transaction
9 10
 from django.core.exceptions import ImproperlyConfigured
10 11
 from django.core.urlresolvers import reverse
11 12
 from django.shortcuts import render_to_response
@@ -168,7 +169,7 @@ def check_dependencies(self):
168 169
             raise ImproperlyConfigured("Put 'django.contrib.auth.context_processors.auth' "
169 170
                 "in your TEMPLATE_CONTEXT_PROCESSORS setting in order to use the admin application.")
170 171
 
171  
-    def admin_view(self, view, cacheable=False):
  172
+    def admin_view(self, view, cacheable=False, use_transaction=False):
172 173
         """
173 174
         Decorator to create an admin view attached to this ``AdminSite``. This
174 175
         wraps the view and provides permission checking by calling
@@ -186,10 +187,13 @@ def get_urls(self):
186 187
                         url(r'^my_view/$', self.admin_view(some_view))
187 188
                     )
188 189
                     return urls
189  
-
  190
+        
190 191
         By default, admin_views are marked non-cacheable using the
191 192
         ``never_cache`` decorator. If the view can be safely cached, set
192 193
         cacheable=True.
  194
+        
  195
+        By default, admin views are not wrapped in a transaction. If a transaction
  196
+        is needed, set use_transaction=True.
193 197
         """
194 198
         def inner(request, *args, **kwargs):
195 199
             if not self.has_permission(request):
@@ -197,6 +201,10 @@ def inner(request, *args, **kwargs):
197 201
             return view(request, *args, **kwargs)
198 202
         if not cacheable:
199 203
             inner = never_cache(inner)
  204
+        # Wrap the view in a transaction. This can't be done with a decorator,
  205
+        # as it breaks subclassing.
  206
+        if use_transaction:
  207
+            inner = transaction.commit_on_success(inner)
200 208
         # We add csrf_protect here so this function can be used as a utility
201 209
         # function for any view, without having to repeat 'csrf_protect'.
202 210
         if not getattr(view, 'csrf_exempt', False):

0 notes on commit 6682fc3

Please sign in to comment.
Something went wrong with that request. Please try again.