问题
I noticed that the User model that Django provides does not have a Date of Birth Field
.
I do not want to write my own custom User class
just to include this attribute
. I am wondering if it is possible in some way to "attach" date of birth
to the User model
. If not what are the other simple options to make this work. I am also ok to save the contents of User Model
to a profile model
with additional date of birth
information.
But would my form
has to save both User and profile model
which I am confused as how this work.
EDIT 2: (After implementing frnhr's solution):
Two issues: No activation email
is sent out in the development server
. I tried default User model
with django-registration
and I see activation email
being sent out. but now, with the custom user model
, no activation email
is sent out.
when I login
as admin
, http://127.0.0.1:8000/admin/
, I see no User model
but only registration profiles
and Groups
. when I click registration profiles
, it does not show all the information about User
, but just username
and activation key
which is shown as already expired. Attached is a screenshot
. how to fix this?


回答1:
In newer versions of Django, making your own custom User model is quite painless. See this answer for details: https://stackoverflow.com/a/16125609/236195
You might run into problems if you are using some older third-party apps which have model relationships hardcoded to auth.models.User
. Most of third-party apps which have ongoing development have probably switched already or will do so soon.
Edit - getting it to work with django-registration
myapp/models.py:
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.utils.translation import ugettext_lazy as _
class CustomUser(AbstractUser):
age = models.PositiveIntegerField(_("age"), null=True) # this field is added to default User model
settings.py:
INSTALLED_APPS = (
# ...
'registration_defaults',
'registration',
'myapp',
)
# ...
AUTH_USER_MODEL = "myapp.CustomUser"
ACCOUNT_ACTIVATION_DAYS = 2 # or something
urls.py (add this line):
url(r'^accounts/', include('registration.backends.default.urls')),
myapp/admin.py (optionally):
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.utils.translation import ugettext_lazy as _
from .models import CustomUser
class CustomUserAdmin(UserAdmin):
fieldsets = (
(None, {'fields': ('username', 'password')}),
(_('Personal info'), {'fields': ('first_name', 'last_name', 'email', 'age')}), # added "age" field
(_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser',
'groups', 'user_permissions')}),
(_('Important dates'), {'fields': ('last_login', 'date_joined')}),
)
admin.site.register(CustomUser, CustomUserAdmin)
django-registration
Get it from here: https://bitbucket.org/fhrzenjak/django-registration and put it in your project folder.
Disclaimer: this is my fork of the original django-registration repo, with applied patch for custom user models by mrginglymus: https://bitbucket.org/ubernostrum/django-registration/pull-request/30/django-15-compatibility-with-custom-user/diff
Django-registration-defaults is a collection of default templates from here: https://github.com/yourcelf/django-registration-defaults It's pip-installable
EDIT 2 - accept a custom field on registration
Well, this is a separate question, but ok here is how...
Create a MyRegistrationForm
form:
from registration.forms import RegistrationForm
class MyRegistrationForm(RegistrationForm):
age = forms.CharField(required=False)
In your urls.py add a line before django-registration include
. That will override whatever is in the include:
url(r'^accounts/register/$',
RegistrationView.as_view(form_class=MyRegistrationForm),
name='registration_register',
),
url(r'^accounts/', include('registration.backends.default.urls')),
Modify your custom user model to respond on user_registered
signal and save the additional data:
class CustomUser(AbstractUser):
age = models.PositiveIntegerField(_("age"), null=True)
@classmethod
def user_created(cls, sender, user, request, **kwargs):
from myapp.forms import MyRegistrationForm
form = MyRegistrationForm(request.POST)
user.age = form.data.get('age', None)
user.save()
pass
from registration.signals import user_registered
user_registered.connect(CustomUser.user_created)
回答2:
Your best bet is probably to go ahead and create a custom User model (you can subclass django.contrib.auth.models.AbstractUser
and add whatever fields you want).
Regarding processing multiple models in single form, it's actually quite easy. You actually want to use multiple Form
s, but render them both in the same <form>
element, and process them separately in the view.
Another approach is just to create a single Form
(probably not a ModelForm
), which contains all of the fields you want. Then, write a save
method on your form, which creates/updates the relevant models. This makes your view and template code simpler than the approach above.
As an example, here is a form class that lets an existing user change their email address and date of birth. Note that you pass the logged in User
from your view when calling save()
:
class UserEditForm(forms.Form):
email = forms.EmailField()
date_of_birth = forms.DateField()
def save(self, user):
user.email = self.cleaned_data['email']
user.save()
user.userprofile.date_of_birth = self.cleaned_data['date_of_birth']
user.userprofile.save()
Note this assumes you have a UserProfile
model, which has a one-to-one field to User
.
来源:https://stackoverflow.com/questions/22565964/how-to-add-fields-to-django-user-model-and-show-it-on-registration-form-with-dja