Django: UNIQUE constraint failed: user.username - python

I have a problem using Djangos Default user from django.contrib.auth.models but trying to use it with my custom User model, using from django.contrib.auth.models import AbstractUser.
So here is my User model:
from django.db import models
from django.contrib.auth.models import AbstractUser, UserManager as AbstractUserManager
# from django.conf import settings
from django_countries.fields import CountryField
# https://github.com/SmileyChris/django-countries
from django.db.models.signals import post_save
from django.dispatch import receiver
class UserManager(AbstractUserManager):
pass
class User(AbstractUser):
"""auth/login-related fields"""
is_a = models.BooleanField('a status', default=False)
is_o = models.BooleanField('o status', default=False)
def __str__(self):
return "{} {}".format(self.first_name, self.last_name)
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
User.objects.set_password(instance.password)
and here is my Profile model:
from django.db import models
from django_countries.fields import CountryField # https://github.com/SmileyChris/django-countries
from django.contrib.auth import get_user_model
User = get_user_model()
# https://medium.com/swlh/best-practices-for-starting-a-django-project-with-the-right-user-model-290a09452b88
from django.db.models.signals import post_save
from django.dispatch import receiver
class Profile(models.Model):
"""non-auth-related/cosmetic fields"""
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='Profile')
birth_date = models.DateTimeField(auto_now=False, auto_now_add=False, null=True)
nationality = CountryField(null=True)
GENDER_CHOICES = (
('M', 'Male'),
('F', 'Female'),
)
gender = models.CharField(max_length=1, choices=GENDER_CHOICES, null=True)
def __str__(self):
return f'{self.user.username} Profile'
"""receivers to add a Profile for newly created users"""
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
But before adding User.objects.set_password(instance.password) to my User model, I did it in py shell, which worked perfectly.
But now I added this line in my User model, and when I'm using Postman to post a User:
{
"username":"1564",
"password":"12345678",
"first_name":"Al",
"last_name":"Pongvf",
"email":"ahgj#live.fr"
}
It gives me this error message:
IntegrityError at /user/create/
UNIQUE constraint failed: ep_user.username
Which I don't get it because I'm creating a new user with a total new username.
I've searched for a solution, but I didn't get lucky:
StackOverflow
1
StackOverflow
2
StackOverflow
3
StackOverflow
4
Does anyone know what am I missing? or doing wrong?
Thanks!
UPDATE:
Here is my User Serializer:
from rest_framework import serializers
from django.contrib.auth import get_user_model
from ..models.model_user import *
# from .serializers_profile import *
class UserIndexSerializer(serializers.ModelSerializer):
# profile = ProfileIndexSerializer()
class Meta:
model = User
fields = [
'id',
'username',
'password',
'first_name',
'last_name',
'email',
'is_a',
'is_o'
# 'profile'
]
class UserCreateSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = [
'username',
'password',
'first_name',
'last_name',
'email',
'is_a',
'is_o'
]
class UserDetailsSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
And here is my User View:
from rest_framework import generics
from django.contrib.auth import get_user_model
from ..models.model_user import *
from ..serializers.serializers_user import *
class UserIndex(generics.ListAPIView):
"""List all users, or create a new user."""
queryset = User.objects.all().order_by('id')
serializer_class = UserIndexSerializer
class UserCreate(generics.CreateAPIView):
"""List all art pieces, or create a new art piece."""
queryset = User.objects.all()
serializer_class = UserCreateSerializer
class UserDetails(generics.RetrieveUpdateDestroyAPIView):
"""Retrieve, update or delete a user instance."""
queryset = User.objects.all()
serializer_class = UserDetailsSerializer
And my admin.py:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
# Register your models here.
from .models.model_user import *
from .models.model_profile import *
admin.site.register(User, UserAdmin)
admin.site.register(Profile)

Related

Cannot edit user profile and change password of the custom user in django

