Django setting up database for different users - python

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.

Related

Django - Team/User relationships

I'm at a loss... I'm just learning Django and I am really rather confused about how to make a field work the way I would like it to.
I understand that Django has a native "Groups" model. However, I am looking to build my own teams model for customization and practice.
Here is my models.py file for my Users app:
from django.db import models
from django.contrib.auth.models import User
class Team(models.Model):
members = models.ManyToManyField(User)
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
admin = models.BooleanField("Admin Status")
Here's where I'm confused. I would like to be able to call the team that the user is part of directly from User.Profile. So, I want to add a field to my Profile class that will automatically populate with the team name when a user is added to a team.
A potential problem I can see is that, currently, I can assign a user to multiple teams. This doesn't bother me, perhaps I can have a Profile model field that automatically populates with a list of all the teams that the user is associated with. Regardless, I can't figure out what type of field I would need to use, or how to do this.
Does that make sense?
A potential problem I can see is that, currently, I can assign a user to multiple teams.
Indeed, you can however easily retrieve the Teams the myprofile object is a member of with:
Team.objects.filter(members__profile=myprofile)
You thus can make a property for the Profile model:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
admin = models.BooleanField("Admin Status")
#property
def teams(self):
return Team.objects.filter(
members__profile=self
)
Then you thus access the Teams of a myprofile with myprofile.teams.
So, I want to add a field to my Profile class that will automatically populate with the team name when a user is added to a team.
From my limited knowledge of database, you can add a name field to your Team model.
Keeping in mind your requirement as mentioned in question, i would suggest you to use django reverse relations to get all the teams the profile is associated with
user_teams = User.objects.get(id='user_id').profile_set.all()[0].team_set.all()
to know more about django ORM reverse relation, here is a very short article

difference between ForeignKey and extending the User class/model in Django

