What is the best way to extend third party model in django 1.5?
Suppose I have 3rd party model called Feedback:
class Feedback(models.Model):
user = models.ForeignKey(
'auth.User',
verbose_name=_('User'),
related_name='feedback_form_submissions',
blank=True, null=True,
)
email = models.EmailField(
verbose_name=_('Email'),
blank=True,
)
...
I have my own user class. I need to override the user field. email I need to make blank=False and presumably want to add another Field to the model. What is the best way to do this?
Depending on the circumstance, that is, which 3rd party app you are using, you can approach this in a variety of ways:
Explicity inheriting from a model:
class CustomFeedback(Feedback):
#etc
Create a custom app:
Extend the app by doing a django-admin.py startapp AppName_custom which is a technique I have used with some apps. In that case you will want to inheret from a class like above but intercept DB methods like save or clean.
Fork the app. This is easily the most difficult way of doing this if you are inexperienced with Django. Just clone or fork via git or mercurial then add whatever code you need to modify the behavior of the app.
As a rule of thumb (pardon the expression) you shoudln't modify the User model since the Auth module is nicely comparmentalized. Instead you should use an app like django-profiles to add data to models or extend Forms.
Have you looked at this post? How to make email field unique in model User from contrib.auth in Django
I think it answers everything you want.
Django also includes documentation on how to do this here: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#extending-user
You can also designate a custom User model for Django to use with AUTH_USER_MODEL = 'myapp.MyUser'. From there you can set your custom fields.
Related
i'm happy with django built in user/auth , i just want to add some fields to it and change table name (mostly the last one , i can use another table for custom fields )
so i searched around and apparently we can use subclass as suggested on Rename Django's auth_user table?
So i have to start a new app and use it's model to as a subclass for AbstractUser or there is another way? (After all i just want to use it's model and other parts of app are useless )
anyway i created a new project / started app called customuser and in its model i have this code
customuser/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class customuser(AbstractUser):
class Meta:
swappable = 'AUTH_USER_MODEL'
db_table = 'customuser'
i ran makemigrations AND migrate ... it's done successfully
but atill the tables with default name was created in database as you can see below ... am i missing something ?
To use a custom user model, you need to set the AUTH_USER_MODEL setting in your settings module.
Note that you don't need to set swappable = 'AUTH_USER_MODEL'. This is an undocumented and private attribute, and is probably better left untouched.
Quite frankly if you're still in the position to do it, i'd just start a new app. It says in the docs that this decision is best made before starting your project because its a pain in the ... its hard.
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.
The solution otherwise is to dumpdata from the database, and manually tweak it so any reference to the user class in your dump file is replaced with your new user class. then you need to create some migrations to change the schema.
So it is doable. its just much simpler to start from a fresh project.
Django allows you to override the default User model by providing a value for the AUTH_USER_MODEL setting that references a custom model
AUTH_USER_MODEL = 'myapp.MyUser'
This dotted pair describes the name of the Django app (which must be in your INSTALLED_APPS), and the name of the Django model that you wish to use as your user model.
A full example of an admin-compliant custom user app can be found on the Django Project website.
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.
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
So I am using a custom user model accounts.player and i'm also using django-registration in my project.
With the custom model it now encounters an error. I know I could just write my own registration code but is there a way to use the custom model class with django-registration. I had a look on the docs but didn't really find a solution.
I'm sure theres probably a way using something like a subclass but i'm not sure how to implement this.
What files are required and what code would I need??
This is what I did for a personal project of mine:
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name = 'MoreAboutUser', unique=True)
age = ....
gender = ....
Regarding your error, I don't know how to help you since you didn't provide any traceback/code. But you can connect your custom model with the User model with a OneToOneFiel'
You could either Fork django-registration and make changes to Make it work with Custom User model... But that would be a long process...
Or
You could switch to django-allauth , which is a better and well maintained Registration app for Django.
It is compatible with Latest django version and also provides social registration out of the box
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.