@@ -138,24 +138,30 @@ def teardown_database() -> None:
138138 request .addfinalizer (teardown_database )
139139
140140
141- def _django_db_fixture_helper (
141+ @pytest .fixture ()
142+ def _django_db_helper (
142143 request ,
144+ django_db_setup : None ,
143145 django_db_blocker ,
144- transactional : bool = False ,
145- reset_sequences : bool = False ,
146146) -> None :
147147 from django import VERSION
148148
149149 if is_django_unittest (request ):
150150 return
151151
152- if not transactional and "live_server" in request .fixturenames :
153- # Do nothing, we get called with transactional=True, too.
154- return
152+ marker = request .node .get_closest_marker ("django_db" )
153+ if marker :
154+ transactional , reset_sequences , _databases = validate_django_db (marker )
155+ else :
156+ transactional , reset_sequences , _databases = False , False , None
155157
156- _databases = getattr (
157- request .node , "_pytest_django_databases" , None ,
158- ) # type: Optional[_DjangoDbDatabases]
158+ transactional = transactional or (
159+ "transactional_db" in request .fixturenames
160+ or "live_server" in request .fixturenames
161+ )
162+ reset_sequences = reset_sequences or (
163+ "django_db_reset_sequences" in request .fixturenames
164+ )
159165
160166 django_db_blocker .unblock ()
161167 request .addfinalizer (django_db_blocker .restore )
@@ -186,6 +192,26 @@ class PytestDjangoTestCase(test_case_class): # type: ignore[misc,valid-type]
186192 request .addfinalizer (test_case ._post_teardown )
187193
188194
195+ def validate_django_db (marker ) -> "_DjangoDb" :
196+ """Validate the django_db marker.
197+
198+ It checks the signature and creates the ``transaction``,
199+ ``reset_sequences`` and ``databases`` attributes on the marker
200+ which will have the correct values.
201+
202+ A sequence reset is only allowed when combined with a transaction.
203+ """
204+
205+ def apifun (
206+ transaction : bool = False ,
207+ reset_sequences : bool = False ,
208+ databases : "_DjangoDbDatabases" = None ,
209+ ) -> "_DjangoDb" :
210+ return transaction , reset_sequences , databases
211+
212+ return apifun (* marker .args , ** marker .kwargs )
213+
214+
189215def _disable_migrations () -> None :
190216 from django .conf import settings
191217 from django .core .management .commands import migrate
@@ -229,41 +255,24 @@ def _set_suffix_to_test_databases(suffix: str) -> None:
229255
230256
231257@pytest .fixture (scope = "function" )
232- def db (
233- request ,
234- django_db_setup : None ,
235- django_db_blocker ,
236- ) -> None :
258+ def db (_django_db_helper : None ) -> None :
237259 """Require a django test database.
238260
239261 This database will be setup with the default fixtures and will have
240262 the transaction management disabled. At the end of the test the outer
241263 transaction that wraps the test itself will be rolled back to undo any
242264 changes to the database (in case the backend supports transactions).
243- This is more limited than the ``transactional_db`` resource but
265+ This is more limited than the ``transactional_db`` fixture but
244266 faster.
245267
246- If multiple database fixtures are requested, they take precedence
247- over each other in the following order (the last one wins): ``db``,
248- ``transactional_db``, ``django_db_reset_sequences``.
268+ If both ``db`` and ``transactional_db`` are requested,
269+ ``transactional_db`` takes precedence.
249270 """
250- if "django_db_reset_sequences" in request .fixturenames :
251- request .getfixturevalue ("django_db_reset_sequences" )
252- if (
253- "transactional_db" in request .fixturenames
254- or "live_server" in request .fixturenames
255- ):
256- request .getfixturevalue ("transactional_db" )
257- else :
258- _django_db_fixture_helper (request , django_db_blocker , transactional = False )
271+ # The `_django_db_helper` fixture checks if `db` is requested.
259272
260273
261274@pytest .fixture (scope = "function" )
262- def transactional_db (
263- request ,
264- django_db_setup : None ,
265- django_db_blocker ,
266- ) -> None :
275+ def transactional_db (_django_db_helper : None ) -> None :
267276 """Require a django test database with transaction support.
268277
269278 This will re-initialise the django database for each test and is
@@ -272,35 +281,26 @@ def transactional_db(
272281 If you want to use the database with transactions you must request
273282 this resource.
274283
275- If multiple database fixtures are requested, they take precedence
276- over each other in the following order (the last one wins): ``db``,
277- ``transactional_db``, ``django_db_reset_sequences``.
284+ If both ``db`` and ``transactional_db`` are requested,
285+ ``transactional_db`` takes precedence.
278286 """
279- if "django_db_reset_sequences" in request .fixturenames :
280- request .getfixturevalue ("django_db_reset_sequences" )
281- _django_db_fixture_helper (request , django_db_blocker , transactional = True )
287+ # The `_django_db_helper` fixture checks if `transactional_db` is requested.
282288
283289
284290@pytest .fixture (scope = "function" )
285291def django_db_reset_sequences (
286- request ,
287- django_db_setup : None ,
288- django_db_blocker ,
292+ _django_db_helper : None ,
293+ transactional_db : None ,
289294) -> None :
290295 """Require a transactional test database with sequence reset support.
291296
292- This behaves like the ``transactional_db`` fixture, with the addition
293- of enforcing a reset of all auto increment sequences. If the enquiring
297+ This requests the ``transactional_db`` fixture, and additionally
298+ enforces a reset of all auto increment sequences. If the enquiring
294299 test relies on such values (e.g. ids as primary keys), you should
295300 request this resource to ensure they are consistent across tests.
296-
297- If multiple database fixtures are requested, they take precedence
298- over each other in the following order (the last one wins): ``db``,
299- ``transactional_db``, ``django_db_reset_sequences``.
300301 """
301- _django_db_fixture_helper (
302- request , django_db_blocker , transactional = True , reset_sequences = True
303- )
302+ # The `_django_db_helper` fixture checks if `django_db_reset_sequences`
303+ # is requested.
304304
305305
306306@pytest .fixture ()
0 commit comments