i finally can make my Django+Auth app works. I add the extra information to the user as the docs say. Now, i've a simple question. When i'm building a model that is related to the user, which user should i relate to? To auth.models.User or to my accounts.UserProfile?
An example: I've a model for Product, and the Product belongs to a user. Which would be the best option:
class Product(models.Model):
user = models.ForeignKey(auth.models.User)
or
class Product(models.Model):
user = models.ForeignKey(accounts.UserProfile)
I'm currently using auth.models.User, becouse i can issue a get_profile, but some friend told me that i was wrong.
Thank you!
You're doing the right thing.
UserProfile is just an extension of the User model.
And logically you're making a relation of a object with an object, not a relation of a object with some extra information.
Also, as you mentioned, you can always issue the 'get_profile' to get the extra data.
Related
I'd like to create a project for finding mentor.
In planning i thought, that it would be nice to separate two models on registration users: for students (those, who wants to find mentor) and mentors.
Built-in django user model isn't like that. I plan to add more fields, also several fields can be the same: in students and in mentors.
Can you give me live example of customing model? Would be nice, if you have smth in git or other code sharing.
Shoudl I inherit mentor model from students, because it can have same fields: email, name, surname, etc?
What additional code should i write for working custom model? I read docs and found unknown for me - managers. Should i also customize managers?
If i get success in custom model what problems can i meet in future for auth,registration, changing passwords for this custom model?
Creating 2 separate models is not recommended here. You will need to have separate login process and be careful to avoid problems with sharing pk between users in separate tables. Also I'm pretty sure that django won't allow that.
Better choice is to make 2 profile models, as described in Extending the existing User model. In one of profiles you will store specific data for student and in other specific data for mentors.
Your website has two intended users, so there is no problem with creating two user models. Just make sure to inherit them from user model
from django.contrib.auth.models import User
class Student(User):
...
class Mentor(User):
...
You shouldn't re-invent the wheel, except you really want to learn and practice core features of Django. Just add some add-on library like userena, which "supplies you with signup, signin, account editing, privacy settings and private messaging". In general userena gives an additional UserenaBaseProfile model which is connected to built-in User model. So you can just inherit this model for the Student and for the Mentor:
from django.contrib.auth.models import User
from userena.models import UserenaBaseProfile
class CustomProfile(UserenaBaseProfile):
user = models.OneToOneField(User, unique=True)
common_field_for_all_children = models.IntegerField()
class Meta:
abstract = True
class Student(CustomProfile):
something_student_related = models.IntegerField()
class Mentor(CustomProfile):
something_mentor_related = models.CharField(max_length=255)
So I have Auth and Profile implemented into my system however i'd like to extend the User model and I don't know what is considered the 'correct' way of doing this.
I just want to create a method that returns a link for the user like:
Username
I figured that this is probably best done using a method as the link will change and I don't want to be going through all my template files fixing this.
This may be common to somebody using Django but I have not used it much so I am not well versed in the conventions so any advice would be great
If you're not altering what is stored in the database, the easiest way is a proxy model. Here's an example straight out of the documentation (https://docs.djangoproject.com/en/dev/topics/db/models/#proxy-models)
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
class MyPerson(Person):
class Meta:
proxy = True
def do_something(self):
# ...
pass
If you want to do something more complex than adding methods to the User model, such as adding new data fields, I would recommend creating a Model with a one-to-one relation to User.
The normal way to create URLs in Django without needing to worry about changing them is to use the {% url %} tag. See the documentation on reversing URLs.
I know you are asking specifically for extending the user model but have you considered creating a template tag to generate the link instead?
If you only need the method in the templates than that's definitely the way to go.
In Django you have some naturally defined User class. My app also has a User class defined (they dont conflict, that's not the question)
My question is, since these two User classes conceptually represent the same thing (well, users) then it would be natural to integrate them. That is, have a single User class that contains all methods and variables of both classes.
What is the best way to achieve this?
There are (at least) two possibilities:
1) Use the 'custom user' functionality of Django (since Django 1.5), or
2) Use a OneToOneField to the django.contrib.auth User from your own user class.
The first allows you to customize more, but you might get some problems if you try to use third-party-apps that are either not ready for custom users or need specific properties of the stock User. For example, Django Guardian doesn't work if you remove the User-Group relationship.
The second is less intrusive, but doesn't allow you to customize the existing fields of User. Also, you need to manually create the instance of your own user class at registration time.
You should read the documentation about Extending the existing User model.
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. For example you might create an Employee (note: called MyUser below) model:
from django.contrib.auth.models import User
class MyUser(models.Model):
user = models.OneToOneField(User)
newfield1 = models.CharField(...)
AUTH_USER_MODEL = 'myapp.MyUser'
Django 1.5+ allows us to add custom fields to a User. I want to use this fact, but I don't necessarily know what is good practice. Here is a situation I am confused on how to handle the models.
Given the option to add fields to User, if a project only has one type of User, lets say a Student model, can I simply add student-specific fields to User? I am new to Django, but I believe the alternative would be to set up general User settings, and create a Student model, and a one-to-one unique field in it call user.
Should you ever expand a Django User's fields to mimic that of a model, even if the project is guaranteed only to have one type of user?
If you only have one type of user and are using Django 1.5+, I would recommend taking advantage of the new AbstractUser. Extending Django's default user
As an example where you want to add date of birth and favorite color:
#myusers/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class MyUser(AbstractUser):
dob = models.DateField()
favorite_color = models.CharField(max_length=32, default='Blue')
If you need more flexibility you can extend the AbstractBaseUser instead of AbstractUser, but for most basic cases you should only need AbstractUser.
Also note that in either case, you'll need to reference your user model by using settings.AUTH_USER_MODEL.
Using out example above and assuming the app it was defined in is called myusers:
#settings.py
AUTH_USER_MODEL = 'myusers.MyUser'
The method you mention of creating a Student model with a one-to-one field to the User model still works, but is not as clean (there are still cases where it makes sense if you have multiple kinds of users).
I don't normally like to reference books in answers, but I found that Two Scoops of Django's, Chapter 16 on the User model gave a much clearer explanation of where the different options are appropriate than the current version of the online Django docs. The book is overall a very useful intro to Django and was written based on 1.5. You'd have to buy the book or find someone who has it, though... (FYI: I don't get any money recommending this).
You could also take a look at this SO question/answer: https://stackoverflow.com/a/14104748/307293
You shouldn't touch the django contributed User model (from the authentication framework). This will break upgrades and you do not know what other consequences it might have.
There are two basic ways to do this:
If you just need to store additional information about a user, but don't need to change how the authentication/authorization mechanism works, create a model and add a OneToOneField to the User model. In this model, store any other miscellaneous information.
If you want to change how authentication works you can create your own User model and have django use that (1.5+ only).
I've read a few posts on inheritance of the User model for other models in Django, but I want a user to have a particular parent user, i.e. the User model inherits itself.
I'm not sure how to do this as I'd surely have to edit the django.auth.contrib model for User wouldn't I?
Thanks in advance for any tips.
Firstly, don't edit the source code in Django. That's a big mistake it'll make your code horrible to maintain - Whatever you're trying to do, you really don't want to change the Django source.
I'm not completely clear what you're asking, but it sound like you might need to create a new model that inherits from User and add a ManyToMany field to self on your model.
from django.contrib.auth.models import User
class ExtendedUser(User):
parent = models.ManyToManyField("self", symmetrical=False)
Your new model will now have all the fields and methods of Django's User class plus your extra parent field. The parent field on any particular ExtendedUser object will reference another ExtendedUser object.
As I say I'm taking a guess at what it is you're trying to do (If I've got it right, then you might find it helpful to do a bit of reading on model inheritance and class inheritance in general - maybe seek out a few tutorials on the subject too)