Correcting Django User Model Foreign Key issue - python

I am using the built-in django user model. I keep getting the error django.db.utils.IntegrityError: FOREIGN KEY constraint failed
I did not use the user model in any other models and vice-versa.
models.py looks like this
from django.contrib.auth.models import User
from django.utils import timezone
from django.db.models import CharField
from django.db.models import BooleanField
from django.db.models import TextField
from django.db.models import DateTimeField
class Course(models.Model):
id = models.AutoField(primary_key=True)
name = CharField(max_length=100)
class Project(models.Model):
id = models.AutoField(primary_key=True)
desc = CharField(max_length=150)
name = CharField(max_length=50)
storyboard_file_path = TextField()
storyboard_completed = BooleanField(default=False)
filming_complete = BooleanField(default=False)
audio_complete = BooleanField(default=False)
production_complete = BooleanField(default=False)
aggregation_complete = BooleanField(default=False)
video_file_path = TextField()
final_review_complete = BooleanField(default=False)
course = models.ForeignKey(Course, on_delete=models.CASCADE, related_name="projects", null=True, blank=True)
class Status(models.Model):
status_id = models.IntegerField(primary_key=True)
desc = CharField(max_length=150)
name = CharField(max_length=50)
class Event(models.Model):
project_id = models.ForeignKey(Project, on_delete=models.CASCADE, null=True, blank=True)
status_id = models.ForeignKey(Status, on_delete=models.CASCADE, null=True, blank=True)
datetime = models.DateTimeField(auto_now_add=True, blank=True)
serializers.py looks like this
from rest_framework import serializers
from .models import Event
from .models import Project
from .models import Course
from rest_framework_jwt.settings import api_settings
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id',
"password",
"last_login",
"is_superuser",
"username",
"first_name",
"last_name",
"email",
"is_staff",
"is_active",
"date_joined",
"groups",
"user_permissions")
def create(self, validated_data):
password = validated_data.pop('password', None)
instance = self.Meta.model(**validated_data)
if password is not None:
instance.set_password(password)
instance.save()
return instance
def update(self, instance, validated_data):
for attr, value in validated_data.items():
if attr == 'password':
instance.set_password(value)
else:
setattr(instance, attr, value)
instance.save()
return instance
def get_jwt_token(user):
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
payload = jwt_payload_handler(user)
return jwt_encode_handler(payload)
class ProjectSerializer(serializers.ModelSerializer):
class Meta:
model = Project
fields = ('id', 'desc', 'name', 'storyboard_file_path',
'storyboard_completed', 'filming_complete', 'audio_complete',
'production_complete', 'aggregation_complete', 'video_file_path',
'final_review_complete', 'course')
def create(self, validated_data):
instance = self.Meta.model(**validated_data)
instance.save()
return instance
def update(self, instance, validated_data):
for attr, value in validated_data.items():
setattr(instance, attr, value)
instance.save()
return instance
class CouserSerializer(serializers.ModelSerializer):
projects = ProjectSerializer(many=True, read_only=True)
class Meta:
model = Course
fields = ('id', 'name', 'projects')
def create(self, validated_data):
instance = self.Meta.model(**validated_data)
instance.save()
return instance
I am trying to load in the fixture
{
"model": "auth.user",
"pk": 1,
"fields": {
"password": "pbkdf2_sha256$120000$V2isoXl1Q88l$sVuB+25I6UNNLY76Ti0EixAu/Ucimqi7rFpbadDzqzc=",
"last_login": null,
"is_superuser": true,
"username": "admin#admin.com",
"first_name": "Admin",
"last_name": "User",
"email": "admin#admin.com",
"is_staff": true,
"is_active": true,
"date_joined": "2019-04-16T00:16:13.252Z",
"groups": [1],
"user_permissions": []
}
},
{
"model": "auth.user",
"pk": 2,
"fields": {
"password": "pbkdf2_sha256$120000$6YHv5JMayFnN$+Y2TqedyjZq02kEw/0ZaXtyigzaH2+BRUIqqkSeAG90=",
"last_login": null,
"is_superuser": false,
"username": "content#content.com",
"first_name": "Content",
"last_name": "Manager",
"email": "content#content.com",
"is_staff": true,
"is_active": true,
"date_joined": "2019-04-16T00:19:01.130Z",
"groups": [2],
"user_permissions": []
}
}
]
I do not understand where this foreign key error is coming from. Any help would be appreciated.

