I am trying to save username as firstname while adding a user from django admin. Currently it saves None
in the username field as I have excluded username
in the custom model.
admin.py--
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from .models import UserProfile
from .forms import SignUpForm
class ProfileInline(admin.StackedInline):
model = UserProfile
can_delete = False
verbose_name_plural = 'Profile'
fk_name = 'user'
class CustomUserAdmin(UserAdmin):
inlines = (ProfileInline, )
list_display = ('email', 'first_name', 'last_name', 'is_staff')
list_select_related = ( 'profile', )
exclude = ('username',)
fieldsets = (
('Personal information', {'fields': ('first_name', 'last_name', 'email', 'password')}),
('Permissions', {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')}),
('Important dates', {'fields': ('last_login', 'date_joined')}),
)
add_fieldsets = (
('None', {
'classes': ('wide',),
'fields': ('first_name','last_name', 'email', 'password1', 'password2')}
),
)
def get_inline_instances(self, request, obj=None):
if not obj:
return list()
return super(CustomUserAdmin, self).get_inline_instances(request, obj)
admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)
forms.py
from django import forms
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Div, Field
from ajax_select.fields import AutoCompleteSelectField, AutoCompleteField
from phonenumber_field.formfields import PhoneNumberField
from . import models
from captcha.fields import ReCaptchaField
class SignUpForm(forms.Form):
first_name = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30)
phone_number = PhoneNumberField(label=_("Phone (Please state your country code eg. +44)"))
organisation = forms.CharField(max_length=50)
email = forms.EmailField()
password1 = forms.CharField(max_length=20)
password2 = forms.CharField(max_length=20)
captcha = ReCaptchaField(attrs={'theme' : 'clean'})
def signup(self, request, user):
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
"""
profile, created = models.UserProfile.objects.get_or_create(user=user)
profile.phone_number = self.cleaned_data['phone_number']
profile.organisation = self.cleaned_data['organisation']
profile.save()
user.save()
"""
up = user.profile
up.phone_number = self.cleaned_data['phone_number']
up.organisation = self.cleaned_data['organisation']
user.save()
up.save()
models.py --
from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
from easy_thumbnails.fields import ThumbnailerImageField
from ciasroot.settings import THUMBNAILER_SIZES, UPLOAD_PATH
from ciasroot.constants import GENDERS, LANGUAGES
from ciasroot.util import HashedPk
from phonenumber_field.modelfields import PhoneNumberField
import math, decimal, datetime, os
import uuid
def random_username(sender, instance, **kwargs):
if not instance.username:
instance.username = uuid.uuid4().hex[:30]
models.signals.pre_save.connect(random_username, sender=User)
class UserProfile(models.Model, HashedPk):
user = models.OneToOneField(User, unique=True, related_name ='profile')
job_title = models.CharField(max_length=128, blank=True, null=False, default="")
website = models.URLField(max_length=255, blank=True, null=True)
organisation = models.CharField(max_length=50, blank=True, null=True, default="")
phone_number = PhoneNumberField( blank=True, null=True)
def __str__(self):
return self.user.get_full_name()
def save(self, *args, **kwargs):
super(UserProfile, self).save(*args, **kwargs)
LookupSuggest.add("job_title", self.job_title)
How can I insert username as firstname and make the custom field ie email 'required'. Now the password1 & password2 fields are mandatory.
Any help/link is highly appreciated.
To automatically populate username with the user's first name, you should use a signal - add the following to the models.py
where you've defined UserProfile:
def set_username(sender, instance, **kwargs):
if not instance.username:
instance.username = instance.first_name
models.signals.pre_save.connect(set_username, sender=User)
The problem with this is that if you have two users with the same first name, the username won't be unique, so you'll get an integrity error from the database. You could check for uniqueness and append a number until you get a unique value:
def set_username(sender, instance, **kwargs):
if not instance.username:
username = instance.first_name
counter = 1
while User.objects.filter(username=username):
username = instance.first_name + str(counter)
counter += 1
instance.username = username
models.signals.pre_save.connect(set_username, sender=User)
Or, if you're not using the username at all, you could just set it to a random unique value using uuid:
import uuid
def random_username(sender, instance, **kwargs):
if not instance.username:
instance.username = uuid.uuid4().hex[:30]
models.signals.pre_save.connect(random_username, sender=User)
If you plan on using emails for login rather than username, you'll also need to enforce email uniqueness, add the email to the admin user creation form - this should do what you need: https://gist.github.com/gregplaysguitar/1184995
You can define username as a readonly field.
def user_first_name(obj):
return obj.first_name
user_firstname.short_description = 'Firstname'
class CustomUserAdmin(UserAdmin):
readonly_fields = ('user_firstname')
inlines = (ProfileInline, )
list_display = ('email', 'user_first_name', 'last_name', 'is_staff')
list_select_related = ( 'profile', )
exclude = ('username',)
...
For your second question about validating email, define a form for CustomUserAdmin
.
class CustomUserAdmin(UserAdmin):
...
form = CustomUserAdminForm
class CustomUserAdminForm(forms.ModelForm):
def clean_email(self):
if not self.cleaned_data['email']:
raise forms.ValidationError("Email is required")
return self.cleaned_data['email']
Or:
class CustomUserAdminForm(forms.ModelForm):
email = forms.EmailField(required=True)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With