Subclassing existing model in Django - 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.

Related

Django 2.1 Models Importing Custom User Model

I have been working on an extended User model in my Django 2.1 project. I am curious to know if the way in which I am importing my CustomUser model into another model (for use as a ForeinKey) is the correct way of doing so.
I have encountered verbiage in the past indicating that it is not correct to simple import the User model from the admin app, but rather import it from django.conf.
example importing from the base User model:
from django.conf import settings
User = settings.AUTH_USER_MODEL
...
class <ModelName>(models.mode):
user = ForeignKey(User, on_delete=models.CASCADE, default=1)
Now that I am using a CustomUser Model (extending AbstractUser),
users/models.py:
class CustomUser(AbstractUser):
objects = CustomUserManager()
def __str__(self):
return self.username
Is it better practice to import this model via setting (as shown above) or is how I am doing it below (in my Post app) the right way to it:
posts/models.py:
from users.models import CustomUser
class Post(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, default=1)
I am assuming this is the wrong way to go about this, but I am not sure why, can someone let me know why the above is not best practice? Note: It does get the job done though.
Thanks!
There's nothing wrong with the way you are importing. The "settings" way of importing is merely a round-about way to get to the underlying model, since Django allows you to use a custom Model for user authentication handling.
Even better, however, is using the "lazy" load approach, which doesn't require any import statements at all:
user = models.ForeignKey('CustomUser', on_delete=models.CASCADE, default=1)
Be careful using a default on a ForeignKeyField, by the way. You need to be absolutely certain that the default value you provide will already be present, and will never disappear from the database.

Django: changing OneToOneField to ForeignKey ends up with 'User' object has no attribute 'profile'

Already tried using a Proxy model to access the User model from django-authtools package, but it still shows the same error. I do admit that I may have been doing this wrong, so feel free to suggest anything and I will try it. Thanks!
The model I use is from the django-authtools package.
AUTH_USER_MODEL = 'authtools.User'
This is from my models.py
class UserProfile(models.Model):
# ...
user = models.OneToOneField(
settings.AUTH_USER_MODEL, related_name='profile')
I've been working on this project for quite a while and have used multiple of the lines below**:
user.profile
user.profile.name
user.profile.playlists
# and many others
Now for my use case, I realized I needed to have multiple Profiles for one login so I was planning to go from OneToOneField to ForeignKey
class UserProfile(models.Model):
# ...
user = models.ForeignKey(
settings.AUTH_USER_MODEL, related_name='profiles')
** With this, my previous codes need to be changed because I won't be able to call the old profile attributes freely because it will be returning a set, not a single instance.
Instead, I want to do something like the following:
user.profile = user.profiles.all().first()
so that I don't have to change all the lines with user.profile. But I don't know where I can declare this and I badly need help because it's turning into a major blocker.
Any ideas? Any kind of help will be greatly appreciated.
You can define the property method in the use model.
#property
def profile(self):
retrun self.profiles.first()
If model is not define by you, you can try monkey patch
from module import ClassToPatch
def get_profile(self):
retrun self.profiles.first()
ClassToPatch.profile = property(get_profile)

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"

django - Extending `auth.models.User` and usering login, logout

If I create a CustomUser model which inherits from django.contrib.auth.models.User, like so:
in models.py
class CustomUser(django.contrib.auth.models.User):
customfield = TextField()
...
Should I still be able to use
django.contrib.auth.{authenticate, login, logout} in the normal way? Do I have to make some additional configuration change? I know these methods only work on User objects, but technically my CustomUser is-a User.
Currently, authenticate(username=u, password=p) is always returning None, even with valid credentials.
Since Django 1.5 (officially but it doesn't worked for me) and "stable" in 1.6 there is a functionality to extend the User model in a clean way.
At first:
-> Take care that you load the User model only via:
from django.contrib.auth import get_user_model
User = get_user_model()
-> Once you have built the database theres no easy way to change the User model. The database relations will break and Django / South isn't able to fix it.
-> third party modules have to be compatible with that new layout and refer in it's models to "get_user_model()", too.
You have to add some Code for the admin to respect your new model:
See: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#extending-the-existing-user-model
To Override the model you need to inherit from AbstractBaseUser:
from django.contrib.auth.models import AbstractBaseUser
class MyUser(AbstractBaseUser):
...
date_of_birth = models.DateField()
height = models.FloatField()
...
REQUIRED_FIELDS = ['date_of_birth', 'height']
AbstractBaseUser provides you all attributes of the default user model. So you don't have to take care of email, username, first_name, last_name, password etc.
More info about overriding the user model: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#django.contrib.auth.models.CustomUser
In your settings link your new model:
AUTH_USER_MODEL = 'customauth.MyUser'
Please read the whole documentation of customizing the user model, there are some interesting hints for overriding the default manager, admin forms etc. Just remember that bigger changes in an existing project can be a big pain.
A short overview:
- Extend models.AbstractUser
- Set AUTH_USER_MODEL in settings.py
All details can be found here: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#specifying-a-custom-user-model

When to use the Custom User Model in Django 1.5

I have a question regarding the custom user model in Django 1.5
So right now the default user model looks just fine to me, I just need to add a few other variables such as gender,location and birthday so that users can fill up those variables after they have successfully registered and activated their account.
So, what is the best way to implement this scenario?
Do I have to create a new app called Profile and inherit AbstractBaseUser? and add my custom variable to models.py? Any good example for me to follow?
thank you in advance
You want to extend your user model to the AbstractUser and add your additional fields. AbstractUser inherits all of the standard user profile fields, whereas AbstractBaseUser starts you from scratch without any of those fields.
It's hard to define best practices this close to the release, but it seems that unless you need to drastically redefine the User model, then you should use AbstractUser where possible.
Here are the docs for extending the User model using AbstractUser
Your models.py would then look something like this:
class MyUser(AbstractUser):
gender = models.DateField()
location = models.CharField()
birthday = models.CharField()
MyUser will then have the standard email, password, username, etc fields that come with the User model, and your three additional fields above.
Then you need to add the AUTH_USER_MODEL to your settings.py:
AUTH_USER_MODEL = 'myapp.MyUser'