Where to you monkey patch the Django user model? - python

I want to monkey patch the user model from Django.
My code:
from django.db import models
from django.contrib.auth.models import User
User.add_to_class('secret_question', models.CharField(max_length="100"))
User.add_to_class('answer', models.CharField(max_length="100"))
User.add_to_class('DOB', models.DateField())
Where do I place this code so that python manage.py syncdb will create the correct table?
I tried the main directory models.py, I tried an app's directory's models.py (these two didn't produce the correct table), and I tried placing it in the settings.py of the project (error, couldn't run).

Please take a look at Storing additional information about users section of the authentication documentation. It suggests a cleaner way to add additional information to a User object.
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.

If you really want to monkey patch user model, there already exists an app for this.
Django-primate
A modular django user.
This Django application monkey patches
django in order to have a custom User
model that plugs into the
django.contrib.auth application.

Related

Django extending user model with a onetoone, but have several model.py files in applications

I have a django project with many applications in it, each one has models.py for pieces that are related to that portion of the project (The specific application) though I am using django's model login and user auth but I need more data with that, I saw here:
https://docs.djangoproject.com/en/2.2/topics/auth/customizing/#custom-permissions
That there is a way to create another model that has the extra information and make it a onetoone to the user.
The thing is, this extra data I need available to all my other applications, so what models.py do I stuff this new table to be built?

Django Multiple Auth Models

I am working on a project where I need to have 3 types of Users.
Admin
Vendor
Customer
I want to be having seperate Models for all three of them Vendor & Customers instead of having a type field in a common User Model.
My first approach to this problem was to define all models by sub-classing the AbstractUser model
# models.py
from django.contrib.auth.models import AbstractUser
class Customer(AbstractUser):
pass
class Vendor(AbstractUser):
pass
And add a custom Authentication backend to handle the authentication of users based on the request object.
# settings.py
AUTHENTICATION_BACKENDS = ['backends.CustomAuthBackend']
And my backends.py file will contain the logic to authenticate users and use different models for each one based on the request object.
# backends.py
from __future__ import print_function
class CustomAuthBackend(object):
def authenticate(self, request, username=None, password=None):
# authenticate user based on request object
def get_user(self, user_id):
# logic to get user
However this does not work and looks like i also need to specifiy the AUTH_USER_MODEL in settings.py which is used for authentication.
Is it possible at all.Does Django allow to authenticate from 3 different tables. How can I go ahead with this ? Is there any other approach to this and what should I change ?
I have done similar staff a couple days ago, you are in the right approach. But there are a few other things needed to change to make it work. I'll explain what I did to make it success.
First, you have to custom your own user model, and you have to do it in the first place before you make the migrations. And also in the model file define different userManagers to manager different type of users. Then in your settings file you have to set AUTH_USER_MODEL and AUTHENTICATION_BACKENDS, AUTH_USER_MODEL is the default user model django will use for authentication and you can only set to one user model, but for AUTHENTICATION_BACKENDS you can have multiple backends,it's a list and django will loop every option inside to authenticate. by default it use django.contrib.auth.backends.ModelBackend, you can add your own auth backends. Check this on how to make your own authentication backend:https://docs.djangoproject.com/en/1.11/topics/auth/customizing/#writing-an-authentication-backend.
And depends on your application, you may also need to custom the serializer function and override some classes to make it work. In my own application, I was using DRF and JWT token to authenticate, so I also override some of the function which by default use the AUTH_USER_MODEL variable. In the end, I'm able to use admin model to login the admin page and use another custom user model to authenticate the application and get the JWT token. Anyway, always reference this page: https://docs.djangoproject.com/en/1.11/topics/auth/customizing/#customizing-authentication-in-django. Hope this can help you in your application.
django.contrib.auth is designed to work with one UserModel. Depending on what you want to achieve there are different apporaches.
If you just want to store different kind of profile/meta data for the different types of user you might use multi table inheritance - in this case you might stick with the default user model.
When it comes to different permissions based on the user type you should not solve this using separate classes. Instead use groups. This approach is much more flexible. It can nearly always happen that one person should belong to more than one group of users. When you model this based on the user classes you are in trouble.

Does Django implement user permissions in databases with models?

