How to add fields to Django User model and show it on registration form with django-registration?

会有一股神秘感。 提交于 2019-12-11 18:20:07

问题


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 MyRegistrationFormform:

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 Forms, 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!