I want to add a convenience/model method to the django.contrib.auth.models.User model. What is the best practice for doing this since, last time I checked, extending the User model was considered bad practice.
I have a separate custom UserProfile model. Should I be using that for all User-related convenience methods?
It depends what you are trying to add to the model. If you want to add more information about the user, then it is generally recommended that you use the UserProfile method: http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users
However, if you just want to add custom methods or managers to the User model, I would say that it's more logical to use a proxy model, like so:
from django.contrib.auth.models import User
class UserMethods(User):
def custom_method(self):
pass
class Meta:
proxy=True
A proxy model will operate on the same database table as the original model, so is ideal for creating custom methods without physically extending the model. Just replace any references to User in your views to UserMethods. (And of course you can use this in the admin tool by unregistering the User model and registering your proxy model in its stead.)
Any instances of the original User model that are created will be instantly accessible via the UserMethods model, and vice-versa. More here: http://docs.djangoproject.com/en/dev/topics/db/models/#proxy-models
(NB. Proxy models require Django 1.1 and above)
if you want to add custom methods to the User model, I would recommend monkey_patching:
create a file monkey_patching.py in any of your apps::
#app/monkey_patching.py
from django.contrib.auth.models import User
def get_user_name(self):
if self.first_name or self.last_name:
return self.first_name + " " + self.last_name
return self.username
User.add_to_class("get_user_name",get_user_name)
and import it in app's __init__.py file. ie::
#app/__init__.py
import monkey_patching
Yes. No need to mess with the foundations when your user model has a .get_profile() function attached to it.
2013 update:
in 1.5 you can sustitute a custom User model and add whatever you want https://docs.djangoproject.com/en/dev/topics/auth/customizing/#auth-custom-user
I prefer to use the same UserProfile across various projects I develop and extend User for any project-specific needs. So, common functionality goes to UserProfile, and project-specific functionality goes to custom User. I have not had any adverse effects of having a subclassed User model yet, I wonder if there still exist any with Django 1.0+.
Related
I have created a custom user model before making any migration and I wanted to move it from the app panel to the auth panel in the admin page.
To do that I created a proxy user model:
class User(AbstractUser):
pass
class ProxyUser(User):
pass
class Meta:
app_label = 'auth'
proxy = True
and then in admin.py:
from django.contrib.auth.admin import UserAdmin
from .models import ProxyUser
admin.site.register(ProxyUser, UserAdmin)
The problem is that the auth_permission table has permissions for user and proxyuser.
Can't understand why if I'm using a proxy and only one user table was created the permissions table behaves as if there were two (proxyuser and user).
Am I missing something?
Thanks in advance
Django uses the content type framework to keep track of "permissions" for various models. Proxy models get their own permissions.
This is explained in the authentication section of Django docs:
Proxy models work exactly the same way as concrete models. Permissions are created using the own content type of the proxy model. Proxy models don’t inherit the permissions of the concrete model they subclass
I feel what you're trying to achieve with the proxy model is unnecessary. I personally wouldn't worry much about 'Users' appearing under a separate section in the Django Admin. You will instead add unnecessary complexity to the code by using a proxy model (A future developer/you would wonder wether to use the custom User class or the ProxyUser class).
You may have done all migrations and no only for your apps, if you don't specify the app to migrate, Django makes all of the migrations. On the other way, maybe you can't log into the admin site if you doesn't do it.
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"
in django,i want to extend the auth_user model and adding the 2 fields.one is created_user which will display the date and time when user created something and other is modified_user which will display the date n time when modification is done..
is it possible by migration??
i ve tried dis code..
from django.contrib.auth.models import User, UserManager
class CustomUser(User):
created_user= models.DateTimeField("date and time when created")
modified_user=models.DateTimeField("date and time when modified")
objects= UserManager()
I suggest reading the documentation on creating your own custom user model.
In your particular case, the easiest thing would probably be to subclass AbstractUser and add your fields as above.
If you’re entirely happy with Django’s User model and you just want to add some additional profile information, you can simply subclass django.contrib.auth.models.AbstractUser and add your custom profile fields. This class provides the full implementation of the default User as an abstract model.
http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/
When it comes to extending the User model, the above article list two methods: the old way (ForeignKey) and the new way (User model with inheritance). But at the same time, this article dates back to Aug 2008.
I am using Django's development version.
Would you recommend Extending the Django User model with inheritance or by using ForeignKey?
I read in a couple of posts that extending django.contrib.auth.models.User is not recommended, so I will not be looking at that.
AFAIK, the cleaner approach - if this can fit in your project architecture - is to have a distinct user profile model, and use the AUTH_PROFILE_MODEL setting to link it up to the Django User model.
See the Django Doc about storing additional information for Users
Dominique Guardiola is right. Use the AUTH_PROFILE_MODEL. James Bennett reiterated this in his 'Django in Depth' talk. http://www.youtube.com/watch?v=t_ziKY1ayCo&feature=related around 1hr:37mins.
Decide on the application where we want to house our user's profile, let's call it BngGangOfFour.
Define a Model class, lets name it UserProfile for clarity, and give it the extra field(s) we desire.
BngGangOfFour/models.py
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User) #notice it must contain a 1 to 1 field with the auth user.
last_ip_address = models.CharField(max_length=20, default="")
Edit settings.py to designate our newly created model as the user profile.
settings.py
....
AUTH_PROFILE_MODULE = 'BngGangOfFour.UserProfile' #not case sensitive.
....
Access the profile directly off the user objects.
BngGangOfFour/views.py
....
def index(request):
if request.user.get_profile().last_ip_address = "127.0.0.1":
print("why hello me!")
return render_to_response('index.html', locals(), context_instance=RequestContext(request))
Sip a cold beer and call it a day.
The only time you can cleanly get away with extending User via inheritance is if you're writing an auth backend which will return an instance of the appropriate model instead.
How would you go about making a pluggable django app, that can accept data from any model and then perfom some action with that data (i.e Save to DB, Send email). This functionality should be generic and should not be tied to a specific model.
It depends on what functionality your app would provide and in what way you'd expect users of your app to use it's api. For interacting with other models you don't know about there are a few ways, depending on what your reusable app does. You can make forms, views etc that would accept a model class or instance as a property or parameter. The other way would be for the users of your app to specify their relevant models in settings.py much like auth deals with user profiles. For example if your app needs to know about a model class that provides info about gadgets the user would specify:
#user's settings.py
GADGETS_MODEL='myapp.CustomSuperFunGadgets'
To get the class for the user specified model you would do:
from django.core.exceptions import ImproperlyConfigured
from django.conf import settings
if not getattr(settings, 'GADGETS_MODEL', False):
raise ImproperlyConfigured('You need to set GADGETS_MODEL'
'in your project settings')
try:
app_label, model_name = settings.GADGETS_MODEL.split('.')
except ValueError:
raise ImproperlyConfigured('app_label and model_name should'
' be separated by a dot in the GADGETS_MODEL set'
'ting')
try:
model = models.get_model(app_label, model_name)
if model is None:
raise ImproperlyConfigured('Unable to load the gadgets '
'model, check GADGETS_MODEL in your project sett'
'ings')
except (ImportError):
raise ImproperlyConfigured('Unable to load the gadgets model')
#at this poing model will hold a reference to the specified model class
Another way of interacting with models you don't know about is your app to provide custom model fields or managers or special properties that would just attach signal handlers to the model they are attached to.
As I said it all depends on what problem your reusable app is trying to solve, and the approach you should take is always based on that.