Django: UserCreationForm not getting Custom User Class - django

I'm new to Django and I'm running into an odd issue. Using Django 2.2.5 I've created a custom User class, sub-classed from AbstractBaseUser. Other than extending AbstractBaseUser the only major change I made was deleting the username field and adding my own (won't get into why here). I've added the USERNAME_FIELD = "my new username" to the model as well.
This all appeared to work well and I was able to create users. I then installed django-registration, to use that functionality and when I tried to makemigrations I ran into this error:
'django.core.exceptions.FieldError: Unknown field(s) ("My new username") specified for User`
Now, this didn't make any sense to me since the model clearly has a"My new username" field and I'd specified Django should use my User model in setting via AUTH_USER_MODEL. I knew that was working because calling get_user_model() in a shell returned my custom model.
Now here's where it gets weird, I was able to trace the issue to django-registrations, RegistrationForm. This is a form that subclasses Django's UserCreationForm. When RgistrationForm was loading or whatever during makemigrations it was producing the error because the model reference for the form was django.User not my custom user model. RegistrationForm does not declare a model and uses UserCreationForm model which happens to be User from django.contrib.auth.models.
Based on what I've read and how User is written it should reference my model, via the swappable attribute since I've set AUTH_USER_MODEL and it's supposed to swap to the model located in that settings option. For some reason, though it's not working and I don't know enough about Django to debug further.
I'm very confused by this since get_user_model() references the exact same setting and it works.
I've been able to fix this for the moment by editing the RegistrationForm model to add model = "Custom user model in django-registration's forms. I'd rather not have to distribute a custom version of this package with the rest of the site at the moment.
Any idea what's going on with swappable that might be causing this issue?
Edit 1/27/19: Update I tried sub-classing the relevant django-registration classes, but it turns out that simply importing RegistrationForm causes the issue. Importing UserCreationForm does not immediately cause a problem but if I try to check UserCreationForm.Meta.model."My new username" it provides this error:
AttributeError: type object 'User' has no attribute 'UVI_Handle'
This is consistent with the error above. At this point I'm not sure how to proceed again. I could subclass UserCreationForm, but none of django-registration will pick up on that so there doesn't seem to be a point in using it, since I'll have to copy the whole thing.

Instead of changing the package code, you should subclass:
In the case where your user model is compatible with the default
behavior of django-registration, (see below) you will be able to
subclass RegistrationForm, set it to use your custom user model as the
model, and then configure the views in django-registration to use your
form subclass. For example, you might do the following (in a forms.py
module somewhere in your codebase – do not directly edit
django-registration’s code):
from registration.forms import RegistrationForm
from mycustomuserapp.models import MyCustomUser
class MyCustomUserForm(RegistrationForm):
class Meta:
model = MyCustomUser
Above is taken from here, you should also change the urls, which is also described there.

Related

Django admin: created users have plain text password and can't login

I want to have a custom tab for staff users so in admin.py I do:
class StaffUser(User):
class Meta:
proxy = True
#admin.register(StaffUser)
class AdminUserAdmin(admin.ModelAdmin):
pass
But on the admin site, whenever I add a new user with this interface I can't log in with it since for some reason it sets it's password as plain text instead of hashing it.
I've read this post BUT if I do that and change StaffUser to inherint from AdminUserI get this other error
AttributeError: type object 'StaffUser' has no attribute '_meta'
You should declare your models in models.py (or a models package), not admin.py.
UserAdmin (there is no such thing as an AdminUser in the Django packages) is a subclass of ModelAdmin, that is, a class for registering models in the Django admin. It is not a model subclass that you can extend to make new models.
Also, if you are trying to extend the User just to distinguish users with access to the Django admin site, note that there is already an is_staff property in the default User model. And in any case, if you still want to extend the User model, you should be extending AbstractUser instead as stated in the docs.

Create editable page for user User Account

So my question is what should I look for creating a page which will allow user to add some information after the registration. I took a look at Django Profiles, but it requires lower version of Python (2.7), if I'm not mistaken.
Another thing is I need to create two types of users - I'm thinking of maybe #permission to implement it, but another point is that I want to include something like checkbox while registration, and if user chooses one type of user, he will be allowed to see default account page for this type of user which he should fill up.
I'm running Django 1.10.5 and Python 3.6.0.
Thanks in advance.
If you want to add custom fields to your user object take a look at custom user model django implementation. Then, for updating user object you can just use generic update view, it will look something like this:
from django.contrib.auth import get_user_model
class UserUpdateView(UpdateView):
model = get_user_model()
fields = ['field1', 'field2', 'field3']
template_name = "core/user_edit.html"

How to properly extend django User model

