Exclude certain fields for the users who are superusers - python

I'm trying to make a custom User Model and have parameters like Date of Birth, current level and other such parameters. When I run python manage.py createsuperuser, it gives an error saying these values cannot be null. I don't want these parameters for the superuser account. WHat do I do?
I tried adding the following line to the class that inherits from the UserAdmin class
exclude = ('date_of_birth', 'currentLevel', 'totalStars', 'badges')
This is the model fields
class Learner(AbstractBaseUser):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
email = models.EmailField(max_length=255, unique=True)
date_of_birth = models.DateField(auto_now=False, auto_now_add=False)
currentLevel = models.ForeignKey(SubLevelConcepts, related_name='currentLevel', on_delete=models.CASCADE)
totalStars = models.IntegerField(default=0)
badges = models.IntegerField(default=0)
active = models.BooleanField(default=True)
staff = models.BooleanField(default=False)
superuser = models.BooleanField(default=False)
objects = LearnerManager()
This is the admin class
class LearnerAdmin(UserAdmin):
add_form = LearnerCreationForm
form = LearnerChangeForm
model = Learner
exclude = ('date_of_birth', 'currentLevel', 'totalStars', 'badges')
list_display = (
'first_name',
'last_name',
'email',
'staff',
'active'
)
list_filter = (
'email',
'active'
)
fieldsets = (
(None, {'fields': ('email', 'password',)}),
('Permissions', {'fields': ('staff', 'active')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'first_name', 'last_name','password1', 'passsword2', 'staff', 'active')}
)
)
search_fields = ('email',)
ordering = ('id',)
filter_horizontal = ()
This is the final error when i run python manage.py createsuperuser
django.db.utils.IntegrityError: (1048, "Column 'currentLevel_id' cannot be null")
I want the superuser to just take email and password and finish the job. I'll add the first_name and last_name later

Add null=True and default=None to your ForeignKey field so it's not required, ie
class Learner(AbstractBaseUser):
# ...
currentLevel = models.ForeignKey(SubLevelConcepts, null=True, related_name='currentLevel', on_delete=models.CASCADE)
You may also want to use either models.PROTECT or models.SET_NULL instead of models.CASCADE - unless you really want your users accounts to be deleted when their matching SubLevelConcept is deleted, that is...
And you may also want to check the blank=True models field option FWIW.

Related

Django create user profile

