如何正确使用Django的ATOMIC_REQUESTS?配置后未生效问题求助
Hey there, let's figure out why your transaction isn't rolling back and get you sorted with ATOMIC_REQUESTS in Django 1.11!
1. The Critical Typo in Your Database Config
First off, you've got a small but fatal spelling mistake in your settings. The correct parameter name is ATOMIC_REQUESTS (plural, with an extra S), not ATOMIC_REQUEST. Django doesn't recognize the singular version, so it's not enabling the automatic per-request transaction behavior you're expecting.
Here's the corrected database config:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'HOST': '127.0.0.1', 'NAME': 'kma_dev', 'USER': 'root', 'PASSWORD': 'root', 'ATOMIC_REQUESTS': True, # Fixed plural form } }
2. How ATOMIC_REQUESTS Works
When ATOMIC_REQUESTS is set to True, Django does two key things for every HTTP request:
- Automatically starts a database transaction at the beginning of the request.
- If your view returns a successful response (status codes 200–399), it commits the transaction. If your view raises any uncaught exception (like your
ValueError), it rolls back the entire transaction—undoing all database changes made during the request.
A couple important notes for Django 1.11:
- This applies to all database operations in the request, including those in models, forms, or utility functions called by the view.
- It relies on your MySQL tables using a transactional storage engine. InnoDB is required (MyISAM doesn't support transactions, so rollbacks won't work). MySQL 5.7 uses InnoDB by default, but it's worth verifying your
storetable's engine just in case. - Nested transactions (using
transaction.atomic()inside the view) work with savepoints—rolling back a nested atomic block won't affect the outer request transaction unless you explicitly raise an exception that propagates up.
3. Correct Usage & Troubleshooting Tips
Once you fix the typo, here's how to ensure it works as expected:
- Confirm your table engine: Run this MySQL command to check your
storetable:
Look for theSHOW TABLE STATUS LIKE 'store';Enginecolumn—it should sayInnoDB. If not, alter the table to switch engines:ALTER TABLE store ENGINE=InnoDB; - Don't catch exceptions silently: If you wrap your
raise ValueErrorin atry/exceptblock that doesn't re-raise the exception, Django will think the request succeeded and commit the transaction. Your test code's uncaughtValueErroris exactly what should trigger a rollback. - Check middleware order: Ensure
django.middleware.transaction.TransactionMiddlewareis in yourMIDDLEWAREsetting (it's included by default in Django 1.11). It should come after any middleware that modifies the request/response but before view-specific middleware.
4. Test the Fix
After updating your settings, restart your Django server and test the view again:
- Note the original
namevalue of your firstStoreobject. - Hit the view's GET endpoint (which triggers the
save()and then raisesValueError). - Check the
Storeobject'sname—it should be unchanged, since the transaction was rolled back.
内容的提问来源于stack exchange,提问作者yuqi liu