I'm trying to extend the default Django's authentication model with additional fields and functionaliy, so I've decided to just go with extending User model and writing my own authentication backend.
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
class MyUser(User):
access_key = models.CharField(_('Acces Key'), max_length=64)
This is really a basic code yet when trying to syncdb I'm cetting a strange error that Google doesn't know about :
CommandError: One or more models did not validate:
core.sldcuser: 'user_ptr' defines a relation with the model 'auth.User', which has been swapped out. Update the relation to point at settings.AUTH_USER_MODEL.
In my settings.py I've added what I guess is required :
AUTH_USER_MODEL = 'core.MyUser'
Had anyone stumbled upon this error ?
Or maybe I should use a one-to-one way, or a hybrid of 1t1 with proxy ?
What you're doing right now, is creating a subclass of User, which is non-abstract. This means creating a table that has a ForeignKey called user_ptr pointing at the primary key on the auth.User table. However, what you're also doing by setting AUTH_USER_MODEL is telling django.contrib.auth not to create that table, because you'll be using MyUser instead. Django is understandably a little confused :P
What you need to do instead is inherit either from AbstractUser or AbstractBaseUser.
Use AbstractUser if you want everything that User has already, and just want to add more fields
Use AbstractBaseUser if you want to start from a clean state, and only inherit generic functions on the User, but implement your own fields.
REF:
https://docs.djangoproject.com/en/dev/topics/auth/customizing/#extending-the-existing-user-model
https://docs.djangoproject.com/en/dev/topics/auth/customizing/#substituting-a-custom-user-model

Upgrading Django to 1.5 with Django-CMS - user model issue

I have just moved a site from Django-CMS 2.3.5 to 2.4.1 (with help from Stackoverflow) under Django 1.4.
I am now upgrading to Django 1.5, which is only hard because I need to update the old separate user profile to a new custom user model. I followed the excellent instructions here, and also replaced all references to User with settings.AUTH_USER_MODEL.
Unfortunately Django-CMS's models apparently still refer to User though: when I type manage.py runserver, I get this error:
CommandError: One or more models did not validate:
cms.pagemoderatorstate: 'user' defines a relation with the model 'auth.User', which has been swapped out. Update the relation to point at settings.AUTH_USER_MODEL.
cms.globalpagepermission: 'user' defines a relation with the model 'auth.User', which has been swapped out. Update the relation to point at settings.AUTH_USER_MODEL.
cms.pagepermission: 'user' defines a relation with the model 'auth.User', which has been swapped out. Update the relation to point at settings.AUTH_USER_MODEL.
cms.pageuser: 'user_ptr' defines a relation with the model 'auth.User', which has been swapped out. Update the relation to point at settings.AUTH_USER_MODEL.
cms.pageuser: 'created_by' defines a relation with the model 'auth.User', which has been swapped out. Update the relation to point at settings.AUTH_USER_MODEL.
cms.pageusergroup: 'created_by' defines a relation with the model 'auth.User', which has been swapped out. Update the relation to point at settings.AUTH_USER_MODEL.
How can I get Django-CMS to use the new user model?
thanks!
There is very simple solution. Just need to register your custom user before importing CMSPlugin. Example:
from django.db import models
from django.contrib.auth import models as auth_models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
telephone = models.CharField(max_length=100)
email = models.CharField(max_length=100)
auth_models.User = User
from cms.models import CMSPlugin
For others with this question, here is my summary of what I have learned from https://github.com/divio/django-cms/issues/1798.
There are four potential options:
If you need your custom user model to have a name other than User, you'll need to wait.
You can call the custom user model User - though when I tried this, I got errors about clashes with related m2m fields. There are some further details on the above link which may help resolve this.
Django 1.5 still lets you use user profiles. So if you are ok with using a deprecated feature, you can still use Django-CMS 2.4 and Django 1.5 with user profiles instead of a custom user model. (I misread the Django docs here and thought user profiles were not supported in Django 1.5.)
You can often get away without either a user profile or a custom user model - they are best used to add data specifically for user authentication. Instead, you can use another model with a one-to-one relationship to User, and use the reverse relationship to access it.
In my case, I am going to go with #3 in the short-run and #4 in the long-run.

Subclassing existing model in Django

I'm not sure why this isn't working, since it seems to be exactly what the django documentation tells me to do.
I want to be able to subclass the built-in User model so that I can add extra fields to it.
from django.contrib.auth.models import User
class Person(User):
my_extra_field = models.CharField(max_length=30)
#...
This seems rather simple, and the way I understand it, all the methods of User should be available to Person. However, calling
user = Person.objects.create_user('john', 'lennon#thebeatles.com', 'johnpassword')
in the django shell results in an error.
Is this just a quirk of the shell (I'm using iPython), or am I doing something wrong?
http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/
You need to include the UserManager(). Import the User, UserManager and set the UserManager() to the variable objects in your Person class.