It is probably the groups. Do those groups exist (before the users). If not you would get this error.

Related

Correct way to get/create nested objects with DRF?

I have the following models:
class Platform(models.Model): # Get
key = models.CharField(max_length=32, unique=True)
class PlatformVersion(models.Model): # Get or create
platform = models.ForeignKey(Platform, on_delete=models.CASCADE)
major = models.IntegerField(db_index=True)
minor = models.IntegerField(db_index=True)
build = models.IntegerField(db_index=True)
class DeviceManufacturer(models.Model): # Get or create
name = models.CharField(max_length=64, unique=True)
class DeviceModel(models.Model): # Get or create
manufacturer = models.ForeignKey(DeviceManufacturer, on_delete=models.CASCADE)
platform = models.ForeignKey(Platform, on_delete=models.CASCADE)
# ...
# And many others
POST JSON looks like this:
{
"device_model": {
"manufacturer": {
"name": "samsung"
},
"platform": {
"key": "android"
}
},
"version": {
"platform": {
"key": "android"
},
"major": 8,
"minor": 1,
"build": 0
}
}
I have the following serializers:
class PlatformSerializer(serializers.ModelSerializer):
class Meta:
model = Platform
fields = ('name', 'key',)
extra_kwargs = {
'name': {
'read_only': True,
},
}
def create(self, validated_data):
return Platform.objects.get(key=validated_data['key'])
class PlatformVersionSerializer(serializers.ModelSerializer):
platform = PlatformSerializer()
class Meta:
model = PlatformVersion
fields = ('platform', 'major', 'minor', 'build',)
def create(self, validated_data):
# ?
pass
class DeviceManufacturerSerializer(serializers.ModelSerializer):
class Meta:
model = DeviceManufacturer
fields = ('name',)
def create(self, validated_data):
manufacturer, _ = DeviceManufacturer.objects.get_or_create(
defaults={
'name': validated_data['name'],
},
name=validated_data['name']
)
return manufacturer
class DeviceModelSerializer(serializers.ModelSerializer):
manufacturer = DeviceManufacturerSerializer()
platform = PlatformSerializer()
class Meta:
model = DeviceModel
fields = ('manufacturer', 'platform')
def create(self, validated_data):
# ?
pass
I've marked in serializers places where I don't know how to correctly do the object creation, as some of nested objects are «read-only» (I mean that I in fact use get, not create), some of them are get or create.
How should I do it?

Django Rest Framework nested serializer object is null

