Add more field in SignupForm using django-allauth - django

Models:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(max_length=500, blank=True)
nationality = models.CharField(max_length=20)
def __str__(self):
return self.user.first_name
#receiver(post_save, sender=User)
def create_user_profile(self, sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_profile(self, sender, instance, **kwargs):
instance.profile.save()
Forms:
from allauth.account.forms import SignupForm
class CustomSignupForm(SignupForm):
first_name = forms.CharField(max_length=100)
last_name = forms.CharField(max_length=100)
class Meta:
model = Profile
fields = ('first_name', 'last_name', 'nationality', 'bio')
def signup(self, request, user):
# Save your user
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.save()
user.profile.nationality = self.cleaned_data['nationality']
user.profile.gender = self.cleaned_data['bio']
user.profile.save()
Views:
ACCOUNT_FORMS = {'signup': 'myproject.forms.CustomSignupForm',}
This process isn't work. Error is: Model class all_auth.models.Profile doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.
How can I solve it? Or, How can i add more field with SignupForm using django-allauth?

Create an application, such as accounts and it has this code, but you need to create a database only after creating this code, it is more accurate to perform the first migration in the project
accounts/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
phone = models.CharField(max_length=12)
accounts/forms.py
from allauth.account.forms import SignupForm
from django import forms
from .models import *
class SimpleSignupForm(SignupForm):
phone = forms.CharField(max_length=12, label='Телефон')
def save(self, request):
user = super(SimpleSignupForm, self).save(request)
user.phone = self.cleaned_data['phone']
user.save()
return user
settings.py
...
ACCOUNT_FORMS = {'signup': 'accounts.forms.SimpleSignupForm'}
AUTH_USER_MODEL = 'accounts.CustomUser'
accounts/admin.py
from django.contrib import admin
from .models import *
admin.site.register(CustomUser)

Related

Exception Value: 'CustomUser' object is not callable | CustomUserModel

I am trying to create a custom user model. The model is working fine in command prompt and I am able to login to admin panel as well. I can access Login page as well. But when I try to access the SignUp page Is is showing me the following error.
Error image
models.py
from django.db import models
from django.contrib import auth
from django.urls import reverse
# Create your models here.
# for custom user
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, User
from .managers import CustomUserManager
class CustomUser(AbstractBaseUser, PermissionsMixin):
'''Model representation for user'''
user_type_choices = (
('ps','problem_solver'),
('pp','problem_provider')
)
account_type_choices = (
('o','Organization'),
('i','Individual')
)
user_type = models.CharField(max_length=5, choices=user_type_choices, default='pp', verbose_name="Who you are? ")
account_type = models.CharField(max_length=5, choices= account_type_choices, default='o', verbose_name="Account Type ")
email = models.EmailField(max_length=50, unique=True, blank=False, verbose_name="Your Email ")
is_active = models.BooleanField(default=True) # anyone who signs up for thsi application is by default an active user
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False) # the person who has highest level of control over database
# need to specify manager class for this user
objects = CustomUserManager()
# we are not placing password field here because the password field will always be required
REQUIRED_FIELDS = ['user_type', 'account_type']
USERNAME_FIELD = 'email'
EMAIL_FIELD = 'email'
# class User(User, PermissionsMixin): # for username and password
# def __str__(self):
# return "#{}".format(self.username)
# def get_absolute_url(self):
# return reverse("Solver_detail", kwargs={"pk": self.pk})
views.py
from django.shortcuts import render
from django.urls import reverse_lazy
from . import forms
from django.views.generic import CreateView
from .managers import CustomUserManager
# Create your views here.
class SignUpView(CreateView):
form_class = forms.SignUpForm
success_url = reverse_lazy('login')
template_name = 'accounts/signup.html'
managers.py
from django.contrib.auth.models import BaseUserManager
# from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
class CustomUserManager(BaseUserManager):
def create_user(self, user_type, account_type, email, password):
if not email:
raise ValueError('User must provide valis email address')
if not password:
raise ValueError('User must provide password')
user = self.model(
user_type = user_type,
account_type = account_type,
email = self.normalize_email(email=email) # it normalizes the email for storage
)
user.set_password(raw_password = password) # it hashes password before setting it up into the database
user.save(using = self._db)
return user
def create_superuser(self, user_type, account_type, email, password):
user = self.create_user(
user_type= user_type,
account_type= account_type,
email=email,
password= password
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using = self._db)
return user
forms.py
# from django.contrib.auth import get_user_model
from accounts.models import CustomUser
from django.contrib.auth.forms import UserCreationForm
class SignUpForm(UserCreationForm):
class Meta:
fields = ('user_type','account_type','email', 'password1', 'password2')
model = CustomUser()
# def __init__(self, *args, **kwargs) -> None:
# super().__init__(*args, **kwargs)
admin.py
from django.contrib import admin
from accounts.models import CustomUser
# Register your models here.
admin.site.register(CustomUser)
I am newbie to django developement. Please help me out.
I am expecting to know how to resolve this kind of error
your wrong in file:
class SignUpForm(UserCreationForm):
class Meta:
fields = ('user_type','account_type','email', 'password1', 'password2')
model = CustomUser()
Fix to
class SignUpForm(forms.ModelForm):
class Meta:
fields = ('user_type','account_type','email', 'password1', 'password2')
model = CustomUser
Because model required one MODEL, you write CustomUser() mean callable object. Model CustomUser can't do it and raise exception