In a typical database, admin can assign users and can create tables which can be accessed by only a particular set of users or groups. One can also create queries that can be made by certain users in a database like MySQL.
Does Django provide any such functionality or is is it only the Django ADMIN Interface that does this?
I am aware that the admin can create users and provide them with permissions for working with app models.
Django by itself doesn't provide access to the database-level users / groups / permissions, because it doesn't make much sense for a typical web application where all connections will be made with the same database user (the one defined in settings.DATABASES). Note that it's not a shortcoming be really the standard for web applications.
What Django provides is application-level users / groups / permissions (cf https://docs.djangoproject.com/en/1.8/topics/auth/). You have access to this application-level layer thru the admin but also - of course - programmatically thru the django.contrib.auth package.
Yes, you can do that.
Django defined these models in module django.contrib.auth.models
You can import all models from there like Group, Permission and all.
from django.contrib.auth.models import *
If you want to list all django auth models you can see them in mysql/or other database too by prefix auth_* e.g, in mysql
show tables like "%auth%";
Over these models you can use django ORM.

Django Pinax , extending bundled applications

I want to use Pinax for a small project , but I am confused because I don't if can extend/change the behavior and functional of the provided applications .
Is there any documentation for extending the behavior of the bundled applications ?
example: in registration application ,I want to add custom fields but I am not able to find proper documentation on how to achieve it..( mainly for those which need db changes )
Thanks !
Yes, you can extend the behaviour of the built-in applications. If you are using the pinax basic setup with user accounts and profiles, you will have to add the extra fields you want in apps/profiles/models.py. For a list of field types, see here: https://docs.djangoproject.com/en/1.3/ref/models/fields/
This will create the necessary db fields for you when you run manage.py syncdb. If you have already sync'd the db, however, you will have to manually add the db columns. If you don't have any data you care about in that table, you can always just drop the table and it will recreate it. Django doesn't modify db tables once they are created, even if you change the model.
You will also have to modify the signup form to include these new fields and point your urls.py to the new signup form you created. Copy the form from the site-packages/pinax directory to your project. Don't modify them directly.
If you haven't already, you should check out the Django tutorial here: https://docs.djangoproject.com/en/1.3/intro/tutorial01/
This will give you a good idea of how Django apps are put together and how the different pieces interact, so you can do a better job customizing Pinax to your liking. Make sure you know what models.py, urls.py, views.py, and the templates are doing.

Django Project structure, recommended structure to share an extended auth "User" model across apps?

I'm wondering what the common project/application structure is when the user model extended/sub-classed and this Resulting User model is shared and used across multiple apps.
I'd like to reference the same user model in multiple apps.
I haven't built the login interface yet, so I'm not sure how it should fit together.
The following comes to mind:
project.loginapp.app1
project.loginapp.app2
Is there a common pattern for this situation?
Would login best be handled by a 'login app'?
Similar to this question but more specific.
django application configuration
UPDATE
Clarified my use-case above.
I'd like to add fields (extend or subclass?) to the existing auth user model. And then reference that model in multiple apps.
Why are you extending User? Please clarify.
If you're adding more information about the users, you don't need to roll your own user and auth system. Django's version of that is quite solid. The user management is located in django.contrib.auth.
If you need to customize the information stored with users, first define a model such as
class Profile(models.Model):
...
user = models.ForeignKey("django.contrib.auth.models.User", unique=True)
and then set
AUTH_PROFILE_MODULE = "appname.profile"
in your settings.py
The advantage of setting this allows you to use code like this in your views:
def my_view(request):
profile = request.user.get_profile()
etc...
If you're trying to provide more ways for users to authenticate, you can add an auth backend. Extend or re-implement django.contrib.auth.backends.ModelBackend and set it as
your AUTHENTICATION_BACKENDS in settings.py.
If you want to make use of a different permissions or groups concept than is provided by django, there's nothing that will stop you. Django makes use of those two concepts only in django.contrib.admin (That I know of), and you are free to use some other concept for those topics as you see fit.
You should check first if the contrib.auth module satisfies your needs, so you don't have to reinvent the wheel:
http://docs.djangoproject.com/en/dev/topics/auth/#topics-auth
edit:
Check this snippet that creates a UserProfile after the creation of a new User.
def create_user_profile_handler(sender, instance, created, **kwargs):
if not created: return
user_profile = UserProfile.objects.create(user=instance)
user_profile.save()
post_save.connect(create_user_profile_handler, sender=User)
i think the 'project/app' names are badly chosen. it's more like 'site/module'. an app can be very useful without having views, for example.
check the 2008 DjangoCon talks on YouTube, especially the one about reusable apps, it will make you think totally different about how to structure your project.

Categories