Adding custom permissions to imported models - python

In my Django project, I would like to add a custom permission to the User model imported from django.contrib.auth.
(Specifically, a permission to allow/deny the user to change their password).
I do understand how to add permissions to my own model, however, I would like the ability to extend an existing model.
Is this possible?

These instructions are a bit outdated, but should give you an idea on how to extend the User model via inheritance, so that you could add any new functionality to the subclass.

Related

Whats the difference between DjangoModelPermissions and DjangoObjectPermissions

Whats the difference between DjangoModelPermissions and DjangoObjectPermissions?
I'm still learning Django and DRF and according to the docs, they seems to do exactly the same thing.
DjangoModelPermissions:
This permission class ties into Django's standard django.contrib.auth model permissions.
DjangoObjectPermissions
This permission class ties into Django's standard object permissions framework that allows per-object permissions on models
For the later, it seems like it has something to do with Django’s permission framework foundation which has no implementation. and apparently, django-guardian fills in this gap.
In Django admin, I'm able to assign a Model's CRUD permission to users and groups, so what does the later add?
I'm trying to wrap my head around this permission system. What are the differences and what should I know about them?
DjangoModelPermissions is all about permissions to interact with a database table which are represented as models in code while DjangoObjectPermissions are permissions to interact with individual rows in the table which are model instances in code.
Basically, the object permissions are granular permissions which give access to some rows in a table but can restrict access to other rows in the same table

Extend User Model or Custom Pipeline in Social-App-Django

I am implementing social-app-django (not the deprecated one; the one that relies on Python-social-auth) with django 1.11 (not using Mongo). My application will need to store and manipulate a lot of data on users other than that which is fetched from their social media accounts at login.
I don't need to fetch or collect any extra data when the user authenticates, but various actions they perform on my site will need to be saved to their user model. I am wondering which of the following approaches is preferred (I've searched extensively online, but can't find a specific explanation of why to use one vs the other):
Create my own user model in my app's models.py (call it MyUser) that doesn't extend anything special, and then add a function in the authentication pipeline that associates the social-app-django user with a corresponding instance of MyUser. Leave AUTH_USER_MODEL and SOCIAL_AUTH_USER_MODEL unchanged.
or...
Create my own user model in my app's models.py, and in the project's settings.py set AUTH_USER_MODEL and SOCIAL_AUTH_USER_MODEL to point to MyUser. Leave the pipeline unchanged. In this case, I was wondering whether someone could clarify what MyUser and its manager should extend, and what I need to import in modules.py (I am confused because a lot of stack overflow posts are referring to deprecated versions of this module and I keep getting errors). Also, in this case should I be setting both AUTH_USER_MODEL and SOCIAL_AUTH_USER_MODEL, or just one of them?
Do these two methods essentially achieve the same thing? Is one more reliable/preferred for some reason? Or, should I be doing both? Thanks very much for any assistance.
Another detail: I would like to be able to access the User database not only from the app I am currently building, but also from other apps (within the same Django project) that I will build in the future. Does this affect anything?
Since I see this has a decent number of views I will post the solution I eventually came to.
Both django and social-app-django (or any other social auth module) make use of the default User model for authentication. While it's possible to edit this model to add custom parameters, I don't recommend it. It's not good abstraction or modularization. If you make a mistake when configuring the model, you won't just break a specific feature on your site, but you might also break the authentication itself.
The only circumstances I can think of under which you'd want to edit the default user model itself is if you need to make changes that affect the authentication flow itself (for example, adding your own custom authentication provider).
It's much easier and safer to create a new model called UserProfile, with a required one-to-one relationship to a User object. Now, you can treat the User object as the authentication part, and the UserProfile object as the content/storage part. You won't have to mess with the User model very often, and the UserProfile model doesn't matter for authentication purposes. Note that in this configuration you should NOT need to change the AUTH_USER_MODEL or SOCIAL_AUTH_USER_MODEL fields in the settings.py file.
If you take this approach, you will need to add a custom step in the authentication pipeline in which you create a new UserProfile object and associate it with the User who is currently logging in.

Whether to define own User model in django or use Django auth user model?