Cannot assign "<User: someuser>": "UserProfileInfo.user" must be a "User" instance

[enter image description here][1]I don't know what is causing this error but i couldn't find any solution for this. i checked everything and everything seems to be fine but i don't know why this error is occuring.
Views.py
from django.contrib.auth import get_user_model
from django.shortcuts import render
from django.urls import reverse_lazy
from django.views.generic import CreateView,FormView
from . import forms
# Create your views here.
def signup(request):
if request.method =='POST':
user_create_form = forms.UserCreateForm(data=request.POST)
user_profile_form = forms.UserProfileInfoForm(data=request.POST)
if user_create_form.is_valid() and user_profile_form.is_valid():
user = user_create_form.save()
user.save()
profile = user_profile_form.save(commit=False)
profile.user = user
if 'profile_pic' in request.FILES:
profile.profile_pic = request.FILES['profile_pic']
profile.save()
else:
print(user_create_form.errors,user_profile_form.errors)
else:
user_create_form = forms.UserCreateForm()
user_profile_form = forms.UserProfileInfoForm()
return render(request,'accounts/signup.html',{'user_create_form':user_create_form,
'user_profile_form':user_profile_form})
Models.py
from django.db import models
from django.contrib import auth
# Create your models here.
class User(auth.models.User,auth.models.PermissionsMixin):
def __str__(self):
return "#{}".format(self.username)
class UserProfileInfo(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE)
Contact_number = models.IntegerField(blank=True)
joined_at = models.DateTimeField(auto_now=True)
profile_pic = models.ImageField(upload_to='profiles',blank=True)
def __str__(self):
return self.user.username + ' Profile'
Forms.py
from django.contrib.auth import get_user_model # this gets the model that is in the application
from django import forms
from django.contrib.auth.forms import UserCreationForm
from . import models
class UserCreateForm(UserCreationForm):
class Meta():
fields = ('username','email','password1','password2',)
model = get_user_model()
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
self.fields['username'].label = 'Display Name' # to set up a custom label for the field
self.fields['email'].label = "Email Address"
class UserProfileInfoForm(forms.ModelForm):
class Meta():
model = models.UserProfileInfo
fields = ('Contact_number','profile_pic')
I am getting this error no matter what i do, i tried referencing other similar questions but couldn't find any solution for this error. pls help me out on this one.
Thanks in Advance !
image of the error
[1]: https://i.stack.imgur.com/HOcmf.png
You can overwrite save() method in your model to return a model instance after saving an object, for example:
class YourModel(models.Model):
name = models.CharField(max_length=20)
def save(self, *args, **kwargs):
super(YourModel, self).save(*args, **kwargs)
return self
your_model_saved_instance = YourModel(name='example').save()
Then you will receive an instance from the user class instead of the form class
user = user.save()

