I created a Django API to create a new user. However, when I try to create a user I get the error message:
IntegrityError at /api/v1/users/register/ NOT NULL constraint failed: accounts_user.user_id
This is what I have in models.py
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 User(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=100, blank=True)
location = models.CharField(max_length=100, blank=True)
password = models.CharField(max_length=32)
email = models.EmailField(max_length=150)
signup_confirmation = models.BooleanField(default=False)
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def update_profile_signal(sender, instance, created, **kwargs):
if created:
User.objects.create(user=instance)
instance.profile.save()
In serializers.py
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('user_id', 'name', 'location', 'password', 'email', 'signup_confirmation')
and my views.py
from rest_framework import viewsets
from .serializers import UserSerializer
from .models import User
from rest_framework.decorators import action
from .forms import SignUpForm
from .tokens import account_activation_token
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all().order_by('name')
serializer_class = UserSerializer
#action (detail=True, methods=['post'])
def register(self, request):
print(request)
Any ideas on what I can do to resolve this error
As John wrote in a comment:
Here you have a problem: fields = ('user_id',...).
I also advise you to change your User model. If you don't need separating (I suppose you don't), it is way better to create your User with inheritance directly from AbstractUser instead of creating in fact doubled User models.
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
...
In this way you will already have username, password and email, but you can add anything else in same model, instead of using user.user etc.
Related
I got the following error:
Got AttributeError when attempting to get a value for field Name on
serializer UserSerializer. The serializer field might be named
incorrectly and not match any attribute or key on the User instance.
Original exception text was: 'User' object has no attribute 'Name'.
Why do I get an error?
Here is my code:
views.py
from .serializers import UserSerializer
from rest_framework import viewsets, status
from django.contrib.auth.models import User
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
serializers.py
from django.contrib.auth.models import User
from rest_framework import serializers
from .models import Profile
from rest_framework.authtoken.models import Token
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = ('id', 'Name', 'secondName', 'user', 'nickName', 'phoneNumber')
"""extra_kwargs = {'password': {'write_only': True, 'required': True}}"""
def create(self, validated_data):
user = User.objects.create_user(**validated_data)
token = Token.objects.create(user=user)
print('Loogg')
return user
models.py
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
"""Define Profile Fields"""
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, default=None)
Name = models.CharField(max_length=32)
secondName = models.CharField(max_length=32)
nickName = models.CharField(max_length=32)
phoneNumber = models.IntegerField(max_length=32)
def __str__(self):
return self.user.username
class Meta:
verbose_name = 'Profile'
verbose_name_plural = 'profiles'
urls.py
from django.contrib import admin
from django.urls import path
from django.conf.urls import include
from rest_framework import routers
from .views import UserViewSet
router = routers.DefaultRouter()
router.register('users', UserViewSet)
urlpatterns = [
path('', include(router.urls))
]
admin.py
from django.contrib import admin
from .models import Profile
admin.site.register(Profile)
Thanks,
I am quite new to Django so it could be a stupid error.
queryset = Profile.objects.all() instead of queryset = User.objects.all()
– Arakkal Abu
I'm new in Django rest framework, I tried my whole day but can't do it,I want to do full crud operation in my UserProfile Model which have a OneToOne field user, User can only update their own profile and in UserProfile create or update user shouldn't update User[username], How can i achieve it Please Help me
*** serializers.py ***
from rest_framework import serializers
from product.models import UserProfile
from django.contrib.auth.models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
read_only_fields = ['username','password', ]
class UserProfileSerializer(serializers.ModelSerializer):
user = UserSerializer(many=False)
class Meta:
model = UserProfile
fields = "__all__"
def create(self, validated_data):
user_data = validated_data.pop('user')
user_instance = User.objects.get(
username=user_data['username'])
user_instance.save()
user_profile_instance = UserProfile.objects.create(
**validated_data, user=user_instance)
user_profile.save()
return user_profile
*** views.py ***
from django.shortcuts import render
from .serializers import UserProfileSerializer
from rest_framework.views import APIView
from rest_framework import generics, permissions
from rest_framework.response import Response
from rest_framework import status
from django.contrib.auth.models import User
from product.models import UserProfile
# Create your views here.
class CreateUserView(generics.ListCreateAPIView):
serializer_class = UserProfileSerializer
permission_classes = [permissions.IsAuthenticated,]
def get_queryset(self):
user = self.request.user
return UserProfile.objects.filter(user = user)
*** models.py ***
from django.db import models
from django.contrib.auth.models import User
from django.core.validators import MaxValueValidator, MinValueValidator
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='user_profile', on_delete=models.CASCADE)
country = models.CharField(max_length=50, default='India')
city = models.CharField(max_length=100, default='')
phone = models.CharField(max_length=15,default='')
image = models.ImageField(upload_to='profile_image', blank=True)
created_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.user.username
For Authentication you can use token based authentication(like jwt)
and for username you can use read_only=True
no need to send the password for get request
to update profile you need to handle put/post methods
CLEANED Serializers:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
read_only_fields = ['username','password']
class UserProfileSerializer(serializers.ModelSerializer):
# REMOVED all unecessary overrides
user = UserSerializer(read_only=True)
class Meta:
model = UserProfile
fields = "__all__"
Views:
class UserProfileViewSet(viewsets.GenericViewSet,
mixins.UpdateModelMixin):
# Changed inherited class and class NAME !
# I assume that your endpoint is something like /users/me/profile
# I think you want only to update user profile
# Listing or creating profile here is bad - user should have only ONE profile
# and you should do this on user model post_save signal
serializer_class = UserProfileSerializer
permission_classes = [permissions.IsAuthenticated,]
def get_object(self):
return self.request.user.user_profile
This setup will allow you to update profile and only profile data
In your models file you can make signal listener for automatically creating UserProfile object on User object create.
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
I’m trying to create an instance of Listing so I can have user populate in the admin.
I’m new to Django and thought I had it but looks like I’m wrong somewhere.
How do I create an instance of Listing to populate in admin?
Any help i gladly appreciated, thanks.
Code Below:
user_profile/models
from django.db import models
from django.urls import reverse
from django.contrib.auth.models import AbstractUser, UserManager
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.conf import settings
from users.forms import CustomUserCreationForm, CustomUserChangeForm
from users.models import CustomUser
class Listing (models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.PROTECT, null=True)
created = models.DateTimeField(auto_now_add=True, null=True)
updated = models.DateTimeField(auto_now=True)
name = models.CharField(max_length=100)
address = models.CharField(max_length=100)
zip_code = models.CharField(max_length=100)
mobile_number = models.CharField(max_length=100)
cc_number = models.CharField(max_length=100)
cc_expiration = models.CharField(max_length=100)
cc_cvv = models.CharField(max_length=100)
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = Listing.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender=User)
user_profile/admin.py
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from user_profile.forms import HomeForm
from users.forms import CustomUserCreationForm, CustomUserChangeForm
from user_profile.models import Listing
from users.models import CustomUser
# Register models here.
class UserProfileAdmin(admin.ModelAdmin):
list_display = ['name', 'address', 'zip_code', 'mobile_number', 'created', 'updated', 'user']
list_filter = ['name', 'zip_code', 'created', 'updated', 'user']
admin.site.register(Listing, UserProfileAdmin)
I suspect the problem is that you have a custom user model, but your signal is listening to the post_save event from the built-in User. Since you never create instances of that model, the signal never gets triggered.
Change it to:
post_save.connect(create_profile, sender=CustomUser)
I’m trying to get the username of the current logged in user using OneToOneField to populate in the admin once the user submits a form.
The username should go in the user column of admin.py.
I’ve tried various methods and still no luck. I’m new to this and this is my first Django application I’m building so I’m not sure what I’m missing.
I’m stuck and have no idea what I’m doing so any help is gladly appreciated.
Can someone please help? What am I missing?
Thanks!
Code Below:
user_profile/models
from django.db import models
from django.urls import reverse
from django.contrib.auth.models import AbstractUser, UserManager
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.conf import settings
from users.forms import CustomUserCreationForm, CustomUserChangeForm
from users.models import CustomUser
class Listing (models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
name = models.CharField(max_length=100)
address = models.CharField(max_length=100)
zip_code = models.CharField(max_length=100)
mobile_number = models.CharField(max_length=100)
cc_number = models.CharField(max_length=100)
cc_expiration = models.CharField(max_length=100)
cc_cvv = models.CharField(max_length=100)
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = Listing.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender=User)
user_profile/admin.py
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from user_profile.forms import HomeForm
from user_profile.models import Listing
# Register models here.
class UserProfileAdmin(admin.ModelAdmin):
list_display = ['name', 'address', 'zip_code', 'mobile_number', 'created', 'updated', 'user']
list_filter = ['name', 'zip_code', 'created', 'updated', 'user']
admin.site.register(Listing, UserProfileAdmin)
#admin.site.unregister(Listing)
master_application/settings.py
AUTH_USER_MODEL = 'users.CustomUser'
AUTH_PROFILE_MODULE = 'users.UserProfile'
users/models.py
from django.contrib.auth.models import AbstractUser, UserManager
from django.contrib.auth.models import User
from django.db import models
from django.urls import reverse
class CustomUserManager(UserManager):
def get_by_natural_key(self, username):
case_insensitive_username_field = '{}__iexact'.format(self.model.USERNAME_FIELD)
return self.get(**{case_insensitive_username_field: username})
class CustomUser(AbstractUser):
objects = CustomUserManager()`
Your signal is broken; kwargs will never have a user key so the profile will never be created. What you actually want to do is to check that the signal is being called on creation (rather than on update), add then create an instance of Listing:
if kwargs['created']:
user_profile = Listing.objects.create(user=kwargs['instance'])
Note, the AUTH_PROFILE_MODULE setting has not been used for years, you should remove it.
I'm trying to add additional field for user's profile which can be edited only by administrator.
When I try to save a new value of city in an administration module I'm getting an error:
global name 'created' is not defined
This error comes from:
signals.py in create_profile, line 7
I described what I have done till now :)
I started a new app profil
In models.py
from django.db import models
from django.contrib.auth.models import User
from django.utils.encoding import smart_str
class UserProfile(models.Model):
"""Model przechowujący dodatkowe informacje o użytkowniku"""
user = models.ForeignKey(User, unique=True)
city = models.CharField(max_length=255, verbose_name=u'Miasto', blank=True, null=True)
class Meta:
verbose_name = 'Profil użytkownika'
verbose_name_plural = 'Profile użytkowników'
def __unicode__(self):
return u'%s' self.user.username
def __str__(self):
return smart_str('%s' % self.user.username)
import profil.signals
In file: signals.py
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from profil.models import UserProfile
def create_profile(sender, instance, **kwargs):
if created == True:
UserProfile.objects.get_or_create(user=instance)
post_save.connect(create_profile, sender=User)
forms.py
from django import forms
from profil.models import UserProfile
class UserProfileForm(forms.ModelForm):
'''Formularz modelu UserProfile'''
class Meta:
model = UserProfile
admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from profil.forms import UserProfileForm
from profil.models import UserProfile
class UserProfileInline(admin.StackedInline):
model = UserProfile
fk_name = 'user'
max_num = 1
form = UserProfileForm
class UserProfileAdmin(UserAdmin):
inlines = [UserProfileInline, ]
admin.site.unregister(User)
admin.site.register(User, UserProfileAdmin)
In your signals.py you are using created but is not defined yet.
So, you can get it from kwargs using this kwargs.get('created')
Fianlly, you create_profile function should looks like this.
def create_profile(sender, instance, **kwargs):
if kwargs.get('created',None):
UserProfile.objects.get_or_create(user=instance)
You can use:
def create_profile(sender, instance, **kwargs):
if kwargs.get('created', False) ...
or
def create_profile(sender, instance, created, **kwargs):
if created == True: