What's the best way to extend the User model (bundled with Django's authentication app) with custom fields? I would also possibly like to use the email as the username (for authentication purposes).
I've already seen a few ways to do it, but can't decide on which one is the best.
The least painful and indeed Django-recommended way of doing this is through a OneToOneField(User) property.
Extending the existing User model
…
If you wish to store information related to User, you can use a one-to-one relationship to a model containing the fields for additional information. This one-to-one model is often called a profile model, as it might store non-auth related information about a site user.
That said, extending django.contrib.auth.models.User and supplanting it also works...
Substituting a custom User model
Some kinds of projects may have authentication requirements for which Django’s built-in User model is not always appropriate. For instance, on some sites it makes more sense to use an email address as your identification token instead of a username.
[Ed: Two warnings and a notification follow, mentioning that this is pretty drastic.]
I would definitely stay away from changing the actual User class in your Django source tree and/or copying and altering the auth module.
Note: this answer is deprecated. see other answers if you are using Django 1.7 or later.
This is how I do it.
#in models.py
from django.contrib.auth.models import User
from django.db.models.signals import post_save
class UserProfile(models.Model):
user = models.OneToOneField(User)
#other fields here
def __str__(self):
return "%s's profile" % self.user
def create_user_profile(sender, instance, created, **kwargs):
if created:
profile, created = UserProfile.objects.get_or_create(user=instance)
post_save.connect(create_user_profile, sender=User)
#in settings.py
AUTH_PROFILE_MODULE = 'YOURAPP.UserProfile'
This will create a userprofile each time a user is saved if it is created.
You can then use
user.get_profile().whatever
Here is some more info from the docs
http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users
Update: Please note that AUTH_PROFILE_MODULE is deprecated since v1.5: https://docs.djangoproject.com/en/1.5/ref/settings/#auth-profile-module
Well, some time passed since 2008 and it's time for some fresh answer. Since Django 1.5 you will be able to create custom User class. Actually, at the time I'm writing this, it's already merged into master, so you can try it out.
There's some information about it in docs or if you want to dig deeper into it, in this commit.
All you have to do is add AUTH_USER_MODEL to settings with path to custom user class, which extends either AbstractBaseUser (more customizable version) or AbstractUser (more or less old User class you can extend).
For people that are lazy to click, here's code example (taken from docs):
from django.db import models
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser
)
class MyUserManager(BaseUserManager):
def create_user(self, email, date_of_birth, password=None):
"""
Creates and saves a User with the given email, date of
birth and password.
"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=MyUserManager.normalize_email(email),
date_of_birth=date_of_birth,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, username, date_of_birth, password):
"""
Creates and saves a superuser with the given email, date of
birth and password.
"""
u = self.create_user(username,
password=password,
date_of_birth=date_of_birth
)
u.is_admin = True
u.save(using=self._db)
return u
class MyUser(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
date_of_birth = models.DateField()
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['date_of_birth']
def get_full_name(self):
# The user is identified by their email address
return self.email
def get_short_name(self):
# The user is identified by their email address
return self.email
def __unicode__(self):
return self.email
def has_perm(self, perm, obj=None):
"Does the user have a specific permission?"
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
"Does the user have permissions to view the app `app_label`?"
# Simplest possible answer: Yes, always
return True
#property
def is_staff(self):
"Is the user a member of staff?"
# Simplest possible answer: All admins are staff
return self.is_admin
Since Django 1.5 you may easily extend the user model and keep a single table on the database.
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.utils.translation import ugettext_lazy as _
class UserProfile(AbstractUser):
age = models.PositiveIntegerField(_("age"))
You must also configure it as current user class in your settings file
# supposing you put it in apps/profiles/models.py
AUTH_USER_MODEL = "profiles.UserProfile"
If you want to add a lot of users' preferences the OneToOneField option may be a better choice thought.
A note for people developing third party libraries: if you need to access the user class remember that people can change it. Use the official helper to get the right class
from django.contrib.auth import get_user_model
User = get_user_model()
There is an official recommendation on storing additional information about users.
The Django Book also discusses this problem in section Profiles.
The below one is another approach to extend an User.
I feel it is more clear,easy,readable then above two approaches.
http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/
Using above approach:
you don't need to use
user.get_profile().newattribute to access the additional information
related to the user
you can just directly access
additional new attributes via
user.newattribute
You can Simply extend user profile by creating a new entry each time when a user is created by using Django post save signals
models.py
from django.db.models.signals import *
from __future__ import unicode_literals
class UserProfile(models.Model):
user_name = models.OneToOneField(User, related_name='profile')
city = models.CharField(max_length=100, null=True)
def __unicode__(self): # __str__
return unicode(self.user_name)
def create_user_profile(sender, instance, created, **kwargs):
if created:
userProfile.objects.create(user_name=instance)
post_save.connect(create_user_profile, sender=User)
This will automatically create an employee instance when a new user is created.
If you wish to extend user model and want to add further information while creating a user you can use django-betterforms (http://django-betterforms.readthedocs.io/en/latest/multiform.html). This will create a user add form with all fields defined in the UserProfile model.
models.py
from django.db.models.signals import *
from __future__ import unicode_literals
class UserProfile(models.Model):
user_name = models.OneToOneField(User)
city = models.CharField(max_length=100)
def __unicode__(self): # __str__
return unicode(self.user_name)
forms.py
from django import forms
from django.forms import ModelForm
from betterforms.multiform import MultiModelForm
from django.contrib.auth.forms import UserCreationForm
from .models import *
class ProfileForm(ModelForm):
class Meta:
model = Employee
exclude = ('user_name',)
class addUserMultiForm(MultiModelForm):
form_classes = {
'user':UserCreationForm,
'profile':ProfileForm,
}
views.py
from django.shortcuts import redirect
from .models import *
from .forms import *
from django.views.generic import CreateView
class AddUser(CreateView):
form_class = AddUserMultiForm
template_name = "add-user.html"
success_url = '/your-url-after-user-created'
def form_valid(self, form):
user = form['user'].save()
profile = form['profile'].save(commit=False)
profile.user_name = User.objects.get(username= user.username)
profile.save()
return redirect(self.success_url)
addUser.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="." method="post">
{% csrf_token %}
{{ form }}
<button type="submit">Add</button>
</form>
</body>
</html>
urls.py
from django.conf.urls import url, include
from appName.views import *
urlpatterns = [
url(r'^add-user/$', AddUser.as_view(), name='add-user'),
]
Extending Django User Model (UserProfile) like a Pro
I've found this very useful: link
An extract:
from django.contrib.auth.models import User
class Employee(models.Model):
user = models.OneToOneField(User)
department = models.CharField(max_length=100)
>>> u = User.objects.get(username='fsmith')
>>> freds_department = u.employee.department
It's very easy in Django version 3.0+ (If you are NOT in the middle of a project):
In models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
extra_field=models.CharField(max_length=40)
In settings.py
First, register your new app and then below AUTH_PASSWORD_VALIDATORS
add
AUTH_USER_MODEL ='users.CustomUser'
Finally, register your model in the admin, run makemigrations and migrate, and it will be completed successfully.
Official doc: https://docs.djangoproject.com/en/3.2/topics/auth/customizing/#substituting-a-custom-user-model
It's too late, but my answer is for those who search for a solution with a recent version of Django.
models.py:
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
extra_Field_1 = models.CharField(max_length=25, blank=True)
extra_Field_2 = models.CharField(max_length=25, blank=True)
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
you can use it in templates like this:
<h2>{{ user.get_full_name }}</h2>
<ul>
<li>Username: {{ user.username }}</li>
<li>Location: {{ user.profile.extra_Field_1 }}</li>
<li>Birth Date: {{ user.profile.extra_Field_2 }}</li>
</ul>
and in views.py like this:
def update_profile(request, user_id):
user = User.objects.get(pk=user_id)
user.profile.extra_Field_1 = 'Lorem ipsum dolor sit amet, consectetur adipisicing elit...'
user.save()
New in Django 1.5, now you can create your own Custom User Model (which seems to be good thing to do in above case). Refer to 'Customizing authentication in Django'
Probably the coolest new feature on 1.5 release.
Here I tried to explain how to extend Django's Default user model with extra fields
It's very simple just do it.
Django allows extending the default user model with AbstractUser
Note:- first create an extra field model which you want to add in user model then run the command python manage.py makemigrations and python manage.py migrate
first run ---> python manage.py makemigrations then
second run python manage.py migrate
Step:- create a model with extra fields which you want to add in Django default user model (in my case I created CustomUser
model.py
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class CustomUser(AbstractUser):
mobile_no = models.IntegerField(blank=True,null=True)
date_of_birth = models.DateField(blank=True,null=True)
add in settings.py name of your model which you created in my case CustomUser is the user model. registred in setttings.py to make it the default user model,
#settings.py
AUTH_USER_MODEL = 'myapp.CustomUser'
finally registred CustomUser model in admin.py
#admin.py
#admin.register(CustomUser)
class CustomUserAdmin(admin.ModelAdmin):
list_display = ("username","first_name","last_name","email","date_of_birth", "mobile_no")
then run command python manage.py makemigrations
then python manage.py migrate
then python manage.py createsuperuser
now you can see your model Default User model extended with (mobile_no ,date_of_birth)
This is what i do and it's in my opinion simplest way to do this. define an object manager for your new customized model then define your model.
from django.db import models
from django.contrib.auth.models import PermissionsMixin, AbstractBaseUser, BaseUserManager
class User_manager(BaseUserManager):
def create_user(self, username, email, gender, nickname, password):
email = self.normalize_email(email)
user = self.model(username=username, email=email, gender=gender, nickname=nickname)
user.set_password(password)
user.save(using=self.db)
return user
def create_superuser(self, username, email, gender, password, nickname=None):
user = self.create_user(username=username, email=email, gender=gender, nickname=nickname, password=password)
user.is_superuser = True
user.is_staff = True
user.save()
return user
class User(PermissionsMixin, AbstractBaseUser):
username = models.CharField(max_length=32, unique=True, )
email = models.EmailField(max_length=32)
gender_choices = [("M", "Male"), ("F", "Female"), ("O", "Others")]
gender = models.CharField(choices=gender_choices, default="M", max_length=1)
nickname = models.CharField(max_length=32, blank=True, null=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
REQUIRED_FIELDS = ["email", "gender"]
USERNAME_FIELD = "username"
objects = User_manager()
def __str__(self):
return self.username
Dont forget to add this line of code in your settings.py:
AUTH_USER_MODEL = 'YourApp.User'
This is what i do and it always works.
Simple and effective approach is
models.py
from django.contrib.auth.models import User
class CustomUser(User):
profile_pic = models.ImageField(upload_to='...')
other_field = models.CharField()
Currently as of Django 2.2, the recommended way when starting a new project is to create a custom user model that inherits from AbstractUser, then point AUTH_USER_MODEL to the model.
Source: https://docs.djangoproject.com/en/2.2/topics/auth/customizing/#using-a-custom-user-model-when-starting-a-project
Try this:
Create a model called Profile and reference the user with a OneToOneField and provide an option of related_name.
models.py
from django.db import models
from django.contrib.auth.models import *
from django.dispatch import receiver
from django.db.models.signals import post_save
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='user_profile')
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
try:
if created:
Profile.objects.create(user=instance).save()
except Exception as err:
print('Error creating user profile!')
Now to directly access the profile using a User object you can use the related_name.
views.py
from django.http import HttpResponse
def home(request):
profile = f'profile of {request.user.user_profile}'
return HttpResponse(profile)
Related
I've been learning Django and I'm trying to understand how to extend some of the built-in functionality. To do that I've referenced Customizing Authentication in Django and tried to implement the instructions I've found there in a standard django-admin project.
The problem is that when I try to save the form to the database (sqlite3 included db), nothing is recorded. The form passes the is_valid check, but when I check the database however, nothing has been added to either my user or patients tables.
Hoping someone can point out where this is going wrong, thank you.
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
isPatient = models.BooleanField(default=False)
class Patient(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
age = models.PositiveIntegerField()
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.db import transaction
from .models import *
class RegisterPatient(UserCreationForm):
age = forms.IntegerField()
class Meta:
model = User
fields = UserCreationForm.Meta.fields + ("age")
#transaction.atomic
def save(self, commit=True):
user = super(RegisterPatient, self).save(commit=False)
user.isPatient = True
user.save()
patient = Patient.objects.create(user=user)
patient.firstName.add(*self.cleaned_data.get('age'))
patient.save()
views.py
def register(response):
form = RegisterPatient(response.POST)
if form.is_valid():
print("is Valid") # < Code reaches here
form.save
return redirect("/")
settings.py
AUTH_USER_MODEL = 'main.User'
admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from . models import User
admin.site.register(User, UserAdmin)
You need to replace form.save with form.save(). The latter calls the save function, whereas the former does not.
I have a Profile model that extends the user model like so,
class Profile(User):
user = models.OneToOneField(User, parent_link=True, on_delete=models.CASCADE)
slug = models.SlugField(unique=True, blank=True)
def save(self, *args, **kwargs):
print('self.username')
print(self.username)
self.slug = self.username
super(Profile, self).save(*args, **kwargs)
I am trying to create a slug field for my model , so I override the save method to include the slug as the username. The thing is, when I create a new user with the command createsuperuser and print out the username as you can see in the code, it doesn't show anything - it doesn't show the provided username. Could this be the reason why I am having this problem ? And if so, how can I fix it?
If you're sure you don't want to have your user's profile data in a separate model with a OneToOneField back to Django's default User, then you should probably subclass AbstractUser and not User, as specified in the docs.
https://docs.djangoproject.com/en/2.2/topics/auth/customizing/#substituting-a-custom-user-model
Consider this part :
If you’re entirely happy with Django’s User model and you just want to add some additional profile information, you could simply subclass django.contrib.auth.models.AbstractUser and add your custom profile field [...]
(from https://docs.djangoproject.com/en/2.2/topics/auth/customizing/#extending-django-s-default-user)
Then you'd go like this:
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.models import UserManager
from django.utils.text import slugify
from django.db import models
class User(AbstractUser):
slug = models.SlugField(unique=True, blank=True)
objects = UserManager()
def save(self, *args, **kwargs):
print('self.username')
print(self.username)
self.slug = slugify(self.username)
super().save(*args, **kwargs)
Then, define settings.AUTH_USER_MODEL,
AUTH_USER_MODEL = "myapp.User" # also, add 'myapp' to INSTALLED_APPS
Remember: you'll need to reference your User model like this (and this is how you should do it anyway, whether you customized that model or not):
from django.contrib.auth import get_user_model
User = get_user_model()
Profile cannot inherit User but instead should inherit Model. And, for the creation of User to be able to create a corresponding row in a different table (Profile) and set the slug will involve the use of signals.
You are overriding the save method correctly. You need to do more when you use the createsuperuser command.
from django.utils.text import slugify
from django.contrib.auth.models import UserManager
class CustomUserManager(UserManager):
def _create_user(self, username, email, password, **extra_fields):
username_slug = slugify(username)
extra_fields.setdefault('slug', username_slug)
super()._create_user(username, email, password, **extra_fields)
class Profile(User):
user = models.OneToOneField(User, parent_link=True, on_delete=models.CASCADE)
slug = models.SlugField(unique=True, blank=True)
def save(self, *args, **kwargs):
print('self.username')
print(self.username)
self.slug = slugify(self.username)
super().save(*args, **kwargs)
objects = CustomUserManager()
While trying to create my own user model and admin, the test gives the following error.
: (admin.E019) The value of 'filter_horizontal[0]' refers to 'groups', which is not an attribute of 'account.User'.
: (admin.E019) The value of 'filter_horizontal[1]' refers to 'user_permissions', which is not an attribute of 'account.User'.
: (admin.E116) The value of 'list_filter[1]' refers to 'is_superuser', which does not refer to a Field.
: (admin.E116) The value of 'list_filter[3]' refers to 'groups', which does not refer to a Field.
models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
class UserManager(BaseUserManager):
def create_user(self,username,email,password=None, **extra_fields):
user=self.model(
username=username.lower(),
email=self.normalize_email(email),
**extra_fields)
#user name is converted into lowercase
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self,username,email,password=None):
user = self.create_user(
username,email
)
user.set_password(password)
user.is_superuser=True
user.is_staff =True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
username=models.CharField(max_length=255,unique=True)
email=models.EmailField(max_length=255,unique=True)
password=models.CharField(max_length=255)
is_staff =models.BooleanField(default=False)
is_active=models.BooleanField(default=True)
objects=UserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from . import models
# Register your models here.''''
class UserAdmin(BaseUserAdmin):
ordering = ['id']
list_display=['username','email']
admin.site.register(models.User,UserAdmin)
admintest.py
from django.test import TestCase, Client
from django.contrib.auth import get_user_model
from django.urls import reverse
class AdminTests(TestCase):
def setUp(self):
self.client = Client()
self.admin_user = get_user_model().objects.create_superuser(
username='admin',
password='123',
email='fda#gmail.com'
)
self.client.force_login(self.admin_user)
self.user = get_user_model().objects.create_user(
username='mantis',
password='123',
email='111'
)
def test_users_listed(self):
"""Test that users are listed on the user page"""
url = reverse('admin:core_user_changelist')
res = self.client.get(url)
self.assertContains(res, self.user.username)
self.assertContains(res, self.user.email)
You simply need to add PermissionsMixin in your class User(AbstractBaseUser) such so User(AbstractBaseUser, PermissionsMixin)
You can import it with following: from django.contrib.auth.models import PermissionsMixin
if you look at django docs
https://docs.djangoproject.com/en/3.1/ref/contrib/admin/#module-django.contrib.admin
in the Note they said you need to add your custom fields to fieldsets (for fields to be used in editing users) and to add_fieldsets (for fields to be used when creating a user).
so you need to add these fields to your UserAdmin class
For anyone who come across the same issue, simply import the permission mixin as so: from django.contrib.auth.models import PermissionsMixin and sub-class it with your custom user model (along side the AbstractBaseUser class).
Also, there's no need to include email, as the authentication token, in the REQUIRED_FIELDS array. This is because the USERNAME_FIELD field is already set to email and it's always prompted as required.
Another error you may come across is the (admin.E033) The value of 'ordering[0]' refers to 'username', which is not an attribute of '<app.CustomUserModel>'. This is because the USERNAME_FIELD in the custom model was re-assigned to use email instead. To fix, add ordering=("email",) to the registered custom model fieldsets in admin.py.
There is something to note before doing anything: as in my case, you have to make sure there is no method in your model with the same name as the fields which throw E116. (Python, right?)
In this example, make sure you don't have any method named is_superuser and groups in your model.
I'd like to save and access custom field of allauth. After I save the form and try to access the data but it's empty.
{{ user.school }}
I only add forms.py. Do I need to add on models.py too?
-> I change the models but still I can't access the school filed ㅜㅜ)
forms.py
from django.contrib.auth import get_user_model
from django import forms
SCHOOL = (
('', 'Select your school...'),
('ucla.edu', 'UCLA'),
('berkeley.edu', 'Berkeley'),
)
class SignupForm(forms.Form):
school = forms.ChoiceField(choices=SCHOOL, required=True)
def signup(self, request, user):
user.school = self.cleaned_data['school']
user.save()
models.py
class UserProfile(models.Model):
user = models.OneToOneField(User)
school = models.CharField(max_length=128)
def __unicode__(self):
return self.user.username
Thanks in advance!
yes.
I would extend the django user model and
profile = user.profile
profile.school = self.cleaned_data['school']
profile.save(update_fields=['school'])
I am new to Django and I have been trying this for weeks, but could not find a way to solve this problem.
I want to store additional information like user mobile number, bank name, bank account. And want to store the mobile number while user registers and wants user to login with either (mobile number and password) or (email and password).
This is my UserProfile model
from django.db import models
from django.contrib.auth.models import User
from django.contrib.auth.models import AbstractUser
# Create your models here.
class UserProfile(AbstractUser):
user_mobile = models.IntegerField(max_length=10, null=True)
user_bank_name=models.CharField(max_length=100,null=True)
user_bank_account_number=models.CharField(max_length=50, null=True)
user_bank_ifsc_code = models.CharField(max_length=30,null=True)
user_byt_balance = models.IntegerField(max_length=20, null=True)
And this is my forms.py
from django import forms
from django.contrib.auth.models import User # fill in custom user info then save it
from django.contrib.auth.forms import UserCreationForm
from models import UserProfile
from django.contrib.auth import get_user_model
class MyRegistrationForm(UserCreationForm):
email = forms.EmailField(required = True)
mobile = forms.IntegerField(required=True)
class Meta:
model = UserProfile
fields = ('username', 'email', 'password1', 'password2','mobile' )
def save(self,commit = False):
user = super(MyRegistrationForm, self).save(commit = False)
user.email = self.cleaned_data['email']
user.user_mobile = self.cleaned_data['mobile']
user.set_password(self.cleaned_data["password1"])
user_default = User.objects.create_user(self.cleaned_data['username'],
self.cleaned_data['email'],
self.cleaned_data['password1'])
user_default.save()
if commit:
user.save()
return user
In my settings.py I have included
AUTH_USER_MODEL = "registration.UserProfile"
admin.py of my app is
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from models import UserProfile
class UserProfileInline(admin.StackedInline):
model = UserProfile
can_delete = False
verbose_name_plural = 'userprofile'
class UserProfileAdmin(UserAdmin):
inlines = (UserProfileInline, )
admin.site.register(UserProfile, UserProfileAdmin)
While adding the user from admin I get this error
Exception at /admin/registration/userprofile/1/
<class 'registration.models.UserProfile'> has no ForeignKey to <class 'registration.models.UserProfile'>
Can someone help me with this or point out to the full working exapmle, I have seen Django documentation but didn't find any luck. Or if there is another way to do this.
Thanks in advance
Edit 1:
While registering from the registration form I'm also getting this error
DatabaseError at /register
(1146, "Table 'django_auth_db.auth_user' doesn't exist")
You have confused yourself a bit here. The idea of subclassing AbstractUser - and defining AUTH_USER_MODEL as your subclass - is that the new model completely replaces auth.models.User. You shouldn't be importing the original User at all, and you certainly should be calling User.objects.create_user(): your new model's manager now has its own create_user method.
Because of this, there's no reason to muck about with inline admins. Your UserProfile should be registered in the admin using the existing django.contrib.auth.admin.UserAdmin class.
Inlines forms assume that you have a Generic ForeignKey on your model, in this case, the UserProfileAdmin expect a Generic ForeignKey of the UserProfile, that does not exists. Try to do a regular Model Admin, like:
class UserProfileAdmin(admin.ModelAdmin):
can_delete = False
verbose_name_plural = 'userprofile'
admin.site.register(UserProfile, UserProfileAdmin)