I have a custom user model in my django project. I can create users using the form based on this model but I'm unable to edit and change the passwords. How can I make this possible?
Created the custom user models as shown below.
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
class Role(models.TextChoices):
ADMIN = 'ADMIN', 'Admin'
DEVELOPER = 'DEVELOPER', 'Developer'
TESTER = 'TESTER', 'Tester'
base_role = Role.ADMIN
role = models.CharField(max_length=20, choices= Role.choices)
def save(self, *args,**kwargs):
if not self.pk:
self.role = self.base_role
return super().save(*args, **kwargs)
I tried to edit the user the profile and change password using this form.
from django.contrib.auth.forms import UserCreationForm
from .models import User
from django import forms
class RegisterUserForm(UserCreationForm):
email = forms.EmailField()
first_name = forms.CharField(max_length=50)
last_name = forms.CharField(max_length=50)
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email','role', 'password1', 'password2')
class EditUserForm(forms.ModelForm):
email = forms.EmailField()
first_name = forms.CharField(max_length=50)
last_name = forms.CharField(max_length=50)
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email')
corresponding views.py file
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib import messages
from django.views.decorators.cache import never_cache
from .forms import RegisterUserForm, EditUserForm
from django.views import generic
from django.urls import reverse_lazy
from django.contrib.auth.views import PasswordChangeView
from django.contrib.auth.forms import PasswordChangeForm
from django.contrib.messages.views import SuccessMessageMixin
class EditProfileView(generic.UpdateView, SuccessMessageMixin):
form_class = EditUserForm
template_name = 'edit_profile.html'
success_url = reverse_lazy('home')
def get_object(self):
return self.request.user
def form_valid(self, form):
messages.success(self.request, 'Updated Successfully!')
return super().form_valid(form)
class PasswordsChangeView(PasswordChangeView):
form_class = PasswordChangeForm
template_name = 'change_password.html'
success_url = reverse_lazy('home')
def form_valid(self, form):
messages.success(self.request, 'Password changed successfully')
return super().form_valid(form)
The forms are working fine with the templates but it's not getting updated based on the input I've given.

Django models: Access to a multilevel link between tables

I have a problem to access certain data in my models.
I have a User model giving its id to a Profile model which is giving its id to a ProfileA model.
And when I create a User it automatically creates a Profile.
Here is my user_model
from django.db import models
from django.contrib.auth.models import AbstractUser
from django_countries.fields import CountryField
from .model_custom_user_manager import CustomUserManager
class User(AbstractUser):
"""auth/login-related fields"""
is_a = models.BooleanField('a status', default=False)
is_e = models.BooleanField('e status', default=False)
# objects = CustomUserManager()
def __str__(self):
return "{} {}".format(self.first_name, self.last_name)
My profile_model:
from django.db import models
from django_countries.fields import CountryField
from django.contrib.auth import get_user_model
User = get_user_model()
from django.db.models.signals import post_save
from django.dispatch import receiver
class Profile(models.Model):
"""non-auth-related/cosmetic fields"""
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile')
birth_date = models.DateTimeField(auto_now=False, auto_now_add=False, null=True)
nationality = CountryField(null=True)
def __str__(self):
return f'{self.user.username} Profile'
"""receivers to add a Profile for newly created users"""
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
And what I'm trying to do is create a ProfileA when a Profile is created AND when a User has is_a==True.
Here is my profilea_model:
from django.db import models
from .model_profile import *
from django.db.models.signals import post_save
from django.dispatch import receiver
class ProfileA(models.Model):
profile = models.ForeignKey(Profile, null=True, on_delete=models.CASCADE, related_name='profile_a')
biography = models.CharField(max_length=200, null=True)
def __str__(self):
return "{}".format(self.profile)
#receiver(post_save, sender=Profile)
def create_profile_profile_a(sender, instance, created, **kwargs):
if created & Profile.user.is_a == True:
ProfileA.objects.create(profile=instance)
And when I try creating a User with Postman:
{
"username":"Pepe",
"password":"Yolo1234",
"first_name":"Pepe",
"last_name":"Pepito",
"email":"pepe#yolo.com",
"is_a":true,
"is_e":false
}
I get the error:
AttributeError at /users/
'ForwardOneToOneDescriptor' object has no attribute 'is_a'
I've tried a lot of things but nothing woks and using the DjangDocs I can't understand.
What am I doing wrong?
Thanks for your responses!
The instance argument of the create_profile_profile_a function is the instance of Profile which can be easily pointed to User and further get the target attribute is_a.
The receiver part in profilea_model should change to:
#receiver(post_save, sender=Profile)
def create_profile_profile_a(sender, instance, created, **kwargs):
if created & instance.user.is_a == True:
ProfileA.objects.create(profile=instance)

How to add extra fields to registration end point of rest-auth

