Reputation: 3193
How to can I create my own user model in Django, in which I want that my P.K be the username field and not the id field autogenerated by Django?
I am trying the following:
I've create the userprofiles application in where I will create my customize django user model
INSTALLED_APPS = [
...
'userprofiles.apps.UserprofilesConfig',
...
]
AUTH_USER_MODEL = 'userprofiles.User'
In my userprofiles/models.py
file I have defined the following:
from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, UserManager, PermissionsMixin
# Create your models here.
class User(AbstractBaseUser, PermissionsMixin):
GENDER_MALE = 'M'
GENDER_FEMALE = 'F'
GENDER_OTHER = 'O'
GENDER_CHOICES = (
(GENDER_MALE, u'Male'),
(GENDER_FEMALE, u'Female'),
)
username = models.CharField(max_length=15, unique=True, db_index=True, primary_key=True)
first_name=models.CharField(max_length=50, blank=False,)
last_name=models.CharField(max_length=50, blank=False,)
photo = models.ImageField(upload_to='avatars', blank=True)
email = models.EmailField(max_length=254, unique=True)
is_staff = models.BooleanField(
default=True,
help_text='Designates whether the user can log into this admin site.')
is_active = models.BooleanField(default=True)
#date_joined = models.DateTimeField(default=None)
#date_joined = models.DateTimeField()
gender = models.CharField(
max_length=1,
choices=GENDER_CHOICES,
blank=False, )
is_player = models.BooleanField(default=False)
is_coach = models.BooleanField(default=False)
is_viewer = models.BooleanField(default=False)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email',]
objects = UserManager()
class Meta:
db_table = 'auth_user'
def get_full_name(self):
"""
Returns the first_name plus the last_name, with a space in between.
"""
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
"Returns the short name for the user."
return self.first_name
I am using the AbstractBaseUser
class due to:
AbstractBaseUser provides the core implementation of a User model, including hashed passwords and tokenized password resets. You must then provide some key implementation details: ...
and also I considered this explanation in which say that is necessary add manually the fields that I needed.
Then, when I perform the migrations the fields that I've defined in my User
model (that inherit from AbstractBaseUser
) are created in my database:
(fuupbol) ➜ fuupbol_project git:(master) ✗ python manage.py makemigrations
Migrations for 'userprofiles':
0013_auto_20160418_2252.py:
- Add field groups to user
- Add field user_permissions to user
- Alter field is_superuser on user
(fuupbol) ➜ fuupbol_project git:(master) ✗ python manage.py migrate
Operations to perform:
Apply all migrations: sessions, userprofiles, admin, contenttypes, auth
Running migrations:
Rendering model states... DONE
Applying userprofiles.0013_auto_20160418_2252... OK
(fuupbol) ➜ fuupbol_project git:(master) ✗
Then I've created a superuser via command line interface of this way:
(fuupbol) ➜ fuupbol_project git:(master) ✗ python manage.py createsuperuser
Username: cdiaz
Email: [email protected]
Password:
Password (again):
Superuser created successfully.
(fuupbol) ➜ fuupbol_project git:(master) ✗
Like Django use special forms to create and edit forms in the admin relative to Users model, due to these was thinked only for the django original user model.
Here we are using a custom django user model with AbstractBaseUser
, then we use the following class:
UserChangeForm
which is applied to the User model, so this way is applied to the admin user form, and the UserCreationForm
for that an user be created with from my user form customized with the previous modificationsIn my userprofiles/forms.py
file
from django import forms
from django.contrib.auth.forms import (UserChangeForm,UserCreationForm)
from .models import User
class CustomUserChangeForm(UserChangeForm):
class Meta(UserChangeForm.Meta):
model = User
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = User
In my userprofiles/admin.py
file create an CustomUserAdmin class customized with the fields defined before in my custom User model
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User
from .forms import CustomUserChangeForm, CustomUserCreationForm
# Register your models here.
class CustomUserAdmin(UserAdmin):
form = CustomUserChangeForm
add_form = CustomUserCreationForm
fieldsets = UserAdmin.fieldsets + (
(
None, {
'fields':(
'username',
'password',
'first_name',
'last_name',
'gender',
'email',
'photo',
'is_staff',
'is_active',
'is_superuser',
'is_player',
'is_coach',
'is_viewer',
'last_login',
)
}
),
)
#Change our UserAdmin class to inherit of our CustomUserAdmin created above (do not inherit of model.ModelAdmin)
@admin.register(User)
class UserAdmin(CustomUserAdmin):
list_display = ('username','password','first_name','last_name','gender','email','photo','is_staff','is_active','is_superuser','is_player','is_coach','is_viewer','last_login',)
Then when I go to the Django admin and I see the options to edit some user already created, I get this message:
In this moment I do not have the date_joined
attribute in my User model, and if I add the date_joined
attribute to my User model, and perform the migrations, I get this messages:
(fuupbol) ➜ fuupbol_project git:(master) ✗ python manage.py makemigrations userprofiles
Migrations for 'userprofiles':
0022_user_date_joined.py:
- Add field date_joined to user
(fuupbol) ➜ fuupbol_project git:(master) ✗
And when I execute the migrate
command
(fuupbol) ➜ fuupbol_project git:(master) ✗ python manage.py migrate userprofiles
Operations to perform:
Apply all migrations: userprofiles
Running migrations:
Rendering model states... DONE
Applying userprofiles.0015_user_date_joined...Traceback (most recent call last):
File "/home/bgarcial/.virtualenvs/fuupbol/lib/python3.4/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
psycopg2.IntegrityError: column "date_joined" contains null values
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/home/bgarcial/.virtualenvs/fuupbol/lib/python3.4/site-packages/django/core/management/__init__.py", line 353, in execute_from_command_line
utility.execute()
File "/home/bgarcial/.virtualenvs/fuupbol/lib/python3.4/site-packages/django/core/management/__init__.py", line 345, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/bgarcial/.virtualenvs/fuupbol/lib/python3.4/site-packages/django/core/management/base.py", line 348, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/bgarcial/.virtualenvs/fuupbol/lib/python3.4/site-packages/django/core/management/base.py", line 399, in execute
output = self.handle(*args, **options)
File "/home/bgarcial/.virtualenvs/fuupbol/lib/python3.4/site-packages/django/core/management/commands/migrate.py", line 200, in handle
executor.migrate(targets, plan, fake=fake, fake_initial=fake_initial)
File "/home/bgarcial/.virtualenvs/fuupbol/lib/python3.4/site-packages/django/db/migrations/executor.py", line 92, in migrate
self._migrate_all_forwards(plan, full_plan, fake=fake, fake_initial=fake_initial)
File "/home/bgarcial/.virtualenvs/fuupbol/lib/python3.4/site-packages/django/db/migrations/executor.py", line 121, in _migrate_all_forwards
state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
File "/home/bgarcial/.virtualenvs/fuupbol/lib/python3.4/site-packages/django/db/migrations/executor.py", line 198, in apply_migration
state = migration.apply(state, schema_editor)
File "/home/bgarcial/.virtualenvs/fuupbol/lib/python3.4/site-packages/django/db/migrations/migration.py", line 123, in apply
operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
File "/home/bgarcial/.virtualenvs/fuupbol/lib/python3.4/site-packages/django/db/migrations/operations/fields.py", line 62, in database_forwards
field,
File "/home/bgarcial/.virtualenvs/fuupbol/lib/python3.4/site-packages/django/db/backends/base/schema.py", line 396, in add_field
self.execute(sql, params)
File "/home/bgarcial/.virtualenvs/fuupbol/lib/python3.4/site-packages/django/db/backends/base/schema.py", line 110, in execute
cursor.execute(sql, params)
File "/home/bgarcial/.virtualenvs/fuupbol/lib/python3.4/site-packages/django/db/backends/utils.py", line 79, in execute
return super(CursorDebugWrapper, self).execute(sql, params)
File "/home/bgarcial/.virtualenvs/fuupbol/lib/python3.4/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/home/bgarcial/.virtualenvs/fuupbol/lib/python3.4/site-packages/django/db/utils.py", line 95, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/home/bgarcial/.virtualenvs/fuupbol/lib/python3.4/site-packages/django/utils/six.py", line 685, in reraise
raise value.with_traceback(tb)
File "/home/bgarcial/.virtualenvs/fuupbol/lib/python3.4/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
django.db.utils.IntegrityError: column "date_joined" contains null values
(fuupbol) ➜ fuupbol_project git:(master) ✗
I cannot understand the reason of the error message django.db.utils.IntegrityError: column "date_joined" contains null values
due to in this moment I do not have this attribute date_joined
Any orientation would be appreciated. Thanks
Upvotes: 3
Views: 2371
Reputation: 4158
I am assuming you don't have data for date_joined on any of the instances and one of the migrations requires it to not be be null. You can probably either go into the database and add it manual to get around it temporarily.
Upvotes: 1