I have a two model setup using the Django Rest Framework. One model is a nested serializer into another object. One model is Player and the other model is TeamData. I want TeamData to be nested into Player.
# models.py
from django.db import models
class TeamData(models.Model):
urlName = models.CharField(max_length=50)
city = models.CharField(max_length=50)
nickname = models.CharField(max_length=50)
tricode = models.CharField(max_length=3)
def __str__(self):
return self.city
class Player(models.Model):
firstName = models.CharField(max_length=100)
lastName = models.CharField(max_length=100)
jersey = models.CharField(max_length=10)
pos = models.CharField(max_length=10)
posExpanded = models.CharField(max_length=10)
heightFeet = models.CharField(max_length=2)
heightInches = models.CharField(max_length=2)
weightPounds = models.CharField(max_length=5)
personId = models.CharField(max_length=50)
teamData = models.ForeignKey(
TeamData, on_delete=models.CASCADE, null=True, blank=True)
isAllStar = models.BooleanField()
orderChar = models.CharField(max_length=1)
playerUrl = models.CharField(max_length=50)
displayName = models.CharField(max_length=100)
#serializer.py
from rest_framework import serializers
from .models import *
class TeamDataSerializer(serializers.ModelSerializer):
class Meta:
model = TeamData
fields = ('id', 'urlName', 'city', 'nickname', 'tricode')
class PlayerSerializer(serializers.ModelSerializer):
teamData = TeamDataSerializer('teamData')
class Meta:
model = Player
fields = ('id', 'firstName', 'lastName', 'jersey', 'pos',
'posExpanded', 'heightInches', 'weightPounds', 'personId',
'teamData', 'isAllStar', 'orderChar', 'playerUrl', 'displayName')
def create(self, validated_data):
teamData = validated_data.pop('teamData')
player = Player.objects.create(**validated_data)
return player
#views.py
from rest_framework import viewsets
from .models import Player, TeamData
from rest_framework import viewsets, permissions
from .serializers import *
class PlayerViewSet(viewsets.ModelViewSet):
queryset = Player.objects.all()
permission_classes = [
permissions.AllowAny
]
serializer_class = PlayerSerializer
when I do a POST request of
{
"firstName": "Ste",
"lastName": "Adams",
"jersey": "12",
"pos": "C",
"posExpanded": "Center",
"heightFeet": "6",
"heightInches": "11",
"weightPounds": "265",
"personId": "203500",
"teamData": {
"id": "1",
"urlName": "thunder",
"city": "Oklahoma City",
"nickname": "Thunder",
"tricode": "OKC"
},
"isAllStar": false,
"orderChar": "A",
"playerUrl": "/players/steven/adams/203500",
"displayName": "Adams, Steven"
}
I get back
{
"id": 6,
"firstName": "Ste",
"lastName": "Adams",
"jersey": "12",
"pos": "C",
"posExpanded": "Center",
"heightInches": "11",
"weightPounds": "265",
"personId": "203500",
"teamData": null,
"isAllStar": false,
"orderChar": "A",
"playerUrl": "/players/steven/adams/203500",
"displayName": "Adams, Steven"
}
Any idea why teamData is null? I suspect it may have something to do with
the view but I'm not sure what the problem is.
You are passing a string to PlayerSerializer for no reason. It should be,
class PlayerSerializer(serializers.ModelSerializer):
teamData = TeamDataSerializer() # without passing anything to the serializer
# other code
also, you are not creating TeamData instance in your create() method of the serializer.
#final code sample
class PlayerSerializer(serializers.ModelSerializer):
teamData = TeamDataSerializer()
class Meta:
model = Player
fields = ('id', 'firstName', 'lastName', 'jersey', 'pos',
'posExpanded', 'heightInches', 'weightPounds', 'personId',
'teamData', 'isAllStar', 'orderChar', 'playerUrl', 'displayName')
def create(self, validated_data):
validated_data['teamData'] = TeamData.objects.create(**validated_data.get('teamData', {}))
player = Player.objects.create(**validated_data)
return player

Django rest related model not included