I am using rest-auth registration api for user registration. I have some extra fields in the UserProfile model.
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
org_id = models.CharField(max_length=100, default='')
is_teacher = models.BooleanField(blank=True, default=False)
def __str__(self):
return self.user.username
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = UserProfile.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender=User)
The UserProfile model is shown above. How can I add these fields to rest-auth regestration api endpoint and save the data to database.
I found an answer for myself
The serializers can be written as
from rest_framework import serializers
from rest_auth.registration.serializers import RegisterSerializer
from .models import UserProfile
class RegistrationSerializer(RegisterSerializer):
first_name = serializers.CharField(required=False)
last_name = serializers.CharField(required=False)
personal_id = serializers.CharField(required=True)
def custom_signup(self, request, user):
user.first_name = self.validated_data.get('first_name', '')
user.last_name = self.validated_data.get('last_name', '')
user.userprofile.personal_id = self.validated_data.get(
'personal_id', '')
user.save(update_fields=['first_name', 'last_name'])
user.userprofile.save(update_fields=['org_id'])
I didnt add the is_teacher because its optional.
In views.py extend the RegisterView of the rest_auth.regeistration.views to pass this data and its done.
class RegistrationView(RegisterView):
serializer_class = RegistrationSerializer
And finally add a url and pass RegisterView.as_view().

Extending Django User Model and Adding to Admin List Display

I am trying to extend my user model with a profile and then add the new profile fields to the user list display so that it is searchable. Everything is working up until adding it to the admin list display.
I keep getting this error 'User' object has no attribute 'MyProfile'
models.py
from django.db import models
# Create your models here.
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
from userena.models import UserenaBaseProfile
class MyProfile(UserenaBaseProfile):
user = models.OneToOneField(User,
unique=True,
verbose_name=_('user'),
related_name='my_profile')
dealer_num = models.CharField(blank=True,
max_length=15,
verbose_name="Dealer Number")
Admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from .models import MyProfile
class ProfileInline(admin.StackedInline):
model = MyProfile
can_delete = False
verbose_name_plural = 'Profile'
fk_name = 'user'
fields = ('user', 'dealer_num')
class UserAdmin(UserAdmin):
inlines = (ProfileInline, )
list_display = ('username', 'get_dealer_num')
def get_inline_instances(self, request, obj=None):
if not obj:
return list()
return super(UserAdmin, self).get_inline_instances(request, obj)
def get_dealer_num(self, obj):
return obj.MyProfile.dealer_num
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
Try this:
def get_dealer_num(self, obj):
return MyProfile.objects.get(user=obj).dealer_num

Django 2.1.3/SQLite : UNIQUE constraint failed: users_profile.user_id || while trying to access my superuser account

i am working on a website that has a social appeal and i have to create an AbstractUser Model to store extra info about the users; while doing so, i ran into this error while trying to log into django admin page with my superuser account.
UNIQUE constraint failed: users_profile.user_id.
i have rebuilt the project 3 times and the issue still occurs.
here's my models/forms/signals/admin.py files
models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.conf import settings
from PIL import Image
# Create your models here.
class UserModel(AbstractUser):
bio = models.TextField(max_length=500, blank=True, null=True)
location = models.CharField(max_length=35, blank=True, null=True)
birthday = models.DateField(blank=True, null=True)
url = models.URLField(blank=True, null=True)
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, primary_key=True)
image = models.ImageField(default='default.png', upload_to="profile_pics")
def __str__(self):
return self.user.username
def save(self, *args, **kwargs):
super(Profile, self).save(*args, **kwargs)
path = self.image.path
img = Image.open(path)
if img.height > 500 and img.width > 500:
output_size = (500, 500)
img.thumbnail(output_size)
img.save(path)
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import UserModel, Profile
class UserModelCreationForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = UserModel
fields = [
'username',
'password1',
'password2',
'email',
]
class UserModelChangeForm(UserChangeForm):
email = forms.EmailField()
class Meta:
model = UserModel
fields = [
'username',
'email',
]
class ProfileUpdateForm(forms.ModelForm):
model = Profile
fields = [
'image',
]
signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.conf import settings
from .models import Profile
#receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_user_profile(sender, instance, created, **kwargs):
Profile.objects.create(user=instance)
#receiver(post_save, sender=settings.AUTH_USER_MODEL)
def update_user_profile(sender, instance, **kwargs):
instance.profile.save()
admin.py
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from .models import UserModel, Profile
from .forms import UserModelCreationForm, UserModelChangeForm
# Register your models here.
#admin.register(UserModel)
class UserModelAdmin(UserAdmin):
add_form = UserModelCreationForm
form = UserModelChangeForm
model = UserModel
list_display = [
'username', 'email', 'first_name', 'last_name',
]
admin.site.register(Profile)
i have added AUTH_USER_MODEL = 'users.UserModel' to settings.py
i have added default_app_config = 'users.apps.UsersConfig' to users/__init__.py to automatically create profiles.
i have added def ready(self): import users.signals to apps.py
all i am trying to do is access my superuser account. i have created 7 different superusers (just to check) they all raise the same error.
I think the signals are redundant. Only one signal should be fine, it should be like this:
#receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)

Categories

Resources