Django: When extending User, better to use OneToOneField(User) or ForeignKey(User, unique=True)?
I went through this thread and found that ForeignKey(with unique=True) is better than OneToOneField, but what about extending the class itself, I.e. here is the example
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
# some additional fields
OR
class UserProfile(User):
# some additional fields
Difference between these two approaches and pros/cons and which one should I use?
EDIT:
I can use AbstractUser as well
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
phone_no = models.CharField(max_length=10, blank=True)
and then mentioned AUTH_USER_MODEL = 'myapp.User' in settings.py
main concern is, what approach should I use, extending the class or ForeignKey ?
Duplicates:
What's the difference between OneToOne and Subclassing a model in Django
Django Model Inheritance versus OneToOne field
MORE EDIT
Forget about ForeginKey or OneToOne, assume only one of these two exist, now compare that with extending/subclassing approach
First, it is good to know there currently are several options how to extend the Django user model. Each has its purpose (but there is some overlap as well). Django docs are a bit confusing as it seems from this there are two options, i.e. proxy or OneToOneField. However this relates to the existing user model, as further on in the docs is dealt with custom user models.
So in practice there are four (common) ways to deal with extending the user model:
Proxy model (no new databasefields, just to change user model behavior, i.e. new ordering, new methods, etc.).
OneToOneField (extra datafields needed within existing Djang user model).
Custom user model with AbstractBaseUser (extra datafields
needed, and specific requirements regarding authenticaton process,
e.g. using emailaddress als id token instead of username).
Custom user model with AbstractUser (extra datafields needed, no
change to authentication).
Implementing option 3 and 4 a fresh database migration is needed, so these are only suitable for new projects.
This is a good link for more detail on this. I think option 2 and 4 are closest as both only want to extend to add more datafields. Writer seems in favor of option 2, but when starting a new project option 4 seems easier to me. Somewhere in the comments writer mentions risk of not being able to upgrade to new Django versions for option 3 and 4. Seems far-fetched to me, but I can't tell really.
There is no better way to do, the thing is if you do extend AbstractUser you need to redefine some functions so it may be longer but you have more control on what you wanna do with your user.
Make a OneToOne field on django default user is faster and also allow you to add your own user custom fields but you can use directly User default field in your custom object, and your custom field on the user :
from django.contrib.auth.models import User
class Employee(models.Model):
user = models.OneToOneField(User)
department = models.CharField(max_length=100)
You can do :
>>> u = User.objects.get(username='fsmith')
>>> freds_department = u.employee.department
So it really depends on what you want to do. You can do your User for example if you want to take the mail adress as the identification token (it's a common exmaple but you can do much more things :p).
Here is a good explanation (I place it on user but you can read the whole page it's pretty interesting when you dive into User and authentication into Django).
Hope it help.
I am skeptical about the benefits of a unique FK verses one-to-one, you could achieve a similar thing in the admin by using fieldsets so I would prefer to have an explicit one-to-one field on the model, making the nature of the relation more obvious.
The duplicate questions you linked to aren't specific to the auth User model and discuss one-to-one vs model inheritance generally. Technically they are both the same (i.e. model inheritance uses a one-to-one field)
So ultimately the choice comes down to semantics: is your related model a 'subclass' of the other, or just a link to further related info?
In the case of auth User you would ask yourself then: are there some extra fields that should be present for all users (eg gender, facebook id etc)? or some fields you want to omit from the Django User model (eg to use unique email address as username)?
In this case the obvious choice is to extend AbstractUser. If you can't imagine specifying null=True on your user profile model you should consider extending AbstractUser.
On the other hand there may be some data that is more analogous to the old UserProfile model (have a look how things were in old versions of Django before extending AbstractUser was supported: https://docs.djangoproject.com/en/1.4/topics/auth/#storing-additional-information-about-users)
Perhaps for example you have different types of users who may or may not have certain extra sets of fields. In this case it may make sense to have a one-to-one link to one or more 'profile' models.

Django-Nonrel AbstractUser Permissions

I am working on a project and I have decided to use Google App Engine for hosting (Django-nonrel). The website will have multiple types of users (inheriting from AbstractUser), and I want to be able to create permissions to control what a user can see/do. Since the native Django permissions do not work on Nonrel, I tried using permission_backend_nonrel, however it only works if you use the standard User model.
I have spent lots of time searching for how others have gotten permissions to work on Nonrel and AbstractUser, but have not found anything. It seems like I should give up on getting permissions to work and just create fields within the user models to replicate permissions. For example, if I want only some users to have the ability to change their email address, then I could do:
accounts\models.py
class UserProfile(AbstractUser):
address = models.CharField(max_length=40)
can_change_email = models.BooleanField(default=True)
customers\models.py
class CustomerProfile(UserProfile):
company = models.BooleanField(max_length=40)
In this scenario I could set 'can_change_email' and control this behavior in the views for UserProfile.
I would prefer to use the built-in permission system, but running out of ideas. Any suggestions?
I'd say you might have better luck creating separate one-to-one models to signify the difference between your users. Django expects you to have a single user model.
Another option is to use the normal User model and create proxy models that reflect the changes you want to have between users.
The first way:
class CustomerProfile(models.Model):
user = models.OneToOneField(User)
The second way:
class CustomerProfile(User):
class Meta:
proxy = True

django-oauth2-provider with custom user model?

I am really stuck in my project right now. I am trying to implement Oauth2 for my app. I found out about django-oauth2-provider a lot and tried it. The only problem is, it uses the User model at django.contrib.auth. The main users of our site are saved in a custom model called User which does not inherit from or extend the model at django.contrib.auth.
Is there any way to use my custom User model for creating clients and token?
If django-oauth2-provider can't be used for this purpose, can anyone recommend me some oauth2 library with the option to implement oauth2 with my own model.
Sincerely,
Sushant Karki
As the previous answer suggested, you should extend AbstractUser from django.contrib.auth.models.
The problem with the access token that the OP referring to, occur when changing the setting AUTH_USER_MODEL AFTER django-oauth2-provider was migrated.
When django-oauth2-provider is migrated, it creates a key constrain between the User model and django-oauth2-provider.
The solution is very easy:
Create your new User model and change the AUTH_USER_MODEL setting.
Go to the django_migration table in your database.
Delete all rows of django-oauth2-provider.
run python manage.py makemigrations
run python manage.py migrate
Now, the django-oauth2-provider tables are connected to the RIGHT User model.
django-oauth2-provider fetches the user model using settings.AUTH_USER_MODEL, with a fallback to auth.User. If you extend AbstractUser your User model will include all the fields of auth.User plus any additional fields you specify.
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
some_additional_field = models.BooleanField(default=False)
Specify the user model to be used like this in settings.py:
AUTH_USER_MODEL = 'user_api.User'
If you don't want to base your user on AbstractUser you'll also need to write your own user manager, e.g. by extending the BaseUserManager
You can read more about ways to customize django's user model here.

What's the proper way to use multiple AUTH_USER_MODEL in Django 1.5?

I want to use two different models for django.contrib.auth module. The first one is the default User model provided by Django which is completely suitable for admin access (groups, permissions etc.) but the other one is customer model which has a lot of different attributes (city, locale, address etc.) compared to default User model. These user groups must use different tables and mustn't have any relation.
I created a Customer model inherited from AbstractBaseUser and a middleware class called ChangeBaseUser like this:
class ChangeBaseUser(object):
def process_request(self, request):
match = resolve(request.path)
if match.app_name == "myapp":
settings.AUTH_USER_MODEL = 'myapp.Customer'
else:
settings.AUTH_USER_MODEL = 'auth.User'
It's working but I'm not sure whether this is the proper way to do it because in documentation there is a section (link) that implies the convenient way is to assign a static value for default user model.
If this is not the proper way, do you have any suggestions for having multiple user models per module basis?
If your requirement is to keep admin users and customers separate, I don't see anything wrong with having multiple user models. At this point, the customer model is like any model, except it is very similar to the user model and that is perfectly fine if that works for you. The only disadvantage is that you will have to possibly duplicate many helpers django gives you for the Django user model such as auth backend or sessions for users. If you are willing to do all that, this seems perfectly fine.
If you wish however to utilize many of the django helpers you might want to create a very basic user model which will serve as a base for both admins and customers:
class User(AbstractBaseUser):
# use this for auth and sessions
class Admin(models.Model):
user = models.OneToOneField(UserBase, related_name='admins')
# ... other admin-specific fields
class Customer(models.Model):
user = models.OneToOneField(UserBase, related_name='admins')
# ... other customer-specific fields
This will allow you to reuse many of the things Django provides out of the box however it will incur some additional db overhead since more joins will have to be calculated. But then you can cache things for customers so you can get some of the performance back.

Categories