Django Admin is not allowing me to change any user settings after implementing a AbstractUser

Following a video on Youtube I want to creat a website with different Roles for students and teachers. I also would like to save off the School ID in to the user.
Here is what I want to change but when I hit save it does nothing.
I've tried creating custom forms to use for the create and change but it doesn't seem to matter. I feel like I missed typed something in the model.py or I'm missing something. Creating users works like a charm so that's why I'm confused why it wouldn't update a user correctly. I have done a fully custom user class before but shouldn't need to for this simple of change.
In the setting is have this line
AUTH_USER_MODEL = "account_app.User"
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser, BaseUserManager
from django.db.models.signals import post_save
from django.dispatch import receiver
class School(models.Model):
name = models.CharField('School Name', max_length=240)
address1 = models.CharField('Address 1', max_length=240)
address2 = models.CharField('Address 2', max_length=240)
city = models.CharField('City', max_length=240)
district = models.CharField('District', max_length=240)
state = models.CharField('State', max_length=2)
zip_code = models.IntegerField('Zip Code')
country =models.CharField('Country', max_length=240)
phone = models.IntegerField('School Phone Number')
time_zone = models.CharField(max_length=50)
def __str__(self):
return f'{self.name}'
class User(AbstractUser):
class Role(models.TextChoices):
ADMIN = "ADMIN", "Admin"
STUDENT = "STUDENT", "Student"
TEACHER = "TEACHER", "Teacher"
base_role = Role.ADMIN
role = models.CharField(max_length=50, choices=Role.choices)
school_id = models.ForeignKey(School,blank=True, null=True, on_delete=models.DO_NOTHING)
def save(self, *args, **kwargs):
if not self.pk:
self.role = self.base_role
return super().save(*args, **kwargs)
class StudentManager(BaseUserManager):
def get_queryset(self, *args, **kwargs):
results = super().get_queryset(*args, **kwargs)
return results.filter(role=User.Role.STUDENT)
class Student(User):
base_role = User.Role.STUDENT
student = StudentManager()
class Meta:
proxy = True
def save(self, *args, **kwargs):
if not self.pk:
self.role = User.role.STUDENT
return super().save(*args, **kwargs)
def welcome(self):
return "Only for students"
class TeacherManager(BaseUserManager):
def get_queryset(self, *args, **kwargs):
results = super().get_queryset(*args, **kwargs)
return results.filter(role=User.Role.TEACHER)
class Teacher(User):
base_role = User.Role.TEACHER
teacher = TeacherManager()
class Meta:
proxy = True
def save(self, *args, **kwargs):
if not self.pk:
self.role = User.role.TEACHER
return super().save(*args, **kwargs)
def welcome(self):
return "Only for teachers"
this is the admin.py
from django.contrib import admin
from .models import User
from .models import Student
from .models import Teacher
admin.site.register(User)
admin.site.register(Teacher)
admin.site.register(Student)
EDIT - Honestly have no clue how I fixed it but I did change my files
admin.py
from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin as AuthUserAdmin
from .forms import UserCreationForm
from .models import School
from .models import UserProfile
"""
*** Used to create users in the Admin
if you didn't do this it would use the default account in django.
"""
class UserCreateForm(UserCreationForm):
class Meta:
model = UserProfile
fields = ('email','first_name')
class AccountsUserAdmin(AuthUserAdmin):
# Displays accounts better on the view
list_display = ('id','username','email', 'first_name', 'last_name', 'role','is_staff')
# Used to search people at top of view
search_fields = ('username','last_name','email')
filter_horizontal = ()
list_filter = ()
add_form: UserCreateForm
## Viewing an and changing existing user
fieldsets = (
(None, {'fields': ('username','password')}),
(('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
(('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser',
'groups', 'user_permissions')}),
(('Important dates'), {'fields': ('last_login', 'date_joined')}),
(('Additional info'), {'fields': ('role', 'school_id')}),
)
## Adding a new User
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('username','first_name','last_name','email','role','school_id','password1','password2'),}),)
admin.site.register(UserProfile, AccountsUserAdmin)
admin.site.register(School)
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django.contrib.auth.models import User
from .models import UserProfile, School
class RegisterUserForm(UserCreationForm):
ROLE_CHOICES =(
("ADMIN", "Admin"),
("STUDENT", "Student"),
("TEACHER", "Teacher"),)
role = forms.ChoiceField(choices=ROLE_CHOICES, required=True)
school_id = forms.ModelChoiceField(queryset=School.objects.all(), required=False)
class Meta:
model = User
fields = ('username', 'first_name', 'last_name','email', 'role' , 'school_id' , 'password1', 'password2')
class UserChangeForm(UserChangeForm):
class Meta(UserChangeForm.Meta):
model = User
fields = '__all__'
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.dispatch import receiver
from django.db.models.signals import post_save
class School(models.Model):
name = models.CharField('School Name', max_length=240)
address1 = models.CharField('Address 1', max_length=240)
address2 = models.CharField('Address 2', max_length=240)
city = models.CharField('City', max_length=240)
district = models.CharField('District', max_length=240)
state = models.CharField('State', max_length=2)
zip_code = models.IntegerField('Zip Code')
country =models.CharField('Country', max_length=240)
phone = models.IntegerField('School Phone Number')
time_zone = models.CharField(max_length=50)
def __str__(self):
return f'{self.name}'
class UserProfile(AbstractUser):
class Role(models.TextChoices):
ADMIN = "ADMIN", "Admin"
STUDENT = "STUDENT", "Student"
TEACHER = "TEACHER", "Teacher"
role = models.CharField(max_length=50, choices=Role.choices, blank=True, null=True)
school_id = models.ForeignKey(School,blank=True, null=True, on_delete=models.DO_NOTHING)
class UserProfileManagerTeachers(models.Manager):
def get_queryset(self):
return super(UserProfile, self).get_queryset().filter(role="TEACHER")
class UserProfileManagerStudents(models.Manager):
def get_queryset(self):
return super(UserProfile, self).get_queryset().filter(role="STUDENT")
It seems that you changed the default permissions for the Abstracted User Class, So you can try this way to add custom permission for each Model, For ex.:
from django.contrib import admin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
#admin.register(User)
class CustomUserAdmin(UserAdmin):
def has_change_permission(self, request, obj=None):
return True
def has_delete_permission(self, request, obj=None):
return False
Here is the full documentation: Admin Panel Permissions Doc.