I have a TwitchChannel model which has a ForeignKey relationship to CustomUser.
class TwitchChannel(models.Model):
login = models.CharField(max_length=25)
display_name = models.CharField(max_length=25)
twitch_user_id = models.CharField(max_length=50)
email = models.EmailField(null=True, blank=True)
profile_image_url = models.URLField(null=True, blank=True)
access_token = models.CharField(default="none", max_length=100)
refresh_token = models.CharField(default="none", max_length=100)
live = models.BooleanField(default=False)
channel_data = JSONField()
created = models.DateTimeField(auto_now=True)
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, null=True)
def save(self, **kwargs):
make_password(self.access_token)
make_password(self.refresh_token)
super().save(**kwargs)
def __str__(self):
return self.display_name
def get_channel_url(self):
return f"https://twitch.tv/{self.login}"
In my UserSerializer I want to include this TwitchChannel when it exists. The following are my serializers.
class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True)
twitch_channel = TwitchChannelSerializer(read_only=True, many=True)
def create(self, validated_data):
user = UserModel.objects.create(
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
def update(self, instance, validated_data):
if 'password' in validated_data:
password = validated_data.pop('password')
instance.set_password(password)
class Meta:
model = UserModel
depth = 3
fields = ( "id", "first_name", "last_name", "email", "password", "twitch_channel")
extra_kwargs = {"password": {"write_only": True, }}
class TwitchChannelSerializer(serializers.Serializer):
class Meta:
model = TwitchChannel
fields = (
'user_id',
'login',
'display_name',
'email',
'profile_image_url',
'access_token',
'refresh_token',
'live',
'channel_data',
'created',
'user'
)
However, when I do a request for the user the field isn't even included at all.
{
"id": 3,
"first_name": "Patrick",
"last_name": "Hanford",
"email": "testing#streambeacon.tv"
}
I get no error, but the field is non-existent.
You can use source argument to specify model's field name. By default django use modelname_set name for reverse foreign key relation, so you can use this:
class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True)
twitch_channel = TwitchChannelSerializer(read_only=True, many=True, source="twitchchannel_set")
Also you need to use ModelSerializer for both classes:
class TwitchChannelSerializer(serializers.ModelSerializer):

Django Rest Framework - Post Foreign Key