I created a user profile model for my system. I created all models and it works perfectly. I have a form, and the form works too. But when I look user create form from admin page, it doesn't look the same.
There are some missing parts like rank, comp_name. How can I fix it?
models.py
class UserProfile(models.Model):
ranks = (
('xxx', 'xxx'),
...
)
comp_name = models.CharField(max_length=200, default="Choose")
user_id = models.UUIDField(default=uuid.uuid4(), editable=False, unique=True)
username = models.CharField(max_length=500)
first_name = models.CharField(max_length=200, default=None)
last_name = models.CharField(max_length=200, default=None)
password = models.CharField(max_length=50)
email = models.EmailField(max_length=254)
rank = models.CharField(max_length=200, choices=ranks)
forms.py
class SignUpForm(UserCreationForm):
comp_name = forms.CharField(label='What is your company name?')
email = forms.CharField(max_length=254)
rank = forms.ChoiceField(label='What is your rank?', choices=UserProfile.ranks)
first_name = forms.CharField(max_length=250)
last_name = forms.CharField(max_length=250)
comp_name = forms.ModelChoiceField(queryset=CompanyProfile.objects.all())
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email', 'comp_name', 'password1', 'password2', 'rank'
admin
admin panel "Change User" screen
In forms.py
class SignUpForm(UserCreationForm):
comp_name = forms.CharField(label='What is your company name?')
email = forms.CharField(max_length=254)
rank = forms.ChoiceField(label='What is your rank?', choices=UserProfile.ranks)
first_name = forms.CharField(max_length=250)
last_name = forms.CharField(max_length=250)
comp_name = forms.ModelChoiceField(queryset=CompanyProfile.objects.all())
class Meta:
model = User --> change to UserProfile
fields = ('username', 'first_name', 'last_name', 'email', 'comp_name', 'password1', 'password2', 'rank'

Python - Add custom user models in Django admin not working

I'm working on a project using Python(3.7) and Django(2.2) in which I have implemented my models for multiple user types with custom user model as the base model. Everything working fine except the admin side, I have register these modles to admin but when I try to add an object from admin interface it's giving an error.
Here's what I have tried so far:
From models.py:
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=254, unique=True)
title = models.CharField(max_length=255, blank=False)
user_type = models.CharField(max_length=255, choices=USER_TYPE, blank=False)
gender = models.CharField(max_length=255, choices=CHOICES, blank=False)
contenst = models.CharField(max_length=255, blank=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
last_login = models.DateTimeField(null=True, blank=True)
date_joined = models.DateTimeField(auto_now_add=True)
USERNAME_FIELD = 'email'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = ['password']
objects = UserManager()
def get_absolute_url(self):
return "/users/%i/" % (self.pk)
class PersonalBelow18(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
dob = models.DateField(blank=False)
customer_id = models.BigIntegerField(blank=False)
collection_use_personal_data = models.BooleanField(blank=False)
reference_identities = models.ForeignKey(Identities, blank=False, on_delete=models.CASCADE, related_name='refs')
def __str__(self):
return self.user.email+'\'s account with ' + str(self.customer_id)
class PersonalAbove18(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
dob = models.DateField(blank=False)
customer_id = models.BigIntegerField(blank=False)
contact_email = models.EmailField(blank=False)
reference_identities = models.ForeignKey(Identities, blank=False, on_delete=models.CASCADE)
contact_no = PhoneNumberField(blank=True, help_text='Phone number must be entered in the'
'format: \'+999999999\'. Up to 15 digits allowed.')
collection_use_personal_data = models.BooleanField(blank=False)
def __str__(self):
return self.user.email+'\'s account with ' + str(self.customer_id)
class Parent(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
contact_email = models.EmailField(blank=False)
customer_id = models.BigIntegerField(blank=True)
contact_no = PhoneNumberField(blank=True, help_text='Phone number must be entered in the'
'format: \'+999999999\'. Up to 15 digits allowed.')
collection_use_personal_data = models.BooleanField(blank=False)
class GroupContactPerson(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
contact_email = models.EmailField(blank=False)
customer_id = models.BigIntegerField(blank=False)
contact_no = PhoneNumberField(blank=True, help_text='Phone number must be entered in the'
'format: \'+999999999\'. Up to 15 digits allowed.')
department = models.CharField(max_length=255, blank=False)
address = models.TextField(max_length=255, blank=False)
and here's how I register these models to admin:
From admin.py:
class UserAdmin(BaseUserAdmin):
fieldsets = (
(None, {'fields': ('email', 'password', 'title', 'user_type',
'gender', 'contenst', 'last_login')}),
('Permissions', {'fields': (
'is_active',
'is_staff',
'is_superuser',
'groups',
'user_permissions',
)}),
)
add_fieldsets = (
(
None,
{
'classes': ('wide',),
'fields': ('email', 'password1', 'password2')
}
),
)
list_display = ('email', 'title', 'is_staff', 'last_login')
list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups')
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ('groups', 'user_permissions',)
admin.site.register(User, UserAdmin)
admin.site.register(PersonalBelow18)
admin.site.register(PersonalAbove18)
admin.site.register(Parent)
admin.site.register(GroupContactPerson)
The Parent and GroupContactPerson models are working well on admin side but the when I try to add an object for PersonalBelow18 & PersonalAbove18 models, it gives the following error as:
TypeError: str returned non-string (type int)
Here's how I debug this problem in these models:
I start removing all fields one-by-one
Remove a field from model & form and perform migrations
Then test the admin
Then I found that when I removed the reference_identities field it start working, so I get that this model was returning an integer, so I fixed that model and it fix the issue.
In short, it's a good approach to find a path to the actual place of problem by removing fields one-by-one and test the admin.

Django create CustomUser model

Folks,
I'm trying to create my own User model by extending the AbstractBaseUser model provided by Django.
However, I keep on getting the following error when migrating:
ValueError: The field admin.LogEntry.user was declared with a lazy reference to '<app_name>.user', but app '<app_name>' doesn't provide model 'user'.
What I have done so far is the following:
In app/models.py added CustomUser class together with CustomUserManager with relevant fields and all.
In app/admin.py I've added this:
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from <app_name>.models import CustomUser
class CustomUserChangeForm(UserChangeForm):
class Meta:
model = get_user_model()
fields = ('email',)
class CustomUserCreationForm(UserCreationForm):
class Meta:
model = get_user_model()
fields = ('email',)
def clean_username(self):
username = self.cleaned_data["username"]
try:
get_user_model().objects.get(username=username)
except get_user_model().DoesNotExist:
return username
raise forms.ValidationError(self.error_messages['duplicate_username'])
class CustomUserAdmin(UserAdmin):
form = CustomUserChangeForm
add_form = CustomUserCreationForm
fieldsets = (
(None, {'fields': [('username', 'password'),]}),
(('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
(('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser',
'groups', 'user_permissions')}),
(('Important dates'), {'fields': ('last_login', 'date_joined')}),
)
admin.site.register(CustomUser, CustomUserAdmin)
Apart from that there is this added to seetings.py
AUTH_USER_MODEL = '<app_name>.CustomUser'
Everything that I found so far suggests that the above given code should make this work, but it doesn't. I spent like 4-5 hours already and I still can't get my head around it. Someone please help
Create your User model like so:
from django.core import validators
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.models import UserManager
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(_('username'), max_length=75, unique=True,
help_text=_('Required. 30 characters or fewer. Letters, numbers and '
'underscores characters'),
validators=[
validators.RegexValidator(re.compile('^[\w]+$'),
_('Enter a valid username.'), 'invalid')
])
first_name = models.CharField(_('first name'), max_length=254, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
email = models.EmailField(_('email address'), max_length = 254, unique = True, null = True)
is_staff = models.BooleanField(_('staff status'), default=False,
help_text=_('Designates whether the user can log into this admin '
'site.'))
is_active = models.BooleanField(_('active'), default=True,
help_text=_('Designates whether this user should be treated as '
'active. Unselect this instead of deleting accounts.'))
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
objects = UserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['first_name']
def get_full_name(self):
return self.name
def get_short_name(self):
return self.username
Don't forget to add your custom fields!
Use a custom admin like so:
#admin.register(models.User)
class CustomUserAdmin(UserAdmin):
list_display = ('name', 'username', 'is_staff', )
list_filter = ('is_staff', )
search_fields = ('first_name', 'last_name', 'username', )
readonly_fields = ('date_joined', 'last_login', )
fieldsets = (
(None, {
'fields': ('username', 'password')
}),
("Personal Information", {
'fields': ('first_name', 'last_name', 'email')
}),
("Permissions", {
'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')
}),
("Important Dates", {
'fields': ('last_login', 'date_joined')
}),
)
Then finally add it to your settings:
AUTH_USER_MODEL = '<app_name>.User'
A working demonstration can be found in my GitHub repository.

django admin: adding a new object as a foriegn key child in admin interface

I have a custom user object GameUser, a profile UserInfo that attaches to each user with information, and a Weapon model that each profile gets associated to, but can only have one at a time.
I want to be able to look up and existing GameUser in my admin interface and, in the change form, have the option to create an associate a new Weapon to that UserInfo profile.
Here's my models:
class GameUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField()
# ...etc
class UserInfo(models.Model):
first = models.CharField(max_length=30)
last = models.CharField(max_length=30)
# ...etc
# relations
user = models.OneToOneField(GameUser)
weapon = models.ForeignKey('Weapon', null=True)
class Weapon(models.Model):
name = models.CharField(max_length=20)
# ...etc
And my admin.py:
class GameUserChangeForm(forms.ModelForm):
password = ReadOnlyPasswordHashField()
class Meta:
model = GameUser
fields = ('email', 'password')
def clean_password(self):
return self.initial["password"]
class GameUserAdmin(UserAdmin):
form = GameUserChangeForm
list_display = ('email', 'is_admin')
list_filter = ('is_admin',)
fieldsets = (
(None, {'fields': ('email', 'password')}),
('Permissions', {'fields': ('is_admin',)}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2')}
),
)
search_fields = ('email',)
ordering = ('email',)
filter_horizontal = ()
class UserInfoAdmin(admin.ModelAdmin):
fieldsets = [
('Personal Information', {'fields': [
'first', 'last']
}),
# ... etc
]
list_display = ('first', 'last')
search_fields = ['city', 'state']
admin.site.register(UserInfo, UserInfoAdmin)
admin.site.register(GameUser, GameUserAdmin)
If there is a Weapon associated with that GameInfo, I'd like to display it there inline. If not, I'd like to be able to create a new Weapon object for that GameInfo and set its fields.
I should mention I'm not married to Weapon being a ForiegnKey - it could certainly be a OneToOneField as well if that makes it easier.
What is the right way for me to do this in Django?

how to change the order of the fields?

please help change the order of the form fields on the screen.
I created the following model:
class UserProfile(User):
status = models.CharField(
max_length=30,
blank=True,
)
address = models.EmailField(
max_length=50,
blank=True,
)
objects = UserManager()
then combined field of this model built with fields of the registration form:
class MyRegistrationForm(UserCreationForm):
username = forms.CharField(
label='username',
help_text='',
required=True,
)
password1 = forms.CharField(
label='pass1',
help_text='',
required=True,
)
password2 = forms.CharField(
label='pass2',
help_text='',
required=True,
)
class Meta:
model = UserProfile
fields = ('status', 'address')
as a result the user sees on the display field in this order:
status, address, username, pass1, pass2
but I need the user to see the screen fields in the following order:
username, address, pass1, pass2, status
According to the documentation:
The generated Form class will have a form field for every model field
specified, in the order specified in the fields attribute.
class MyRegistrationForm(UserCreationForm):
...
class Meta:
model = UserProfile
fields = ('username', 'address', 'password1', 'password2', 'status')
See also: How can I order fields in Django ModelForm?

Categories