How to customize User Model in Django1.5+?

Hi Friends,

Django1.5+ version supports Customized User Model. This is the wonderful feature in Django Auth Framework(for more see release notes).

I am giving you very straight codes which I have implemented in my project.

In models.py

The below code is used for extending default Django User Model.

from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone

# From project
from utils import gv

class MyUser(AbstractUser):
    # Contact
    mobile_number = models.CharField(max_length=13, verbose_name=_('Phone'), help_text=_('Enter a valid mobile number with country code (Example: {0})'.format(gv.DUMMY_MOBILE_NUMBER)))
    photo = models.ImageField(upload_to='img-data/userphoto', default='img-data/userphoto/no_profilephoto.png', blank=True)
    gender = models.CharField(max_length=140, choices=gv.GENDER_CHOICES, blank=True)
    dob = models.DateField(blank=True, null=True)
    marital_status = models.CharField(max_length=140, default='', choices=gv.MARITAL_STATUS_CHOICES, blank=True)
    contact_address_line1 = models.CharField(max_length=140, blank=True)
    contact_address_line2 = models.CharField(max_length=140, blank=True)
    contact_address_line3 = models.CharField(max_length=140, blank=True)
    city = models.CharField(max_length=140, blank=True)
    country = models.ForeignKey(Country)
    state = models.CharField(max_length=140, blank=True)
    zipcode = models.IntegerField(default=0)
    latitude = models.FloatField(default=0.0)
    longitude = models.FloatField(default=0.0)

    # Professional
    education = models.CharField(max_length=140, blank=True, help_text=_("Your educational qualification (Example: B.E.)"))
    occupation = models.CharField(max_length=140, blank=True, help_text=_("Your occupation (Example: Engineer)"))
    industry = models.CharField(max_length=140, blank=True, help_text=_("Your industry name (Example: Software)"))
    company_name = models.CharField(max_length=140, blank=True, help_text=_("Your company name (Example: Xmos)"))
    job_title = models.CharField(max_length=140, blank=True, help_text=_("Your job title (Example: Application Developer)"))

    # Social
    fb_uid = models.CharField(max_length=20, blank=True)
    fb_access_token = models.CharField(max_length=255, blank=True, editable=False)
    tw_access_token = models.CharField(max_length=255, blank=True, editable=False)

    # Others
    firsttime_login = models.BooleanField(default=True)
    modified = models.DateTimeField(default=timezone.now, auto_now=True)

In admin.py

The below code is used for control all admin related user interactions in Django site admin.

from django import forms
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from django.utils.translation import ugettext, ugettext_lazy as _

from models import MyUser, Country

class UserCreationForm(forms.ModelForm):
    """
    A form that creates a user, with no privileges, from the given username and
    password.
    """
    error_messages = {
        'duplicate_username': _("A user with that username already exists."),
        'password_mismatch': _("The two password fields didn't match."),
    }
    username = forms.RegexField(label=_("Username"), max_length=30,
        regex=r'^[\w.@+-]+$',
        help_text=_("Required. 30 characters or fewer. Letters, digits and "
                      "@/./+/-/_ only."),
        error_messages={
            'invalid': _("This value may contain only letters, numbers and "
                         "@/./+/-/_ characters.")})
    password1 = forms.CharField(label=_("Password"),
        widget=forms.PasswordInput)
    password2 = forms.CharField(label=_("Password confirmation"),
        widget=forms.PasswordInput,
        help_text=_("Enter the same password as above, for verification."))

    class Meta:
        model = MyUser
        fields = ("username","country")

    def clean_username(self):
        # Since User.username is unique, this check is redundant,
        # but it sets a nicer error message than the ORM. See #13147.
        username = self.cleaned_data["username"]
        try:
            MyUser._default_manager.get(username=username)
        except MyUser.DoesNotExist:
            return username
        raise forms.ValidationError(self.error_messages['duplicate_username'])

    def clean_password2(self):
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError(
                self.error_messages['password_mismatch'])
        return password2

    def save(self, commit=True):
        user = super(UserCreationForm, self).save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user

class UserChangeForm(forms.ModelForm):
    username = forms.RegexField(
        label=_("Username"), max_length=30, regex=r"^[\w.@+-]+$",
        help_text=_("Required. 30 characters or fewer. Letters, digits and "
                      "@/./+/-/_ only."),
        error_messages={
            'invalid': _("This value may contain only letters, numbers and "
                         "@/./+/-/_ characters.")})
    password = ReadOnlyPasswordHashField(label=_("Password"),
        help_text=_("Raw passwords are not stored, so there is no way to see "
                    "this user's password, but you can change the password "
                    "using <a href=\"password/\">this form</a>."))

    class Meta:
        model = MyUser

    def __init__(self, *args, **kwargs):
        super(UserChangeForm, self).__init__(*args, **kwargs)
        f = self.fields.get('user_permissions', None)
        if f is not None:
            f.queryset = f.queryset.select_related('content_type')

    def clean_password(self):
        # Regardless of what the user provides, return the initial value.
        # This is done here, rather than on the field, because the
        # field does not have access to the initial value
        return self.initial["password"]

class MyUserAdmin(UserAdmin):
    fieldsets = (
        (None, {'fields': ('username', 'password')}),
        (_('Personal info'), {'fields': ('photo', 'first_name', 'last_name', 'email', 'dob', 'gender', 'marital_status')}),
        (_('Contact info'), {'fields': ('contact_address_line1', 'contact_address_line2', 'contact_address_line3', 'city', 'country', 'state', 'zipcode', 'latitude', 'longitude', 'mobile_number')}),
        (_('Professional info'), {'fields': ('education', 'occupation', 'industry', 'company_name', 'job_title')}),
        (_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')}),
        (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
    )

    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('username', 'password1', 'password2', 'country')}
        ),
    )
    # The forms to add and change user instances
    form = UserChangeForm
    add_form = UserCreationForm

# Now register the new UserAdmin...
admin.site.register(MyUser, MyUserAdmin)

Finally, specify the custom model as the default user model for your project using the AUTH_USER_MODEL setting in your settings.py:

AUTH_USER_MODEL = 'yourapp.MyUser'


Django-Python Web based application developer.

Share This Post

Related Articles

Leave a Reply

© 2017 Techy Diary. All rights reserved.
Powered by Charvi Groups