I am starting with Django App schema design and my schema has UserProfile, UserFavourites and UserComments models .
After doing a bit research i found out that we can user django's own User model or we can create own user model which will extend from AbstractUser
Platform = Django 1.8.5
I have found many similar questions but now that i have newest version of Django framework has anything changed ?
Also need to know pros and cons of each approach
In a new project, strongly consider starting out with a custom User model.
The reason is that if you want to change your User model later, then there is a clear way to do that (migrations). However, switching from a auth-User to a custom User when you already have ForeignKey relations (etc) to the auth-User is a major pain (see below). Considering that it is very easy to just start out with your own model at the start of a project (maybe just copy the auth model), there is very little reason not to.
The docs say this about how hard it is to change AUTH_USER_MODEL later:
Warning
Changing AUTH_USER_MODEL has a big effect on your database structure.
It changes the tables that are available, and it will affect the
construction of foreign keys and many-to-many relationships. If you
intend to set AUTH_USER_MODEL, you should set it before creating any
migrations or running manage.py migrate for the first time.
Changing this setting after you have tables created is not supported
by makemigrations and will result in you having to manually fix your
schema, port your data from the old user table, and possibly manually
reapply some migrations.
Warning
Due to limitations of Django’s dynamic dependency feature for
swappable models, you must ensure that the model referenced by
AUTH_USER_MODEL is created in the first migration of its app (usually
called 0001_initial); otherwise, you will have dependency issues.
In addition, you may run into a CircularDependencyError when running
your migrations as Django won’t be able to automatically break the
dependency loop due to the dynamic dependency. If you see this error,
you should break the loop by moving the models depended on by your
User model into a second migration (you can try making two normal
models that have a ForeignKey to each other and seeing how
makemigrations resolves that circular dependency if you want to see
how it’s usually done)
In other words, if you choose not to use AUTH_USER_MODEL at the start of your project, it's almost impossible to change later.
There is a ticket #24370 for adding custom user model and AUTH_USER_MODEL setting to the default project template, and to recommend doing this in the documentation. This ticket is just waiting for someone to implement it.
Pulled from Django's documentation
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
So just add your extra user fields to UserProfile Model. Make a one-to-one relationship with each of your desired model

Django: extending user model vs creating user profile model

I'm creating an app in Django and so far I have been using an extended user model like so:
class MyUser(AbstractBaseUser):
...
with all the user and profile info, but I see a lot of people creating different models for the profile and the user itself on stack overflow, using OneToOneField, although those are mostly old questions.
My question is: which is better and, if there isn't a best among them, what are the advantages for each solution?
thanks!
It depends on what you want to do -- if you're happy with the User model as it stands in the latest version of Django you should just use that -- it's easy and you'll get a lot functionality that goes along with it -- for example a pretty good permission system, and you can be sure to be compatible with all third party modules. But if you thing you'll need to expand on the User model, it's pretty straightforward how to do it. You might find that in the future you need to add more methods to your model than you expected.
The examples that you see with separate UserProfile / User model are mostly a legacy of django < 1.5, where that was the recommended way to extend the User model. There's no reason to follow that pattern any more -- it's a lot more work to have to use two models where you just want one model
**2019 Update**
If you are starting a new Django project, you should always create your own custom user model that inherits from AbstractUser, as per the Django documentation, i.e.
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
pass
even if you don't need any additional functionality. The reason for this is that for very low effort, you are making it easy to customize your user object in the future. It's very laborious to replace the built-in User object with your own after you have run the initial migrations, unless you're able to delete all of your data and migrations and start over.
I find some useful information in Django docs:
Extending Django’s default User¶
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
fields, although we’d recommend a separate model as described in the
“Model design considerations” note of Specifying a custom User model.
AbstractUser provides the full implementation of the default User as
an abstract model.
And:
Model design considerations
Think carefully before handling information not directly related to
authentication in your custom User Model.
It may be better to store app-specific user information in a model
that has a relation with the User model. That allows each app to
specify its own user data requirements without risking conflicts with
other apps. On the other hand, queries to retrieve this related
information will involve a database join, which may have an effect on
performance.
So if I reads it correctly, it means if the fields are related to authentication, then you should consider substitute the original User model. But if it's not related, like profile fields, such birthday, or profile_image, then you might want to create a standalone app that reference the original User model.
And a good tutorial I found: http://riceball.com/d/content/django-18-tutoria-52-adding-user-profile
A ForeignKey is to create a one-to-many relationship. In other words, it will return a queryset. For example, a single car has many wheels, but one wheel isn't attached to several different cars.
A OneToOneField will create a relationship between strictly two objects. For example, the rim belongs to the front-left tire, and only that tire has that rim.
Does that make sense?

Why not to extend User in Django REST

I am using Django REST to create users for my app.
Everywhere i look at, for users they extend AbstractBaseUser.
I tried extending the User model, and it seems to work just fine.
I have an PersonalAbstractUser that extends the Django User. Then, Worker and Client extends PersonalAbstractUser.
Login and custom permissions seem to work just fine up until now, but i am getting concerned when i see that no one else is extending User...
Why is that? Did i miss something?
This is not a question about Django REST, but about Django itself.
The problem with extending the User object directly is that it is already a concrete model, so extending it will use multi-table inheritance. That's not usually a good idea - especially if you're further extending it.
AbstractUser is an abstract model, but (unlike AbatractBaseUser) contains all the fields that User defines. You should use that.

Categories

Resources