How to fields to the User model - python

I want to be able to save a picture to a user and maybe even a description, these can be optional, but how to you add to a model. I don't want to go into the souce code of django to change it, can I overide a model to add fields, if so how?
how do i access these accounts.UserProfile and accounts.UserProfile.image in my views.py file
I have django-registration installed

From the docs:
If you'd like to store additional information related to your users, Django provides a method to specify a site-specific related model -- termed a "user profile" -- for this purpose.
To make use of this feature, define a model with fields for the additional information you'd like to store, or additional methods you'd like to have available, and also add a OneToOneField named user from your model to the User model. This will ensure only one instance of your model can be created for each User. For example:
from django.contrib.auth.models import User
class UserProfile(models.Model):
# This field is required.
user = models.OneToOneField(User)
# Other fields here
accepted_eula = models.BooleanField()
favorite_animal = models.CharField(max_length=20, default="Dragons.")
To indicate that this model is the user profile model for a given site, fill in the setting AUTH_PROFILE_MODULE with a string consisting of the following items, separated by a dot:
The name of the application (case sensitive) in which the user profile model is defined (in other words, the name which was passed to manage.py startapp to create the application).
The name of the model (not case sensitive) class.
For example, if the profile model was a class named UserProfile and was defined inside an application named accounts, the appropriate setting would be:
AUTH_PROFILE_MODULE = 'accounts.UserProfile'

Related

Django Extended Group's Permissions not applied to users

So I have extended Django's Group model to add an extra field like so:
class MyModel(Group):
extra_field = models.TextField(null=True, blank=True)
On doing this, each instance of MyModel created, creates a Group instance as well.
If I add a user to the resulting group with user.groups.add(group), the group is added as expected.
However, the permissions from the MyModel group do not seem to have trickled down to the user i.e
Doing user.get_all_permissions(), get_group_permissions() or even testing a user.has_permission(mygroup_permission) returns nothing. Only permissions from pure Group instances(created before extending the model) are shown.
Is there anything I need to do for permissions on customised groups to be visible on the users?
TIA
When you take a look in the ModelBackend, the default django authentication backend, you can see this:
def _get_group_permissions(self, user_obj):
user_groups_field = get_user_model()._meta.get_field('groups')
user_groups_query = 'group__%s' % user_groups_field.related_query_name()
return Permission.objects.filter(**{user_groups_query: user_obj})
Its quite obvious, that it tries to determine the permissions from the field that represents the users groups, here groups. Because your MyModel is not tied to djangos user model, you will not get any permissions this way.
You can now:
Write a custom user model and substitute the relationship of groups
Write a custom authentication backend
Use a One-To-One-Relation from MyModel to Group
In my opinion, the easiest way is to extend the Group model with a new model in an One-To-One relationship. This way you can use djangos auth system furthermore and have additional data available.

Django: Automatically selecting related model UserProfile when retrieving User model

When showing {{ user }} in a Django template, the default behavior is to show the username, i.e. user.username.
I'm changing this to show the user's initials instead, which are stored in a separate (OneToOneField) UserProfile model.
So in customsignup/models.py I've overridden the __unicode__ function successfully, with the desired result:
# __unicode__-function overridden.
def show_userprofile_initials(self):
return self.userprofile.initials
User.__unicode__ = show_userprofile_initials
But of course, the database is hit again because it needs to independently select the UserProfile model every time a user object is asked to show itself as a string. So even though this works, it escalates the number of database hits quite a bit.
So what I'd like to do, is to automatically use select_related('userprofile') whenever a User model is called from the database, seeing that I will essentially always want the profile when dealing with the user in the first place.
In more technical terms, I'm attempting to override the model manager of an existing model. So I'm in no control over the User model definition itself, since that's in an imported library.
So I've tried overriding the objects member of the User model in the same way that I overrode the __unicode__ function, like so:
# A model manager for automatically selecting the related userprofile-table
# when selecting from user-table.
class UserManager(models.Manager):
def get_queryset(self):
# Testing indicates that code here will NOT run.
return super(UserManager, self).get_queryset().select_related('userprofile')
User.objects = UserManager()
Is this supposed to work? If so, what am I getting wrong?
(I will mark an answer as correct if it can show that this is not supposed to work in the first place.)
A similar question I've found is here, but it's approached from the other end:
Automatically select related for OneToOne field
No, User.objects = MyManger() is not supposed to work. According to the docs, there are just two supported methods for extending the provided auth User model, either a profile model, as you are doing, or a proxy model, which probably doesn't fit your case. From the docs (emphasis added):
There are two ways to extend the default User model without substituting your own model. If the changes you need are purely behavioral, and don’t require any change to what is stored in the database, you can create a proxy model based on User. This allows for any of the features offered by proxy models including default ordering, custom managers, or custom model methods.
If you wish to store information related to User, you can use a OneToOneField 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.
As an alternative to extending the provided auth User model, you can provide your own custom User model. Then you will have complete control over its managers.
Instead, consider simply replacing {{ user }} with {{ user.profile.initials }}. Creating the OneToOne field on your profile model also creates a reverse accessor for instances of the related model. You can specify the reverse accessor name by the related_name keyword argument on the profile model field. For example...
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model)
user = models.OneToOneField('auth.User', related_name='profile')
initials = models.CharField(max_length=6)
some_user = User.objects.first()
# assuming there is already a profile related to this user
some_user.profile.initials = 'S.P.Y.'
You could also make a __str__ method for your profile model like
def __str__(self):
return self.initials
Then when you do {{ user.profile }} in a template, the initials will be shown.

