how to extend model User? - python

please help to solve this problem
I expanded in django1.6 User model as follows:
class UserProfile(User):
......
......
family = models.CharField(
max_length=30,
blank=True,
)
skype = models.CharField(
max_length=50,
blank=False,
)
email_address = models.EmailField(
max_length=50,
blank=True,
)
.....
....
objects = UserManager()
resulting in adminpanel appeared a form with the above fields. after filling the data is stored in the database table "app_userprofile". This table is linked to the table "auth_user" using the foreign key.
the problem is that the table "auth_user" fields "username" and "password" empty . but each user needed.
please tell me how to do so after the new user registration ( of the admin panel and from the site ) data "username" and "password" fell into the table "auth_user"

I think you need to use AbstractUser model. If you inherit UserProfile from User model you will get 2 tables with same fields, and when you fill app.UserProfile password field - value doesn`t appear in auth.User table.
Of course you can do like this: https://stackoverflow.com/a/23390975/1761844 but better way - create your own custom user:
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
... your custom fields ...
and add to your settings.py
AUTH_USER_MODEL = 'app.CustomUser'
after this you will get user model with your custom fields. You can import it in your apps like this:
from django.contrib.auth import get_user_model
User = get_user_model()
and make foreign keys like this:
owner = models.OneToOneField(settings.AUTH_USER_MODEL)
Link to django documentation: https://docs.djangoproject.com/en/dev/topics/auth/customizing/#extending-django-s-default-user

Use a one to one field, User.profile will create the Profile object the first time user.profile it is accessed:
from django.contrib.auth.models import User
from django.db import models
class Profile(models.Model):
user = models.OneToOneField(User, unique=True)
User.profile = property(lambda u: Profile.objects.get_or_create(user=u)[0])

First, change UserProfile, like it was mentioned in the previous answer. After that, check this answer: https://stackoverflow.com/a/4565957 as it explains how to combine user and user profile forms on a single admin page. Then you will be able to add both user and his/her profile with a single save.
There is also other way to solve your problem: you can define a custom user model with all the fields you need, combining username, password, family and other data in a single table. Check out this page for reference: https://docs.djangoproject.com/en/1.6/topics/auth/customizing/#specifying-a-custom-user-model.

Related

How can I utilise the built in first and last name features of the Django User Model?

So I know that Django has a built in system with the User, and it contains things like Username, e-mail, password, and first and last name. I want to know how I can utilise this in my site.
So I have a first_name and last_name field in the models.py file, and they are CharFields. I want to know how to connect them to the already existing UserForm that comes with Django.
I have tried a few things already, such as doing this with the models.py file.
class UserProfileInfo(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
first_name = models.OneToOneField(User, on_delete=models.CASCADE)
Here is some code for the form.py file.
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta():
model = User
fields = ('username','email','password','first_name')
As you can see from the form, I added the first_name attribute, and in the models.py file, I have the first_name connected with the forms.py one. I am now getting this error.
HINT: Add or change a related_name argument to the definition for 'UserProfileInfo.user' or 'UserProfileInfo.first_name'.
So I added a related name field to the model, as shown here
first_name = models.OneToOneField(User, on_delete=models.CASCADE,related_name='first_name')
But, wouldn't you know it, I got yet another error:
ValueError: Cannot assign "''": "User.first_name" must be a "UserProfileInfo" instance.
I don't really know what is going on here.
So I expected to get no errors, just like the user field. Instead I got this error. Any help would be greatly appreciated :)
Your code is setting a OneToOne to the User model for both the user and first_name fields. So this means the related field will be User.id for both.
To specify that you want UserProfileInfo.first_name to map to User.first_name you will need to set to_field=first_name
class UserProfileInfo(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
first_name = models.OneToOneField(User, on_delete=models.CASCADE, to_field='first_name', related_name='user_profile_first_name')
However, this will still cause an issue as you can only set a OneToOne relationship to a unique field. As User.first_name is not unique, you cannot set a OneToOne relationship to it.
If both the OneToOne relationships are referencing the same object, one of the relationships is redundant as you can access the fields on that object through the other relationship. It would be better to have a method on UserProfileInfo that gets the first name through the user field.
class UserProfileInfo(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
def get_first_name(self):
return user.first_name
You will also need to set signals to create/update UserProfileInfo when User is created/updated. Have a look at this article.
There are also other ways to extend the User model in Django. Have a look at this article or this answer for suggestions.
But if you're not adding any extra fields to the User model, it may be better just to use it directly.

Do i need to update AUTH_USER_MODEL in my settings.py?

I am creating my own users, Restaurant and Customer. I have extended the AbstractUser class and then created a OneToOneField field for each user. I am wondering if I need to add the AUTH_USER_MODEL in my settings.py. And also wondering what that does exactly...
What I was planning on doing was adding to my settings.py:
AUTH_USER_MODEL = 'myapp.Customer','myapp.Restaurant'
Do I have the right idea here?
My models.py:
class User(AbstractUser):
is_restaurant = models.BooleanField(default=False)
is_customer = models.BooleanField(default=False)
class Restaurant(models.Model):
user = models.OneToOneField(User, primary_key=True, on_delete=models.CASCADE)
restaurant_name = models.CharField(max_length=50)
def __str__(self):
return self.restaurant_name
class Customer(models.Model):
user = models.OneToOneField(User, primary_key=True, on_delete=models.CASCADE)
address = models.CharField(max_length=200)
def __str__(self):
return self.user.get_full_name()
No. AUTH_USER_MODEL isn't expecting a tuple, so this won't work.
In any case, Restaurant and Customer are not your user model; your subclassed User is. That's what you should be putting in that setting.
I would suggest create single user table instead of three different tables and add type as restaurant, customer, admin etc. And add only one table into settings file. this won't lead any further issues authentication etc. Having single user table is always robust. In your case having three tables seems not good to maintain.
========== UPDATE ===========
Create model for user named as CustomUser (or name which you feel better) and extends to User Model of Django using AbstractBaseUser,PermissionsMixin. like
class CustomUser(AbstractBaseUser): have all fields which user table has already. and add your desired table to bifurcate type of restaurant and
customer have type field with choices option.
For further help you can check section https://docs.djangoproject.com/en/1.11/topics/auth/customizing/#substituting-a-custom-user-model

Django is failing to save data related to User table. It says it doesn't have `mymodel_set` attribute

I have a model linked to Django User model but when I try saving to that model using User instance, it says 'User' object has no attribute 'mymodel_set'
My models.py:
from django.contrib.auth.models import User
from django.db import models
class MyModel(models.Model):
user = models.OneToOneField(User, blank=True, null=True, related_name='mymodel')
name = models.CharField(max_length=14, blank=True, null=True)
My views.py:
from django.contrib.auth.models import User
from myapp.models import mymodel
def register(request):
#gets data here from template
user = User(username=reg_username, password=reg_password)
user.save()
user.mymodel_set.create(name= display_name)
return HttpResponse('Success')
If the related object existed, you would use mymodel, but it does not exist and the relationship is void, so it cannot be accessed via the user. Create it first and set the relationship to that user:
mymodel = MyModel.objects.create(name=display_name, user=user)
# ^^^^ set related user
The _set suffix is usually used for reverse ForeignKey relationships and not for OneToOne relationships.
Also note that the related_name on the user field was already specified as mymodel, and the related field can now be accessed from the User model via user.mymodel

Using Custom User DB Structure in Mysql for Django 1.8

I have a question regarding the table structure for User if I am extending its functionalities, using a MySQL database.
Given the models.py file
class LibraryUser(models.Model):
user_id = models.OneToOneField(User)
is_catalogue_subscriber = models.IntegerField(default=1)
is_research_subscriber = models.IntegerField(default=1)
library_membership_number = models.CharField(max_length=64)
I have a table structure for SQL
CREATE TABLE library_user(
user_id int(10) primary key
is_catalogue_subscriber integer(1) DEFAULT 1
is_research_subscriber = integer(1) DEFAULT 1
library_membership_number = varchar(16)
)
So now, when I fire up my server and access the accounts in the admin page, Django is throwing an error:
Exception Type: OperationalError
Exception Value:
(1054, "Unknown column 'library_user.id' in 'where clause'")
Use
user = models.OneToOneField(User, primary_key=True)
i.e. drop the _id in the attribute name.
In case you simply want to define a richer user model (i.e. add more attributes) 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 a LibraryUser model:
from django.contrib.auth.models import User
class LibraryUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
is_catalogue_subscriber = models.IntegerField(default=1)
is_research_subscriber = models.IntegerField(default=1)
library_membership_number = models.CharField(max_length=64)
Assuming an existing LibraryUser Fred Smith who has both a User and LibraryUser model, you can access the related information using Django’s standard related model conventions:
>>> u = User.objects.get(username='fsmith')
>>> freds_department = u.libraryuser.department
Then to add the profile model’s fields to the user page in the admin do
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from my_user_profile_app.models import LibraryUser
# Define an inline admin descriptor for Employee model
# which acts a bit like a singleton
class LibraryUserInline(admin.StackedInline):
model = LibraryUser
can_delete = False
verbose_name_plural = 'libraryuser'
# Define a new User admin
class UserAdmin(UserAdmin):
inlines = (LibraryUserInline, )
# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
All taken from the official docs
What you are missing is that by default django models automatically include an id field that maps to models.AutoField().
You need to specify that your DB table id is user_id instead of id.
https://docs.djangoproject.com/en/1.8/topics/db/models/#automatic-primary-key-fields
You want to make your user_id the primary key. It should work by adding primary_key=True to that field, like:
class LibraryUser(models.Model):
user_id = models.OneToOneField(User, primary_key=True)
is_catalogue_subscriber = models.IntegerField(default=1)
is_research_subscriber = models.IntegerField(default=1)
library_membership_number = models.CharField(max_length=64)

What is the best way to query for instances of django models with one to one relationships with users

Let's say you have a django model with a OneToOne / Unique ForeignKey relationship with a User, as show on the Django documentation on how to create a UserProfile.:
Now let's say you have a view method that takes a request you can get a user from. What is the best way to query for the profile associated with that user?
from django.contrib.auth.models import User
# sample user profile model associated with user
class UserProfile(models.Model):
likes_spam = models.BooleanField()
user = models.OneToOneField(User)
#view method
def forward_to_practice_home(request):
user = request.user
profile_for_user = #insert code here that would get the profile for that user
related_names are very helpful. If you change your user profile definition to:
class UserProfile(models.Model):
likes_spam = models.BooleanField()
user = models.OneToOneField(User, related_name='profile')
then you can use profile as follows:
def forward_to_practice_home(request):
user = request.user
profile_for_user = user.profile
UserProfile.objects.get(user=user)
You may use a special method called get_profile()
profile_for_user = user.get_profile()
Be reminded that you have to set the AUTH_PROFILE_MODULE in the settings.py
However, this is deprecated in Django 1.5 because it adds the support of user model customization

Categories

Resources