Django registration profile

I am new in django. I would like to create registration profile. I found some code but it doesn´t work for me. When I want to makemigrations I always get this error AttributeError: Manager isn't available; 'auth.User' has been swapped for 'user.User'
I read that I could fix it with User = get_user_model() but it looks it is doesn´t work for me.
My models.py
import random
from django.contrib.auth import get_user_model
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
User = get_user_model()
def code_generator(length=5):
numbers = '0123456789'
return ''.join(random.choice(numbers) for _ in range(length))
class RegistrationProfile(models.Model):
code = models.CharField(default=code_generator, max_length=5)
user = models.OneToOneField(to=User, on_delete=models.CASCADE, related_name='registration_profile', primary_key=True)
#receiver(post_save, sender=User)
def create_registration_profile(sender, instance, **kwargs):
profile, created = RegistrationProfile.objects.get_or_create(user=instance)
if created:
profile.save()
serializer.py
from rest_framework import serializers
from rest_framework.validators import UniqueValidator
from django.contrib.auth.password_validation import validate_password
from .models import User
class RegisterSerializer(serializers.ModelSerializer):
email = serializers.EmailField(
required=True,
validators=[UniqueValidator(queryset=User.objects.all())]
)
password = serializers.CharField(write_only=True, required=True, validators=[validate_password])
password2 = serializers.CharField(write_only=True, required=True)
class Meta:
model = User
fields = ('username', 'password', 'password2', 'email', 'first_name', 'last_name')
extra_kwargs = {
'first_name': {'required': True},
'last_name': {'required': True}
}
def validate(self, attrs):
if attrs['password'] != attrs['password2']:
raise serializers.ValidationError({"password": "Password fields didn't match."})
return attrs
def create(self, validated_data):
user = User.objects.create(
username=validated_data['username'],
email=validated_data['email'],
first_name=validated_data['first_name'],
last_name=validated_data['last_name']
)
user.set_password(validated_data['password'])
user.save()
return user
and views.py
from django.contrib.auth.models import User
from rest_framework import generics
from rest_framework.permissions import AllowAny
from .serializers import RegisterSerializer
class RegisterView(generics.CreateAPIView):
queryset = User.objects.all()
permission_classes = (AllowAny,)
serializer_class = RegisterSerializer
In the end I would like to send code to email for validation. Any ideas how I could do it by most effective way?
you can do this
from django.contrib.auth.models import User
class RegistrationProfile(models.Model):
code = models.CharField(default=code_generator, max_length=5)
user = models.ForeignKey(to=User, on_delete=models.CASCADE, related_name='registration_profile')
#receiver(post_save, sender=User)
def create_registration_profile(sender, instance, **kwargs):
profile, created = RegistrationProfile.objects.get_or_create(user=instance)
if created:
profile.save()

