The least painful and indeed Django-recommended way of doing this is through a OneToOneField(User)
property.
…
If you wish to store information related to User
, you can use a one-to-one relationship to a model containing the fields for additional information. This one-to-one model is often called a profile model, as it might store non-auth related information about a site user.
That said, extending django.contrib.auth.models.User
and supplanting it also works...
Some kinds of projects may have authentication requirements for which Django’s built-in User
model is not always appropriate. For instance, on some sites it makes more sense to use an email address as your identification token instead of a username.
[Ed: Two warnings and a notification follow, mentioning that this is pretty drastic.]
I would definitely stay away from changing the actual User class in your Django source tree and/or copying and altering the auth module.
On Python ≥ 3.5, use pathlib.Path.mkdir
:
from pathlib import Path
Path("/my/directory").mkdir(parents=True, exist_ok=True)
For older versions of Python, I see two answers with good qualities, each with a small flaw, so I will give my take on it:
Try os.path.exists
, and consider os.makedirs
for the creation.
import os
if not os.path.exists(directory):
os.makedirs(directory)
As noted in comments and elsewhere, there's a race condition – if the directory is created between the os.path.exists
and the os.makedirs
calls, the os.makedirs
will fail with an OSError
. Unfortunately, blanket-catching OSError
and continuing is not foolproof, as it will ignore a failure to create the directory due to other factors, such as insufficient permissions, full disk, etc.
One option would be to trap the OSError
and examine the embedded error code (see Is there a cross-platform way of getting information from Python’s OSError):
import os, errno
try:
os.makedirs(directory)
except OSError as e:
if e.errno != errno.EEXIST:
raise
Alternatively, there could be a second os.path.exists
, but suppose another created the directory after the first check, then removed it before the second one – we could still be fooled.
Depending on the application, the danger of concurrent operations may be more or less than the danger posed by other factors such as file permissions. The developer would have to know more about the particular application being developed and its expected environment before choosing an implementation.
Modern versions of Python improve this code quite a bit, both by exposing FileExistsError
(in 3.3+)...
try:
os.makedirs("path/to/directory")
except FileExistsError:
# directory already exists
pass
...and by allowing a keyword argument to os.makedirs
called exist_ok
(in 3.2+).
os.makedirs("path/to/directory", exist_ok=True) # succeeds even if directory exists.
Best Answer
You can put your tests in a
tests/
subdirectory of the app (rather than atests.py
file), and include atests/models.py
with the test-only models.Then provide a test-running script (example) that includes your
tests/
"app" inINSTALLED_APPS
. (This doesn't work when running app tests from a real project, which won't have the tests app inINSTALLED_APPS
, but I rarely find it useful to run reusable app tests from a project, and Django 1.6+ doesn't by default.)(NOTE: The alternative dynamic method described below only works in Django 1.1+ if your test case subclasses
TransactionTestCase
- which slows down your tests significantly - and no longer works at all in Django 1.7+. It's left here only for historical interest; don't use it.)At the beginning of your tests (i.e. in a setUp method, or at the beginning of a set of doctests), you can dynamically add
"myapp.tests"
to the INSTALLED_APPS setting, and then do this:Then at the end of your tests, you should clean up by restoring the old version of INSTALLED_APPS and clearing the app cache again.
This class encapsulates the pattern so it doesn't clutter up your test code quite as much.