Django: when to use OneToOneField and when use Inheritance? [duplicate]

I want to implement users in my system. I know that Django already has an authentication system, and I've been reading the documentation. But I don't know yet the difference between
from django.contrib.auth.models import User
class Profile(User):
# others fields
And
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User)
# others fields
I don't want to know why to use one or another, but what happens under the hoods. What's the difference?
Your first example is multi-table inheritance.
class Profile(User):
If you have a profile, you can access all the fields on the user model directly (e.g. profile.username and profile.email). In this case, Django creates a OneToOneField for you automatically.
The second example is a regular OneToOneField.
class Profile(models.Model):
user = models.OneToOneField(User)
In this case, you cannot access profile.username and profile.email. Instead, you access these fields via the one to one field (e.g. profile.user.username and profile.user.email).
In your case, where you are adding a profile model, I would avoid using inheritance, and use a one to one field instead. The User model has custom admins to handle passwords. If you use multi-table inheritance, then your Profile model would have to handle this as well. By using a one-to-one field, the custom admins can handle the user fields, and your Profile model admins only have to handle the additional profile fields.
Another option is creating a custom user model. In this case you subclass an abstract class AbstractUser or AbstractBaseUser instead of the class User. If your Profile class works, then I would recommend this instead of the custom user model, because custom user models are more complicated to set up.

Django setting up database for different users

I have Django project for recording personal expenses and keeping personal budget.
I have created required models for the project and authorization using Django. However the idea is that each authentic user shall keep own expenses records, therefore needs likely separate database. I have researched Django documentation and it seems doest not provide answer to this. Probably there is no need to set up another database but to create unique model fields inherited from default admin user fields and store the data for each user in the single database.
Please advice correct approach for this task.
You can always extend the auth user model to include additional data. You can create a new model that has all the additional fields plus a one-to-one relationship with the django user model.
eg:
from django.db import models
from django.conf import settings
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL)
date_of_birth = models.DateField(blank=True, null=True)
...
Here, you should be able to use the default auth user fields plus the custom fields you need.

Under the hoods what's the difference between subclassing the user and creating a one to one field?

I want to implement users in my system. I know that Django already has an authentication system, and I've been reading the documentation. But I don't know yet the difference between
from django.contrib.auth.models import User
class Profile(User):
# others fields
And
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User)
# others fields
I don't want to know why to use one or another, but what happens under the hoods. What's the difference?
Your first example is multi-table inheritance.
class Profile(User):
If you have a profile, you can access all the fields on the user model directly (e.g. profile.username and profile.email). In this case, Django creates a OneToOneField for you automatically.
The second example is a regular OneToOneField.
class Profile(models.Model):
user = models.OneToOneField(User)
In this case, you cannot access profile.username and profile.email. Instead, you access these fields via the one to one field (e.g. profile.user.username and profile.user.email).
In your case, where you are adding a profile model, I would avoid using inheritance, and use a one to one field instead. The User model has custom admins to handle passwords. If you use multi-table inheritance, then your Profile model would have to handle this as well. By using a one-to-one field, the custom admins can handle the user fields, and your Profile model admins only have to handle the additional profile fields.
Another option is creating a custom user model. In this case you subclass an abstract class AbstractUser or AbstractBaseUser instead of the class User. If your Profile class works, then I would recommend this instead of the custom user model, because custom user models are more complicated to set up.

Categories