User Registeration Using Django Rest Framework

I am trying to create a api for user Registration using the django rest framework.
I have the following models.py file
from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE , primary_key = True)
mobileNumber = models.IntegerField(default=0)
avatar= models.ImageField(upload_to = 'User/' , default = '/static/User/defaultProfileImage.png')
def create_user_profile(sender, **kwargs):
if kwargs['created']:
profile = UserProfile.objects.create(user=kwargs['instance'])
post_save.connect(create_user_profile, sender=User)
This is my Serializers.py file
from rest_framework import serializers
from User.models import UserProfile
from django.contrib.auth.models import User
class UserSerializer(serializers.HyperlinkedModelSerializer):
username = serializers.CharField()
password1 = serializers.CharField(
style={'input_type': 'password'},
write_only=True)
password2 = serializers.CharField(
style={'input_type': 'password'},
write_only=True)
email = serializers.EmailField()
class Meta:
model = User
fields = (
'id',
'username',
'password1',
'password2',
'email',
'first_name',
'last_name',
)
class UserProfileSerializer(serializers.HyperlinkedModelSerializer):
user = UserSerializer()
class Meta:
model = UserProfile
fields = (
'user',
'mobileNumber',
'avatar')
And following is my views.py file
from User.models import UserProfile
from .serializers import UserProfileSerializer
from rest_framework.viewsets import ModelViewSet
class UserProfileViewSet(ModelViewSet):
queryset = UserProfile.objects.all()
serializer_class = UserProfileSerializer
What is the best way to create a User Registeration using the api view that i have created. I tried many alternatives like overriding the create method in the UserProfile Serializer class and also the drf-writable-nested but got errors.
Please suggest me a way out. Also i want that the api is able to register users when called on by an android app.
You can do this in your Serializers.py file, this should work.
class UserSerializer(serializers.HyperlinkedModelSerializer):
mobileNumber = serializers.IntegerField()
avatar= serializers.ImageField()
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email', 'password', 'mobileNumber', 'avatar')
def create(self, validated_data):
mobile_number = validated_data.pop('mobileNumber', None)
user = super(UserSerializer, self).create(validated_data)
user.set_password(raw_password=validated_data['password'])
user.save()
userprofile = user.userprofile
userprofile.mobileNumber = mobile_number
userprofile.save()
return user
def update(self, instance, validated_data):
mobile_number = validated_data.pop('mobileNumber', None)
userprofile = instance.userprofile
userprofile.mobileNumber = mobile_number
userprofile.save()
return super(UserSerializer, self).update(instance, validated_data)
Chuck the UserProfileSerializer for this use case, i feel here its not really needed.
Your views.py and models.py look cool to me.
Hope this helps you :-)