Ticket #9964: 9964-against-10087.diff
File 9964-against-10087.diff, 35.3 KB (added by , 16 years ago) |
---|
-
django/db/transaction/fast_select.py
10 10 11 11 Managed transactions don't do those commits, but will need some kind of manual 12 12 or implicit commits or rollbacks. 13 14 This is a version of the transaction manager which marks transactions 15 as 'clean' or 'dirty', and neglects to close 'clean' transactions to 16 improve performnce. 17 18 TODO: Explain when this breaks, and when it is less efficient 13 19 """ 14 20 21 15 22 try: 16 23 import thread 17 24 except ImportError: 18 25 import dummy_thread as thread 19 try: 20 from functools import wraps 21 except ImportError: 22 from django.utils.functional import wraps # Python 2.3, 2.4 fallback. 26 23 27 from django.db import connection 24 28 from django.conf import settings 25 29 26 class TransactionManagementError(Exception): 27 """ 28 This exception is thrown when something bad happens with transaction 29 management. 30 """ 31 pass 30 from django.db.transaction import TransactionManagementError 31 from django.db.transaction import state, savepoint_state 32 from django.db.transaction import is_managed, clean_savepoints, rollback 32 33 33 # The states are dictionaries of lists. The key to the dict is the current34 # thread and the list is handled as a stack of values.35 state = {}36 savepoint_state = {}37 38 34 # The dirty flag is set by *_unless_managed functions to denote that the 39 35 # code under transaction management has changed things to require a 40 36 # database commit. … … 109 105 raise TransactionManagementError("This code isn't under transaction management") 110 106 clean_savepoints() 111 107 112 def clean_savepoints():113 thread_ident = thread.get_ident()114 if thread_ident in savepoint_state:115 del savepoint_state[thread_ident]116 117 def is_managed():118 """119 Checks whether the transaction manager is in manual or in auto state.120 """121 thread_ident = thread.get_ident()122 if thread_ident in state:123 if state[thread_ident]:124 return state[thread_ident][-1]125 return settings.TRANSACTIONS_MANAGED126 127 def managed(flag=True):128 """129 Puts the transaction manager into a manual state: managed transactions have130 to be committed explicitly by the user. If you switch off transaction131 management and there is a pending commit/rollback, the data will be132 commited.133 """134 thread_ident = thread.get_ident()135 top = state.get(thread_ident, None)136 if top:137 top[-1] = flag138 if not flag and is_dirty():139 connection._commit()140 set_clean()141 else:142 raise TransactionManagementError("This code isn't under transaction management")143 144 def commit_unless_managed():145 """146 Commits changes if the system is not in managed transaction mode.147 """148 if not is_managed():149 connection._commit()150 clean_savepoints()151 else:152 set_dirty()153 154 def rollback_unless_managed():155 """156 Rolls back changes if the system is not in managed transaction mode.157 """158 if not is_managed():159 connection._rollback()160 else:161 set_dirty()162 163 def commit():164 """165 Does the commit itself and resets the dirty flag.166 """167 connection._commit()168 set_clean()169 170 def rollback():171 """172 This function does the rollback itself and resets the dirty flag.173 """174 connection._rollback()175 set_clean()176 177 def savepoint():178 """179 Creates a savepoint (if supported and required by the backend) inside the180 current transaction. Returns an identifier for the savepoint that will be181 used for the subsequent rollback or commit.182 """183 thread_ident = thread.get_ident()184 if thread_ident in savepoint_state:185 savepoint_state[thread_ident].append(None)186 else:187 savepoint_state[thread_ident] = [None]188 tid = str(thread_ident).replace('-', '')189 sid = "s%s_x%d" % (tid, len(savepoint_state[thread_ident]))190 connection._savepoint(sid)191 return sid192 193 def savepoint_rollback(sid):194 """195 Rolls back the most recent savepoint (if one exists). Does nothing if196 savepoints are not supported.197 """198 if thread.get_ident() in savepoint_state:199 connection._savepoint_rollback(sid)200 201 def savepoint_commit(sid):202 """203 Commits the most recent savepoint (if one exists). Does nothing if204 savepoints are not supported.205 """206 if thread.get_ident() in savepoint_state:207 connection._savepoint_commit(sid)208 209 ##############210 # DECORATORS #211 ##############212 213 def autocommit(func):214 """215 Decorator that activates commit on save. This is Django's default behavior;216 this decorator is useful if you globally activated transaction management in217 your settings file and want the default behavior in some view functions.218 """219 def _autocommit(*args, **kw):220 try:221 enter_transaction_management(managed=False)222 managed(False)223 return func(*args, **kw)224 finally:225 leave_transaction_management()226 return wraps(func)(_autocommit)227 228 def commit_on_success(func):229 """230 This decorator activates commit on response. This way, if the view function231 runs successfully, a commit is made; if the viewfunc produces an exception,232 a rollback is made. This is one of the most common ways to do transaction233 control in web apps.234 """235 def _commit_on_success(*args, **kw):236 try:237 enter_transaction_management()238 managed(True)239 try:240 res = func(*args, **kw)241 except:242 # All exceptions must be handled here (even string ones).243 if is_dirty():244 rollback()245 raise246 else:247 if is_dirty():248 commit()249 return res250 finally:251 leave_transaction_management()252 return wraps(func)(_commit_on_success)253 254 def commit_manually(func):255 """256 Decorator that activates manual transaction control. It just disables257 automatic transaction control and doesn't do any commit/rollback of its258 own -- it's up to the user to call the commit and rollback functions259 themselves.260 """261 def _commit_manually(*args, **kw):262 try:263 enter_transaction_management()264 managed(True)265 return func(*args, **kw)266 finally:267 leave_transaction_management()268 269 return wraps(func)(_commit_manually) -
django/db/transaction/safe.py
1 """ 2 This module implements a transaction manager that can be used to define 3 transaction handling in a request or view function. It is used by transaction 4 control middleware and decorators. 5 6 The transaction manager can be in managed or in auto state. Auto state means the 7 system is using a commit-on-save strategy (actually it's more like 8 commit-on-change). As soon as the .save() or .delete() (or related) methods are 9 called, a commit is made. 10 11 Managed transactions don't do those commits, but will need some kind of manual 12 or implicit commits or rollbacks. 13 14 This is a version of the transaction manager which treats all transactions 15 as 'dirty', so that they are always closed. 16 """ 17 18 try: 19 import thread 20 except ImportError: 21 import dummy_thread as thread 22 try: 23 from functools import wraps 24 except ImportError: 25 from django.utils.functional import wraps # Python 2.3, 2.4 fallback. 26 from django.db import connection 27 from django.conf import settings 28 29 from django.db.transaction import TransactionManagementError 30 from django.db.transaction import state, savepoint_state 31 from django.db.transaction import is_managed, clean_savepoints, rollback 32 33 34 def enter_transaction_management(managed=True): 35 """ 36 Enters transaction management for a running thread. It must be balanced with 37 the appropriate leave_transaction_management call, since the actual state is 38 managed as a stack. 39 40 The state and dirty flag are carried over from the surrounding block or 41 from the settings, if there is no surrounding block (dirty is always false 42 when no current block is running). 43 """ 44 thread_ident = thread.get_ident() 45 if thread_ident in state and state[thread_ident]: 46 state[thread_ident].append(state[thread_ident][-1]) 47 else: 48 state[thread_ident] = [] 49 state[thread_ident].append(settings.TRANSACTIONS_MANAGED) 50 connection._enter_transaction_management(managed) 51 52 def leave_transaction_management(): 53 """ 54 Leaves transaction management for a running thread. 55 """ 56 connection._leave_transaction_management(is_managed()) 57 thread_ident = thread.get_ident() 58 if thread_ident in state and state[thread_ident]: 59 del state[thread_ident][-1] 60 else: 61 raise TransactionManagementError("This code isn't under transaction management") 62 # TODO: This has two drawbacks: 63 # - It generates a redundant database hit in most cases 64 # - As we no longer tell whether a transaction is dirty, 65 # we cannot throw exceptions if a transaction is pending 66 # To go on the safe side, anything not committed should be rolled back 67 rollback() 68 69 def is_dirty(): 70 """ 71 All transactions are always dirty 72 """ 73 return True 74 75 def set_dirty(): 76 """ 77 All transactions are always dirty 78 """ 79 pass 80 81 def set_clean(): 82 """ 83 All transactions are always dirty 84 """ 85 # TODO: Really? Retained from the fast_select version 86 clean_savepoints() 87 88 89 90 -
django/db/transaction/__init__.py
1 """ 2 This module supports selection, by a setting, of a 3 transaction management "policy". Current policies 4 are "fast-select" (which leaves clean transactions 5 open) and "safe" (which makes sure all transactions 6 are closed, whether they are committed or rolled back. 7 8 TODO: Document when fast is not safe, and when fast is 9 not even fast (repatable-read w/out MVCC). 10 """ 11 12 ############### 13 # Common base # 14 ############### 15 16 # These are common to the policies 17 try: 18 import thread 19 except ImportError: 20 import dummy_thread as thread 21 try: 22 from functools import wraps 23 except ImportError: 24 from django.utils.functional import wraps # Python 2.3, 2.4 fallback. 25 from django.db import connection 26 from django.conf import settings 27 from django.core.exceptions import ImproperlyConfigured 28 29 class TransactionManagementError(Exception): 30 """ 31 This exception is thrown when something bad happens with transaction 32 management. 33 """ 34 pass 35 36 # The states are dictionaries of lists. The key to the dict is the current 37 # thread and the list is handled as a stack of values. 38 state = {} 39 savepoint_state = {} 40 41 def is_managed(): 42 """ 43 Checks whether the transaction manager is in manual or in auto state. 44 Note: True means 'managed manually', False means 'auto' 45 """ 46 thread_ident = thread.get_ident() 47 if thread_ident in state: 48 if state[thread_ident]: 49 return state[thread_ident][-1] 50 return settings.TRANSACTIONS_MANAGED 51 52 def managed(flag=True): 53 """ 54 Puts the transaction manager into a manual state: managed transactions have 55 to be committed explicitly by the user. If you switch off transaction 56 management and there is a pending commit/rollback, the data will be 57 commited. 58 """ 59 thread_ident = thread.get_ident() 60 top = state.get(thread_ident, None) 61 if top: 62 top[-1] = flag 63 if not flag and is_dirty(): 64 connection._commit() 65 set_clean() 66 else: 67 raise TransactionManagementError("This code isn't under transaction management") 68 69 def commit_unless_managed(): 70 """ 71 Commits changes if the system is not in managed transaction mode. 72 """ 73 if not is_managed(): 74 connection._commit() 75 clean_savepoints() 76 else: 77 set_dirty() 78 79 def rollback_unless_managed(): 80 """ 81 Rolls back changes if the system is not in managed transaction mode. 82 """ 83 if not is_managed(): 84 connection._rollback() 85 else: 86 set_dirty() 87 88 def commit(): 89 """ 90 Does the commit itself and resets the dirty flag. 91 """ 92 connection._commit() 93 set_clean() 94 95 def rollback(): 96 """ 97 This function does the rollback itself and resets the dirty flag. 98 """ 99 connection._rollback() 100 set_clean() 101 102 def clean_savepoints(): 103 thread_ident = thread.get_ident() 104 if thread_ident in savepoint_state: 105 del savepoint_state[thread_ident] 106 107 def savepoint(): 108 """ 109 Creates a savepoint (if supported and required by the backend) inside the 110 current transaction. Returns an identifier for the savepoint that will be 111 used for the subsequent rollback or commit. 112 """ 113 thread_ident = thread.get_ident() 114 if thread_ident in savepoint_state: 115 savepoint_state[thread_ident].append(None) 116 else: 117 savepoint_state[thread_ident] = [None] 118 tid = str(thread_ident).replace('-', '') 119 sid = "s%s_x%d" % (tid, len(savepoint_state[thread_ident])) 120 connection._savepoint(sid) 121 return sid 122 123 def savepoint_rollback(sid): 124 """ 125 Rolls back the most recent savepoint (if one exists). Does nothing if 126 savepoints are not supported. 127 """ 128 if thread.get_ident() in savepoint_state: 129 connection._savepoint_rollback(sid) 130 131 def savepoint_commit(sid): 132 """ 133 Commits the most recent savepoint (if one exists). Does nothing if 134 savepoints are not supported. 135 """ 136 if thread.get_ident() in savepoint_state: 137 connection._savepoint_commit(sid) 138 139 ##################### 140 # Policy controlled # 141 ##################### 142 143 ## DRY-minimizing set of functions for policy control 144 145 def _get_policy_module(): 146 policy = getattr(settings, 'TRANSACTION_POLICY', 'fast_select') 147 if policy=='fast_select': 148 import fast_select 149 return fast_select 150 elif policy=='safe': 151 import safe 152 return safe 153 else: 154 raise ImproperlyConfigured, "Unknown transaction policy '%s'" % str(policy) 155 156 _to_be_loaded = [] 157 158 def _load_from_policy_module(): 159 module = _get_policy_module() 160 for name in _to_be_loaded: 161 globals()[name] = getattr(module, name[1:]) 162 163 164 def policy_controlled(func): 165 """ 166 For a function "func", defines a function "_func" which, when 167 first called, replaces itself with function "func" from the 168 policy module. Thus, the implementation of func here can 169 just be written: 170 def func() 171 return _func() 172 policy_controlled(func) 173 """ 174 place_holder_name = "_" + func.func_name 175 def place_holder_func(*args, **kwargs): 176 """ 177 This code is only executed on the first place_holder func to be called 178 """ 179 #print "policy_controlled, replacing ",place_holder_name 180 _load_from_policy_module() 181 real_func = globals()[place_holder_name] 182 return real_func(*args, **kwargs) 183 globals()[place_holder_name] = place_holder_func 184 _to_be_loaded.append(place_holder_name) 185 return func 186 187 # The policy controlled functions 188 189 def enter_transaction_management(managed=True): 190 return _enter_transaction_management(managed) 191 policy_controlled(enter_transaction_management) 192 193 def leave_transaction_management(): 194 return _leave_transaction_management() 195 policy_controlled(leave_transaction_management) 196 197 def is_dirty(): 198 return _is_dirty() 199 policy_controlled(is_dirty) 200 201 def set_dirty(): 202 return _set_dirty() 203 policy_controlled(set_dirty) 204 205 def set_clean(): 206 return _set_clean() 207 policy_controlled(set_clean) 208 209 ############## 210 # DECORATORS # 211 ############## 212 213 # Decorators use the above functions, and their own code 214 # doesn't need to change to reflect policy; they are 215 # defined here to make sure they reference the right versions 216 # of the functions they use 217 218 def autocommit(func): 219 """ 220 Decorator that activates commit on save. This is Django's default behavior; 221 this decorator is useful if you globally activated transaction management in 222 your settings file and want the default behavior in some view functions. 223 """ 224 def _autocommit(*args, **kw): 225 try: 226 enter_transaction_management(managed=False) 227 managed(False) 228 return func(*args, **kw) 229 finally: 230 leave_transaction_management() 231 return wraps(func)(_autocommit) 232 233 def commit_on_success(func): 234 """ 235 This decorator activates commit on response. This way, if the view function 236 runs successfully, a commit is made; if the viewfunc produces an exception, 237 a rollback is made. This is one of the most common ways to do transaction 238 control in web apps. 239 """ 240 def _commit_on_success(*args, **kw): 241 try: 242 enter_transaction_management() 243 managed(True) 244 try: 245 res = func(*args, **kw) 246 except: 247 # All exceptions must be handled here (even string ones). 248 if is_dirty(): 249 rollback() 250 raise 251 else: 252 if is_dirty(): 253 commit() 254 return res 255 finally: 256 leave_transaction_management() 257 return wraps(func)(_commit_on_success) 258 259 def commit_manually(func): 260 """ 261 Decorator that activates manual transaction control. It just disables 262 automatic transaction control and doesn't do any commit/rollback of its 263 own -- it's up to the user to call the commit and rollback functions 264 themselves. 265 """ 266 def _commit_manually(*args, **kw): 267 try: 268 enter_transaction_management() 269 managed(True) 270 return func(*args, **kw) 271 finally: 272 leave_transaction_management() 273 274 return wraps(func)(_commit_manually) -
django/db/transaction.py
1 """2 This module implements a transaction manager that can be used to define3 transaction handling in a request or view function. It is used by transaction4 control middleware and decorators.5 6 The transaction manager can be in managed or in auto state. Auto state means the7 system is using a commit-on-save strategy (actually it's more like8 commit-on-change). As soon as the .save() or .delete() (or related) methods are9 called, a commit is made.10 11 Managed transactions don't do those commits, but will need some kind of manual12 or implicit commits or rollbacks.13 """14 15 try:16 import thread17 except ImportError:18 import dummy_thread as thread19 try:20 from functools import wraps21 except ImportError:22 from django.utils.functional import wraps # Python 2.3, 2.4 fallback.23 from django.db import connection24 from django.conf import settings25 26 class TransactionManagementError(Exception):27 """28 This exception is thrown when something bad happens with transaction29 management.30 """31 pass32 33 # The states are dictionaries of lists. The key to the dict is the current34 # thread and the list is handled as a stack of values.35 state = {}36 savepoint_state = {}37 38 # The dirty flag is set by *_unless_managed functions to denote that the39 # code under transaction management has changed things to require a40 # database commit.41 dirty = {}42 43 def enter_transaction_management(managed=True):44 """45 Enters transaction management for a running thread. It must be balanced with46 the appropriate leave_transaction_management call, since the actual state is47 managed as a stack.48 49 The state and dirty flag are carried over from the surrounding block or50 from the settings, if there is no surrounding block (dirty is always false51 when no current block is running).52 """53 thread_ident = thread.get_ident()54 if thread_ident in state and state[thread_ident]:55 state[thread_ident].append(state[thread_ident][-1])56 else:57 state[thread_ident] = []58 state[thread_ident].append(settings.TRANSACTIONS_MANAGED)59 if thread_ident not in dirty:60 dirty[thread_ident] = False61 connection._enter_transaction_management(managed)62 63 def leave_transaction_management():64 """65 Leaves transaction management for a running thread. A dirty flag is carried66 over to the surrounding block, as a commit will commit all changes, even67 those from outside. (Commits are on connection level.)68 """69 connection._leave_transaction_management(is_managed())70 thread_ident = thread.get_ident()71 if thread_ident in state and state[thread_ident]:72 del state[thread_ident][-1]73 else:74 raise TransactionManagementError("This code isn't under transaction management")75 if dirty.get(thread_ident, False):76 rollback()77 raise TransactionManagementError("Transaction managed block ended with pending COMMIT/ROLLBACK")78 dirty[thread_ident] = False79 80 def is_dirty():81 """82 Returns True if the current transaction requires a commit for changes to83 happen.84 """85 return dirty.get(thread.get_ident(), False)86 87 def set_dirty():88 """89 Sets a dirty flag for the current thread and code streak. This can be used90 to decide in a managed block of code to decide whether there are open91 changes waiting for commit.92 """93 thread_ident = thread.get_ident()94 if thread_ident in dirty:95 dirty[thread_ident] = True96 else:97 raise TransactionManagementError("This code isn't under transaction management")98 99 def set_clean():100 """101 Resets a dirty flag for the current thread and code streak. This can be used102 to decide in a managed block of code to decide whether a commit or rollback103 should happen.104 """105 thread_ident = thread.get_ident()106 if thread_ident in dirty:107 dirty[thread_ident] = False108 else:109 raise TransactionManagementError("This code isn't under transaction management")110 clean_savepoints()111 112 def clean_savepoints():113 thread_ident = thread.get_ident()114 if thread_ident in savepoint_state:115 del savepoint_state[thread_ident]116 117 def is_managed():118 """119 Checks whether the transaction manager is in manual or in auto state.120 """121 thread_ident = thread.get_ident()122 if thread_ident in state:123 if state[thread_ident]:124 return state[thread_ident][-1]125 return settings.TRANSACTIONS_MANAGED126 127 def managed(flag=True):128 """129 Puts the transaction manager into a manual state: managed transactions have130 to be committed explicitly by the user. If you switch off transaction131 management and there is a pending commit/rollback, the data will be132 commited.133 """134 thread_ident = thread.get_ident()135 top = state.get(thread_ident, None)136 if top:137 top[-1] = flag138 if not flag and is_dirty():139 connection._commit()140 set_clean()141 else:142 raise TransactionManagementError("This code isn't under transaction management")143 144 def commit_unless_managed():145 """146 Commits changes if the system is not in managed transaction mode.147 """148 if not is_managed():149 connection._commit()150 clean_savepoints()151 else:152 set_dirty()153 154 def rollback_unless_managed():155 """156 Rolls back changes if the system is not in managed transaction mode.157 """158 if not is_managed():159 connection._rollback()160 else:161 set_dirty()162 163 def commit():164 """165 Does the commit itself and resets the dirty flag.166 """167 connection._commit()168 set_clean()169 170 def rollback():171 """172 This function does the rollback itself and resets the dirty flag.173 """174 connection._rollback()175 set_clean()176 177 def savepoint():178 """179 Creates a savepoint (if supported and required by the backend) inside the180 current transaction. Returns an identifier for the savepoint that will be181 used for the subsequent rollback or commit.182 """183 thread_ident = thread.get_ident()184 if thread_ident in savepoint_state:185 savepoint_state[thread_ident].append(None)186 else:187 savepoint_state[thread_ident] = [None]188 tid = str(thread_ident).replace('-', '')189 sid = "s%s_x%d" % (tid, len(savepoint_state[thread_ident]))190 connection._savepoint(sid)191 return sid192 193 def savepoint_rollback(sid):194 """195 Rolls back the most recent savepoint (if one exists). Does nothing if196 savepoints are not supported.197 """198 if thread.get_ident() in savepoint_state:199 connection._savepoint_rollback(sid)200 201 def savepoint_commit(sid):202 """203 Commits the most recent savepoint (if one exists). Does nothing if204 savepoints are not supported.205 """206 if thread.get_ident() in savepoint_state:207 connection._savepoint_commit(sid)208 209 ##############210 # DECORATORS #211 ##############212 213 def autocommit(func):214 """215 Decorator that activates commit on save. This is Django's default behavior;216 this decorator is useful if you globally activated transaction management in217 your settings file and want the default behavior in some view functions.218 """219 def _autocommit(*args, **kw):220 try:221 enter_transaction_management(managed=False)222 managed(False)223 return func(*args, **kw)224 finally:225 leave_transaction_management()226 return wraps(func)(_autocommit)227 228 def commit_on_success(func):229 """230 This decorator activates commit on response. This way, if the view function231 runs successfully, a commit is made; if the viewfunc produces an exception,232 a rollback is made. This is one of the most common ways to do transaction233 control in web apps.234 """235 def _commit_on_success(*args, **kw):236 try:237 enter_transaction_management()238 managed(True)239 try:240 res = func(*args, **kw)241 except:242 # All exceptions must be handled here (even string ones).243 if is_dirty():244 rollback()245 raise246 else:247 if is_dirty():248 commit()249 return res250 finally:251 leave_transaction_management()252 return wraps(func)(_commit_on_success)253 254 def commit_manually(func):255 """256 Decorator that activates manual transaction control. It just disables257 automatic transaction control and doesn't do any commit/rollback of its258 own -- it's up to the user to call the commit and rollback functions259 themselves.260 """261 def _commit_manually(*args, **kw):262 try:263 enter_transaction_management()264 managed(True)265 return func(*args, **kw)266 finally:267 leave_transaction_management()268 269 return wraps(func)(_commit_manually) -
django/conf/project_template/settings.py
16 16 DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3. 17 17 DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3. 18 18 19 20 TRANSACTION_POLICY = 'safe' # Options: 'safe','fast_select'; TODO: better doc. 21 19 22 # Local time zone for this installation. Choices can be found here: 20 23 # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name 21 24 # although not all choices may be available on all operating systems. -
django/conf/global_settings.py
131 131 DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3. 132 132 DATABASE_OPTIONS = {} # Set to empty dictionary for default. 133 133 134 134 135 # Host for sending e-mail. 135 136 EMAIL_HOST = 'localhost' 136 137 … … 282 283 283 284 # Do you want to manage transactions manually? 284 285 # Hint: you really don't! 285 TRANSACTIONS_MANAGED = False 286 TRANSACTIONS_MANAGED = False # False means 'automatic' 286 287 288 # Django's policy for managed database transactions. 289 # The current options are: 290 # 'safe': always end transaction at the end of request processing. 291 # 'fast_select': leave "clean" transactions open for reuse; pre-1.1 behavior. 292 TRANSACTION_POLICY = 'fast_select' 293 287 294 # The User-Agent string to use when checking for URL validity through the 288 295 # isExistingURL validator. 289 296 from django import get_version -
tests/modeltests/transactions/models.py
86 86 >>> Reporter.objects.all() 87 87 [<Reporter: Ben Jones>, <Reporter: Carol Doe>] 88 88 89 # If you forget, you'll get bad errors89 # If you forget, you'll get errors or rollbacks, depending on transaction policy 90 90 >>> def manually_managed_mistake(): 91 91 ... r = Reporter(first_name="David", last_name="Davidson") 92 92 ... r.save() 93 93 ... # oops, I forgot to commit/rollback! 94 94 >>> manually_managed_mistake = transaction.commit_manually(manually_managed_mistake) 95 >>> manually_managed_mistake() 95 >>> manually_managed_mistake()""" 96 97 # Note: The above string must not include a final newline! 98 99 if getattr(settings, 'TRANSACTION_POLICY', 'fast_select')!='safe': 100 __test__['API_TESTS'] += """ 96 101 Traceback (most recent call last): 97 102 ... 98 103 TransactionManagementError: Transaction managed block ended with pending COMMIT/ROLLBACK 99 104 """ 105 else: 106 __test__['API_TESTS'] += """ 107 >>> Reporter.objects.all() 108 [<Reporter: Ben Jones>, <Reporter: Carol Doe>] 109 110 """ -
tests/modeltests/transaction_middleware/__init__.py
1 -
tests/modeltests/transaction_middleware/models.py
1 1 """ 2 15 . Transactions2 15m. Transaction Middleware 3 3 4 Django handles transactions in three different ways. The default is to commit 5 each transaction upon a write, but you can decorate a function to get 6 commit-on-success behavior. Alternatively, you can manage the transaction 7 manually. 4 Django's Transaction Middleware offers a simple consistent way 5 to wrap every request in a transaction. The behavior is supposed 6 to be equivalent to commit_on_success applied to the entire request 7 processing (within the scope of the middleware, of course). 8 These tests are closely related to the transaction tests, of course. 8 9 """ 9 10 10 11 from django.db import models … … 18 19 return u"%s %s" % (self.first_name, self.last_name) 19 20 20 21 __test__ = {'API_TESTS':""" 22 >>> from django.middleware.transaction import TransactionMiddleware 23 >>> from django.utils.decorators import decorator_from_middleware 24 >>> xact_middle = decorator_from_middleware(TransactionMiddleware) 21 25 >>> from django.db import connection, transaction 22 26 """} 23 27 … … 53 57 >>> Reporter.objects.all() 54 58 [<Reporter: Alice Smith>, <Reporter: Ben Jones>] 55 59 56 # With the commit_on_success decorator, the transaction is only comitted if the 60 # With the transaction middleware (used here as a decorator), 61 # the transaction is only comitted if the 57 62 # function doesn't throw an exception 58 >>> committed_on_success = transaction.commit_on_success(create_a_reporter_then_fail)63 >>> committed_on_success = xact_middle(create_a_reporter_then_fail) 59 64 >>> committed_on_success("Carol", "Doe") 60 65 Traceback (most recent call last): 61 66 ... … … 66 71 [<Reporter: Alice Smith>, <Reporter: Ben Jones>] 67 72 68 73 # If there aren't any exceptions, the data will get saved 69 >>> def remove_a_reporter( ):70 ... r = Reporter.objects.get(first_name= "Alice")74 >>> def remove_a_reporter(first): 75 ... r = Reporter.objects.get(first_name=first) 71 76 ... r.delete() 72 77 ... 73 >>> remove_comitted_on_success = transaction.commit_on_success(remove_a_reporter)74 >>> remove_comitted_on_success( )78 >>> remove_comitted_on_success = xact_middle(remove_a_reporter) 79 >>> remove_comitted_on_success("Alice") 75 80 >>> Reporter.objects.all() 76 81 [<Reporter: Ben Jones>] 82 """ 83 if not getattr(settings, 'TRANSACTION_POLICY', None)=='safe': 84 __test__['API_TESTS'] += """ 85 # Note there is a trick with custom sql (in fast_select): Executing it doesn't 86 # set the transaction 'dirty', so it may not be committed 87 >>> def remove_all_reporters(ignored_request): 88 ... cursor = connection.cursor() 89 ... sql = 'delete from ' + Reporter._meta.db_table 90 ... cursor.execute(sql) 91 ... 92 >>> remove_all_no_commit = xact_middle(remove_all_reporters) 93 >>> remove_all_no_commit(None) 94 >>> Reporter.objects.all() 95 [] 77 96 78 # You can manually manage transactions if you really want to, but you 79 # have to remember to commit/rollback 80 >>> def manually_managed(): 81 ... r = Reporter(first_name="Carol", last_name="Doe") 82 ... r.save() 83 ... transaction.commit() 84 >>> manually_managed = transaction.commit_manually(manually_managed) 85 >>> manually_managed() 97 >>> transaction.rollback() 86 98 >>> Reporter.objects.all() 87 [<Reporter: Ben Jones> , <Reporter: Carol Doe>]99 [<Reporter: Ben Jones>] 88 100 89 # If you forget, you'll get bad errors 90 >>> def manually_managed_mistake(): 91 ... r = Reporter(first_name="David", last_name="Davidson") 92 ... r.save() 93 ... # oops, I forgot to commit/rollback! 94 >>> manually_managed_mistake = transaction.commit_manually(manually_managed_mistake) 95 >>> manually_managed_mistake() 96 Traceback (most recent call last): 97 ... 98 TransactionManagementError: Transaction managed block ended with pending COMMIT/ROLLBACK 101 # To do it properly, you need to set the transaction dirty 102 # when you execute raw SQL 103 # set the transaction 'dirty', so it may not be committed 104 >>> def remove_all_reporters_dirty(ignored_request): 105 ... cursor = connection.cursor() 106 ... sql = 'delete from ' + Reporter._meta.db_table 107 ... cursor.execute(sql) 108 ... transaction.set_dirty() 109 ... 110 >>> remove_all_commit = xact_middle(remove_all_reporters_dirty) 111 >>> remove_all_commit(None) 112 >>> Reporter.objects.all() 113 [] 114 115 >>> transaction.rollback() 116 >>> Reporter.objects.all() 117 [] 99 118 """ 119 else: 120 __test__['API_TESTS'] += """ 121 # Under a 'safe' transaction policy, there's no need to set_dirty 122 >>> def remove_all_reporters(ignored_request): 123 ... cursor = connection.cursor() 124 ... sql = 'delete from ' + Reporter._meta.db_table 125 ... cursor.execute(sql) 126 ... 127 >>> remove_all_safe = xact_middle(remove_all_reporters) 128 129 # See that we have a reporter: 130 >>> Reporter.objects.all() 131 [<Reporter: Ben Jones>] 132 133 >>> remove_all_safe(None) 134 135 # Now we don't, and rollback doesn't get it back 136 >>> Reporter.objects.all() 137 [] 138 >>> transaction.rollback() 139 >>> Reporter.objects.all() 140 [] 141 142 """