I am new to Django Rest Framework and checked some tutorials. Now I am trying to create my own structure which is like following. I want to create a user which is OK, then create a profile seperately.
models.py
class User(models.Model):
name = models.CharField(max_length=32)
surname = models.CharField(max_length=32)
facebook_id = models.TextField(null=True)
is_sms_verified = models.BooleanField(default=False)
created = models.DateTimeField(default=timezone.now)
updated = models.DateTimeField(default=timezone.now)
status = models.BooleanField(default=1)
def __str__(self):
return self.name+" "+self.surname
class Profile(models.Model):
user = models.ForeignKey('User',on_delete=models.CASCADE)
email = models.CharField(max_length=32)
birthday = models.DateField(null=True)
bio = models.TextField(null=True)
points = models.IntegerField(default=0)
created = models.DateTimeField(default=timezone.now)
updated = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.user.name+ " " + self.user.surname
serializers.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model=User
fields = ('id','name','surname','facebook_id','is_sms_verified',)
read_only_fields = ('created','updated')
class ProfileSerializer(serializers.ModelSerializer):
user = UserSerializer(read_only=True)
class Meta:
model=Profile
fields=('id','user','email','birthday','bio','points')
read_only_fields = ('created','updated')
views.py
#api_view(['POST'])
def profile_create(request):
serializer = ProfileSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return JsonResponse(serializer.data, status = status.HTTP_201_CREATED)
return JsonResponse(serializer.errors , status= status.HTTP_400_BAD_REQUEST)
data I'm trying to post
{
"user_id": {
"id": 2
},
"email": "xxx#gmail.com",
"birthday": "1991-05-28",
"bio": "qudur",
"points": 31
}
The error I get;
NOT NULL constraint failed: core_profile.user_id
Where am I doing wrong? Thanks!
Your ProfileSerializer has user as readonly. So you need to change that. I would suggest doing it like this
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model=Profile
fields=('id','user','email','birthday','gender','bio','points')
read_only_fields = ('created','updated')
def to_representation(self, instance):
self.fields['user'] = UserSerializer(read_only=True)
return super(ProfileSerializer, self).to_representation(instance)
If you do it this you could provide your user as plain id for POST
{
"user": 2,
"email": "xxx#gmail.com",
"birthday": "1991-05-28",
"bio": "qudur",
"points": 31
}
And when you will read data it will look like this
{
"user": {
"id": 2,
"name": "Name",
"surname": "Surname",
...
},
"email": "xxx#gmail.com",
"birthday": "1991-05-28",
"bio": "qudur",
"points": 31
}
I've noticed Super() throws an error the way it's mentioned above in the awnser:
return super(ProfileSerializer,self).to_representation(instance)
Error: Type error, object must be an instance or subtype of type
Try the Following:
Models.py
class Program(models.Model):
name = models.CharField(max_length=225)
cost = models.IntegerField(default=0)
description = models.TextField(default="", max_length=555)
class UserProgram(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
program = models.ForeignKey(Program, on_delete=models.CASCADE, related_name="program")
Serializers.py
class ProgramSerializers(serializers.ModelSerializer):
class Meta:
model = Program
fields = "__all__"
class UserProgramSerializers(serializers.ModelSerializer):
class Meta:
model = UserProgram
fields = "__all__"
#IMPORTANT PART
def to_representation(self, instance):
response = super().to_representation(instance)
response['program'] = ProgramSerializers(instance.program).data
return response
Views.py
class UserProgramViewset(viewsets.ModelViewSet):
permission_classes = [
permissions.IsAuthenticated
]
serializer_class = UserProgramSerializers
def get_queryset(self):
return UserProgram.objects.filter(user=self.request.user)
def perform_create(self, serializer):
serializer.save(user=self.request.user)
When you call the GET request the following should be the output:
GET Request Output
When you call the POST request you only need to pass the programID and not the whole JSON dictionary!
Hope this helped.

Django Rest Framework foreign key nesting

I am trying to nest my Users table inside my Relationships table. So instead of this:
[
{
"user": 1,
"related_user": 2,
"relationship": "followed_by"
}
]
I am trying to get this:
[
{
"user": {
"username": "user1",
"name": "User 1",
"email": "bla",
"phone": "bla",
"date_joined": "2017-11-01T21:34:13.101256Z"
},
"related_user": {
"username": "user2",
"name": "User 2",
"email": "bla",
"phone": "bla",
"date_joined": "2017-11-01T21:34:13.101256Z"
},
"relationship": "followed_by"
}
]
I looked up tutorials and I tried adding serializers.RelatedField , UserSerializer(many=true, read-only=true) etc. but nothing worked
Models.py
class User(models.Model):
username = models.CharField(max_length=255)
name = models.CharField(max_length=255)
email = models.CharField(max_length=255)
phone = models.CharField(max_length=255)
date_joined = models.DateTimeField(auto_now_add=True, blank=True)
def __str__(self):
return str(self.pk) + ", " + self.username
RELATIONSHIP_CHOICE = [
("follows", "follows"),
("followed_by", "followed_by"),
("none", "none"),
]
class Relationship(models.Model):
user = models.ForeignKey(User, related_name="primary_user", null=True)
related_user = models.ForeignKey(User, related_name="related_user", null=True)
relationship = models.CharField(max_length=40, choices=RELATIONSHIP_CHOICE, default=RELATIONSHIP_CHOICE[0])
Serializers.py
from rest_framework import serializers
from . import models
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = models.User
fields = (
'username',
'name',
'email',
'phone',
'date_joined',
)
class RelationshipSerializer(serializers.ModelSerializer):
related_user = UserSerializer(many=True)
class Meta:
model = models.Relationship
fields = (
'user',
'related_user',
'relationship',
'related_user'
)
I tried to add related user to my serializer but it didnt work. I am getting an error: 'User' object is not iterable
Any help is appreciated.
class RelationshipSerializer(serializers.ModelSerializer):
user = UserSerializer(read_only=True)
related_user = UserSerializer(read_only=True)
class Meta:
model = models.Relationship
fields = (
'user',
'related_user',
'relationship'
)
user = UserSerializer(read_only=True, many=True) is for manytomany field,user = UserSerializer(read_only=True) is for ForeignKey field.

Categories