Trying to add custom fields to users in Django - python

I am fairly new to django and was it was going well until this.
i'm trying to add fields 'address' and 'phone_number' to users (create custom user basically) but i keep getting this error like this...
File "C:\Users\will5\Desktop\City\city_info\forms.py", line 5, in <module>
class UserForm(forms.ModelForm):
File "C:\Users\will5\AppData\Local\Programs\Python\Python36-32\lib\site-
packages\django\forms\models.py", line 257, in __new__
raise FieldError(message)
django.core.exceptions.FieldError: Unknown field(s) (phone_number, address)
specified for User
this is models
...
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
phone_number = models.IntegerField(default=0)
address = models.CharField(max_length=150)
...
this is in my forms
from django.contrib.auth.models import User
from django import forms
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = ['username', 'email', 'password', 'address', 'phone_number']
I also read that in order to fix this problem i will have to restart my project by creating the custom user and migrating and i don't wanna do that.

The problem is that you are still importing the built in user model
You can fix it by replacing
from django.contrib.auth.models import User
with
from django.contrib.auth import get_user_model
User = get_user_model()
This assumes that you have set AUTH_USER_MODEL = 'yourapp.User' in your settings.
As you have read in the docs, it is extremely difficult to switch to a custom user model after the project has started, there isn't an easy solution to this. If you can't restart your project, perhaps you could create a Profile model with a OneToOneField to the default User instead.

Related

Django: use a Foreignkey relationship for custom user model

I am writing a webapp where I want to have a general Person table to uniquely identify any person interacting with the website, e.g. to be able to comply to GDPR requests.
Some Persons will should also be Users in the authentication sense.
I'd like to use Person.email for the username.
However, I cannot manage to make authentication / admin interface work.
Simplified models:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
class Person(models.Model):
name = models.CharField(max_length=255, blank=False)
email = models.EmailField(blank=False, unique=True)
class User(AbstractBaseUser, PermissionsMixin):
person = models.OneToOneField(Person, on_delete=models.PROTECT)
USERNAME_FIELD = ...# what to put here?
I found a very old Django issue that seems related:
https://code.djangoproject.com/ticket/21832
Any idea, how to make this work with a foreign key to hold the basic user information?
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
Here you go for correct way of achieving this
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
USERNAME_FIELD = ['email'] # It's mean you can login with your email
class Person(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
Note: If you use AbstractBaseUser models, then you have to write custom model manager.
To avoid writing custom models manager, you should use AbstractUser
class User(AbstractUser):
pass
# here all the required fields like email, name etc item
You can create Person record for the user when a user records creating using django signal:
https://docs.djangoproject.com/en/3.2/topics/signals/

model = User in Meta class of django

I am trying to read a code that concerns about user registration form. The code has a Meta class which I know what it does, but assigning model to User doesn't give sense to me. Can you please explain it?
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User # explain?
fields = ["username", "email", "password1", "password2"]
Django relies on Inner Classes to provide metadata, Your UserRegisterForm needs to know when you call UserRegisterForm.save() what database table to send this form data to.
This is why you need model = User inside your Meta class, so the form knows where to go about storing.

django.core.exceptions.FieldError: Unknown field(s) (email) specified for Profile

I am trying to customize djoser's createuser end point. For that I have installed django custom user following this link https://github.com/jcugat/django-custom-user. Here is my models.py
from django.db import models
from custom_user.models import AbstractBaseUser
class Profile(AbstractBaseUser):
account_address = models.CharField(max_length=30, blank=True)
and serializers.py
from djoser.serializers import UserCreateSerializer as BaseUserRegistrationSerializer
class UserRegistrationSerializer(BaseUserRegistrationSerializer):
class Meta(BaseUserRegistrationSerializer.Meta):
fields = ('url', 'id', 'email', 'first_name', 'account_address', 'password')
and in app.admin.py i have registered it in following way.
from django.contrib import admin
from custom_user.admin import UserAdmin
from .models import Profile
class MyCustomEmailUserAdmin(UserAdmin):
"""
You can customize the interface of your model here.
"""
pass
# Register your models here.
admin.site.register(Profile, UserAdmin)
but when I am trying to makemigrations i am running into following error.
any clue what's wrong here?
From the looks of it, you seem to have the following in your settings:
AUTH_USER_MODEL = "your_app.Profile"
And for your profile model, you are inheriting from AbstractBaseUser which is actually from from django.contrib.auth.models import AbstractBaseUser.
I believe you meant to inherit from AbstractEmailUser. Thus, your "Profile" model would actually need be:
from custom_user.models import AbstractEmailUser
class Profile(AbstractEmailUser):
account_address = models.CharField(max_length=30, blank=True)

How to update a user profile field using rest API

I am new to django and very confused. I am using django as the backend API for my angular application.
I want to add few more details to the User model so I added the following to my models.py
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User)
company_name = models.CharField(max_length=100)
I am using an application to add rest authentication support: https://github.com/Tivix/django-rest-auth
Using this application I can edit a users profile with this URL doing a POST request: http://localhost:8080/rest-auth/user/
Question
How can I update the custom field company_name? while editing a users profile?
What I've tried
I tried to override the UserDetailsSerializer that the application provides but it isn't having any effect.
This is what I tried adding to my applications serializers.py
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = models.UserProfile
fields = ('company_name',)
class UserDetailsSerializer(serializers.ModelSerializer):
profile = UserProfileSerializer(required=True)
class Meta:
model = models.User
fields = ('id', 'username', 'first_name', 'last_name', 'profile')
If you are using django rest framework, then you basically want to have an update method on your view class for UserProfile that takes in the user id as a request param. Then in that method you want to use the ORM to get a model object for the given userprofile id, set the property that was also passed as a param, and save the changed model object. Then generate a success response and return it.
You can read more about how to do this here: http://www.django-rest-framework.org/api-guide/views/

Django: how to including inline model fields in the list_display?

I'm attempting to extend django's contrib.auth User model, using an inline 'Profile' model to include extra fields.
from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
class Profile(models.Model):
user = models.ForeignKey(User, unique=True, related_name='profile')
avatar = '/images/avatar.png'
nickname = 'Renz'
class UserProfileInline(admin.StackedInline):
model = Profile
class UserProfileAdmin(UserAdmin):
inlines = (UserProfileInline,)
admin.site.unregister(User)
admin.site.register(User, UserProfileAdmin)
This works just fine for the admin 'Change User' page, but I can't find a way to add inline model fields in the list_display. Just specifying the names of Profile fields in list_display give me an error:
UserProfileAdmin.list_display[4], 'avatar' is not a callable or an attribute of 'UserProfileAdmin' or found in the model 'User'.
I can create a callable which looks up the user in the Profile table and returns the relevant field, but this leaves me without the ability to sort the list view by the inline fields, which I really need to be able to do.
Any suggestions?
You've mentioned the only solution - creating a callable. There's currently no other way to do it, and yes this does mean you can't sort by that column.

Categories