I want to implement users in my system. I know that Django already has an authentication system, and I've been reading the documentation. But I don't know yet the difference between
from django.contrib.auth.models import User
class Profile(User):
# others fields
And
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User)
# others fields
I don't want to know why to use one or another, but what happens under the hoods. What's the difference?
Your first example is multi-table inheritance.
class Profile(User):
If you have a profile, you can access all the fields on the user model directly (e.g. profile.username and profile.email). In this case, Django creates a OneToOneField for you automatically.
The second example is a regular OneToOneField.
class Profile(models.Model):
user = models.OneToOneField(User)
In this case, you cannot access profile.username and profile.email. Instead, you access these fields via the one to one field (e.g. profile.user.username and profile.user.email).
In your case, where you are adding a profile model, I would avoid using inheritance, and use a one to one field instead. The User model has custom admins to handle passwords. If you use multi-table inheritance, then your Profile model would have to handle this as well. By using a one-to-one field, the custom admins can handle the user fields, and your Profile model admins only have to handle the additional profile fields.
Another option is creating a custom user model. In this case you subclass an abstract class AbstractUser or AbstractBaseUser instead of the class User. If your Profile class works, then I would recommend this instead of the custom user model, because custom user models are more complicated to set up.
Related
I've seen two ways of extending the User model in Django.
Method 1:
class User(AuthUser):
new fields...
Method 2:
class MyUser(models.Model):
user = models.OneToOneField(User)
new fields...
What is the difference between them?
The first one is multi table inheritance. (I presume you are actually speacking of django.contrib.auth.models.User here). Your new User model will have all the field that are defined in django's user model. This is managed by django implicitly creating a OneToOneField on your model.
The second, one you are creating the OneToOneField yourself. Now the django.contrib.auth.model.User model's fields do not automatically appear as parts of your own model. YOu can still access them as
myinstance.user.parent_field
Having said all this, for option 1 you should inherit from an abstract base class rather than directly from the User model.
class MyUser(AbstractBaseUser):
...
I have different apps in my django project. I want to keep an independent app for auth&auth that is reused in all apps. The auth&auth app is one app with my basic custom user model. This user needs to log in with email so I am inheriting from AbstractBaseUser instead of extending the User class. Now in all apps the login is same way, basic user attributes are same; but some apps add additional fields like 'salary', others use the model as is. So what is the best way to reuse the Custom User model I created in my login app? If I inherit the concrete class, I'll have 2 tables. If I declare the Custom User class abstract, how will I use its functionalities, roles and permissions?
I think the best way to achieve what you are asking for is:
class Learners(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, unique=True)
nick = models.CharField(max_length=12, unique=True)
#Many to Many relationship with course
courses = models.ManyToManyField(Course, blank=True)
def __str__(self):
return self.user.get_full_name()
Where the AUTH_USER_MODEL is set to the Custom User model, inheriting from AbstractBaseUser, that you created, like this : AUTH_USER_MODEL = 'courseSystem.MyUser' in settings.py for the main Django project. In my example courseSystem.MyUser is the Custom User Class defined.
I am sharing this from a similar situation you have described above, that I am working on.
In the above example, if you were to make the custom MyUser class as abstract and then inherit the Learners class from it:
class Learners(MyUser):
then Learners class would no longer be a models.Model type class but the concrete User class for that app, and in each case i.e., for each such class ineheriting from the abstract MyUser class, you would have to overload the necessary members of MyUser required for a concrete user class for Django. Also since you are using AbstractBaseUser and not extending on default User class, you would have to define custom User forms, and User Managers for your custom user class. So if you have a concrete MyUser class, as in the example above, you can define the custom User Manager and User Forms for MyUser once, and keep one-to-one relationship to it from your models in different apps. But if you make the MyUser class as abstract, you wouldn't define User Forms and User Managers for MyUser, but separately for each of your apps where you form a concrete user class by inheriting from this abstract Custom User class.
https://docs.djangoproject.com/en/1.9/topics/auth/customizing/
I want to implement users in my system. I know that Django already has an authentication system, and I've been reading the documentation. But I don't know yet the difference between
from django.contrib.auth.models import User
class Profile(User):
# others fields
And
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User)
# others fields
I don't want to know why to use one or another, but what happens under the hoods. What's the difference?
Your first example is multi-table inheritance.
class Profile(User):
If you have a profile, you can access all the fields on the user model directly (e.g. profile.username and profile.email). In this case, Django creates a OneToOneField for you automatically.
The second example is a regular OneToOneField.
class Profile(models.Model):
user = models.OneToOneField(User)
In this case, you cannot access profile.username and profile.email. Instead, you access these fields via the one to one field (e.g. profile.user.username and profile.user.email).
In your case, where you are adding a profile model, I would avoid using inheritance, and use a one to one field instead. The User model has custom admins to handle passwords. If you use multi-table inheritance, then your Profile model would have to handle this as well. By using a one-to-one field, the custom admins can handle the user fields, and your Profile model admins only have to handle the additional profile fields.
Another option is creating a custom user model. In this case you subclass an abstract class AbstractUser or AbstractBaseUser instead of the class User. If your Profile class works, then I would recommend this instead of the custom user model, because custom user models are more complicated to set up.
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 have a question about django's user inheritance.
I have gone through docs of django where I have seen inheritence of User model if I want to register the user through email and password.
My questions :
What will be the difference on default User model and Custom User model that I will make ?
Can I use the permissions and add group in the Custom User model ?
And also what if I want to inherit django's default User in my model ?
class Person(User):
address = models.CharField(max_length=100)
def __unicode__(self):
return self.address
Here the user model is django's default User model ?
Can I inherit like that ?
based on django specifying a custom user model
The easiest way to construct a compliant custom User model is to inherit from AbstractBaseUser. AbstractBaseUser provides the core implementation of a User model, including hashed passwords and tokenized password resets.
Alse Extending the existing User model can be a good option.