how can i create Db table using ForiegnKey relationship in DRF - django

Halo i'm working on creating multiple DB table using foreignKey but i'm having some error hoping anyone can help out, below is my code & the error msg
###models.py file
class SchoolVideo(models.Model):
school = models.ForeignKey(
Profile, on_delete=models.CASCADE, related_name='school_video')
intro_video = models.FileField(
upload_to='assets/videos', blank=True, null=True)
###serializer file
class VideoSerializer(serializers.ModelSerializer):
class Meta:
model = SchoolVideo
fields = ('intro_video',)
def create(self, validated_data, *args, **kwargs):
if 'user' in validated_data:
user = validated_data.pop('user')
else:
user = Profile.objects.create(**validated_data)
school_video = SchoolVideo.objects.update_or_create(
user=user, defaults=validated_data
)
return school_video
###API VIEW
class SchoolVideoAPi(generics.CreateAPIView):
serializer_class = VideoSerializer
queryset = SchoolVideo.objects.all()
permission_class = [permissions.IsAuthenticated]
parser_classes = (MultiPartParser, FormParser)
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(
data=request.data, instance=request.user.profile.school_video
)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(
serializer.data,
message='Video successfully Uploaded',
status=status.HTTPS_201_CREATED,
headers=headers,
)
def perform_create(self, serializer):
print(self.request.user.profile)
serializer.save(user=self.request.user.profile)
this is the traceback/err message i'm getting
##err traceback
response = handler(request, *args, **kwargs)
File "/home/olaneat/Desktop/files/project/django/schMrk/lib/python3.8/site-packages/rest_framework/generics.py", line 190, in post
return self.create(request, *args, **kwargs)
File "/home/olaneat/Desktop/files/project/django/schMrk/sch-market/schoolDetail/apiviews.py", line 117, in create
self.perform_create(serializer)
File "/home/olaneat/Desktop/files/project/django/schMrk/sch-market/schoolDetail/apiviews.py", line 128, in perform_create
serializer.save(user=self.request.user.profile)
File "/home/olaneat/Desktop/files/project/django/schMrk/lib/python3.8/site-packages/rest_framework/serializers.py", line 205, in save
self.instance = self.create(validated_data)
File "/home/olaneat/Desktop/files/project/django/schMrk/lib/python3.8/site-packages/rest_framework/serializers.py", line 939, in create
instance = ModelClass._default_manager.create(**validated_data)
File "/home/olaneat/Desktop/files/project/django/schMrk/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/olaneat/Desktop/files/project/django/schMrk/lib/python3.8/site-packages/django/db/models/query.py", line 445, in create
obj = self.model(**kwargs)
File "/home/olaneat/Desktop/files/project/django/schMrk/lib/python3.8/site-packages/django/db/models/base.py", line 483, in __init__
_setattr(self, field.name, rel_obj)
File "/home/olaneat/Desktop/files/project/django/schMrk/lib/python3.8/site-packages/django/db/models/fields/related_descriptors.py", line 215, in __set__
raise ValueError(
ValueError: Cannot assign "<CustomUser: abc#xyz.com>": "SchoolVideo.school" must be a "Profile" instance.
[][1
can anyone help out

The error is caused by this line:
instance=request.user.profile.school_video
As the error says, you are passing school_video as an instance, but it is failing because it is a RelatedManager. Just filter out which school_video you need to fix this.
For example:
instance=request.user.profile.school_video.first()
or
instance=request.user.profile.school_video.filter(<your filters).first()
Just making sure your queryset returns only one object.
Also next time, please try to avoid adding images for code and errors and just put them as text in the question.

Related

Django Rest Framework showing ValueError:Cannot use QuerySet for "Post": Use a QuerySet for "Account"

I am trying to list and paginate favourite post of users. I got a custom pagination snippet from so, which I am using here, But I am getting this error.
ValueError:Cannot use QuerySet for "Post": Use a QuerySet for "Account".
I guess, there are problems with my serializer or views. can anyone please help me fix this issue?
These are the codes:
serializers:
class PostSerializer(serializers.ModelSerializer):
user = serializers.ReadOnlyField(source='user.username')
post_date = serializers.ReadOnlyField()
comment_set = CommentSerializer(many=True)
class Meta:
model = Post
fields = ['id','title', 'post_date', 'user', 'image', 'comment_set']
class PostFavouriteListSerializer(serializers.ModelSerializer):
favourite = PostSerializer(many=True, read_only=True)
class Meta:
model = Post
fields = ['favourite',]
views
class CustomPaginator(PageNumberPagination):
page_size = 3
def generate_response(self, query_set, serializer_obj, request):
try:
page_data = self.paginate_queryset(query_set, request)
except NotFoundError:
return Response({"error": "No results found for the requested page"}, status=status.HTTP_400_BAD_REQUEST)
serialized_page = serializer_obj(page_data, many=True)
return self.get_paginated_response(serialized_page.data)
class FavouritePostAPIView(APIView):
authentication_classes = (TokenAuthentication,)
permission_classes = (IsAuthenticated,)
def get(self, request):
user = self.request.user
favourite_posts = Post.objects.filter(favourite=user.post_favourite.all())
paginator = CustomPaginator()
response = paginator.generate_response(post, PostFavouriteListSerializer, request)
return response
This is the Post model:
class Post(models.Model):
title = models.TextField(max_length=5000, blank=False, null=False)
image = models.ImageField(upload_to='posts/postimage/', null=True)
post_date = models.DateTimeField(auto_now_add=True, verbose_name="Date Posted")
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
slug = models.SlugField(blank=True, unique=True, max_length=255)
favourite = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='post_favourite', blank=True)
Traceback:
File "C:\Users\danny\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\core\handlers\exception.py" in inner
34. response = get_response(request)
File "C:\Users\danny\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\core\handlers\base.py" in _get_response
115. response = self.process_exception_by_middleware(e, request)
File "C:\Users\danny\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\core\handlers\base.py" in _get_response
113. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\danny\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\views\decorators\csrf.py" in wrapped_view
54. return view_func(*args, **kwargs)
File "C:\Users\danny\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\views\generic\base.py" in view
71. return self.dispatch(request, *args, **kwargs)
File "C:\Users\danny\AppData\Local\Programs\Python\Python38-32\lib\site-packages\rest_framework\views.py" in dispatch
505. response = self.handle_exception(exc)
File "C:\Users\danny\AppData\Local\Programs\Python\Python38-32\lib\site-packages\rest_framework\views.py" in handle_exception
465. self.raise_uncaught_exception(exc)
File "C:\Users\danny\AppData\Local\Programs\Python\Python38-32\lib\site-packages\rest_framework\views.py" in raise_uncaught_exception
476. raise exc
File "C:\Users\danny\AppData\Local\Programs\Python\Python38-32\lib\site-packages\rest_framework\views.py" in dispatch
502. response = handler(request, *args, **kwargs)
File "C:\danny\Project\posts\api\views.py" in get
186. favourite_posts = Post.objects.filter(favourite=user.post_favourite.all())
File "C:\Users\danny\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\db\models\manager.py" in manager_method
82. return getattr(self.get_queryset(), name)(*args, **kwargs)
File "C:\Users\danny\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\db\models\query.py" in filter
892. return self._filter_or_exclude(False, *args, **kwargs)
File "C:\Users\danny\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\db\models\query.py" in _filter_or_exclude
910. clone.query.add_q(Q(*args, **kwargs))
File "C:\Users\danny\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\db\models\sql\query.py" in add_q
1290. clause, _ = self._add_q(q_object, self.used_aliases)
File "C:\Users\danny\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\db\models\sql\query.py" in _add_q
1315. child_clause, needed_inner = self.build_filter(
File "C:\Users\danny\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\db\models\sql\query.py" in build_filter
1224. self.check_related_objects(join_info.final_field, value, join_info.opts)
File "C:\Users\danny\AppData\Local\Programs\Python\Python38-32\lib\site-packages\django\db\models\sql\query.py" in check_related_objects
1079. raise ValueError(
Exception Type: ValueError at /api/posts/posts/favourites/
Exception Value: Cannot use QuerySet for "Post": Use a QuerySet for "Account".
replace :
favourite_posts = Post.objects.filter(favourite=user.post_favourite.all())
paginator = CustomPaginator()
response = paginator.generate_response(post, PostFavouriteListSerializer, request)
by :
favourite_posts = user.post_favourite.all()
paginator = CustomPaginator()
response = paginator.generate_response(favourite_posts, PostSerializer, request)
the related m2m post_favourite is a queryset of post , not need to filter/get this, so you dont need PostFavouriteListSerializer
alternative can be this:
favourite_posts = Post.objects.filter(favourite=user)
you get all post with favourite have your user

How to create APIs for UserProfile with rest framework?

I have created a UserProfile model with OneToOne relationship with User model.
The UserProfile model is shown below.
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)
mobile_number = models.IntegerField(blank=True, unique=True, null=True)
profile_image = models.ImageField(upload_to="media", blank=True )
current_location= models.CharField(max_length=300, unique=False, blank=True)
created_at = models.DateTimeField("created at", auto_now_add=True)
university = models.CharField(max_length=100, blank=True)
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 serializer class is shown below.
from rest_framework import serializers
from .models import UserProfile
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = ( 'mobile_number',
'current_location'
,'university','profile_image')
Iam using token authentication. How can I use the ListCreateViewand other classes to implement the post, put ,get and delete method in the best way possible. I also need to validate these data before saving(like mobile_number length should be 10 and mandatory)
I tried to build a view as shown below.
from .models import UserProfile
from .serializers import UserProfileSerializer
class UserProfileView(ListCreateAPIView):
queryset = UserProfile.objects.all()
print(queryset)
serializer_class = UserProfileSerializer
def get_queryset(self):
return UserProfile.objects.filter(user=self.request.user)
def perform_create(self, serializer):
profile = get_object_or_404(UserProfile, user=self.request.user)
print(str(self.request.user.id)+"..."+str(profile))
return serializer.save(userprofile=profile)
But it gives me error:
Got a `TypeError` when calling `UserProfile.objects.create()`. This may be because you have a writable field on the serializer class that is not a valid argument to `UserProfile.objects.create()`. You may need to make the field read-only, or override the UserProfileSerializer.create() method to handle this correctly.
how can I solve the problem.
The stack trace is shown below
Internal Server Error: /users/userprofile
Traceback (most recent call last):
File "/home/vishnu/.local/lib/python3.6/site-packages/rest_framework/serializers.py", line 932, in create
instance = ModelClass._default_manager.create(**validated_data)
File "/home/vishnu/.local/lib/python3.6/site-packages/django/db/models/manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/vishnu/.local/lib/python3.6/site-packages/django/db/models/query.py", line 420, in create
obj = self.model(**kwargs)
File "/home/vishnu/.local/lib/python3.6/site-packages/django/db/models/base.py", line 501, in __init__
raise TypeError("%s() got an unexpected keyword argument '%s'" % (cls.__name__, kwarg))
TypeError: UserProfile() got an unexpected keyword argument 'userprofile'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/vishnu/.local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/home/vishnu/.local/lib/python3.6/site-packages/django/core/handlers/base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/vishnu/.local/lib/python3.6/site-packages/django/core/handlers/base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/vishnu/.local/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/home/vishnu/.local/lib/python3.6/site-packages/django/views/generic/base.py", line 71, in view
return self.dispatch(request, *args, **kwargs)
File "/home/vishnu/.local/lib/python3.6/site-packages/rest_framework/views.py", line 505, in dispatch
response = self.handle_exception(exc)
File "/home/vishnu/.local/lib/python3.6/site-packages/rest_framework/views.py", line 465, in handle_exception
self.raise_uncaught_exception(exc)
File "/home/vishnu/.local/lib/python3.6/site-packages/rest_framework/views.py", line 476, in raise_uncaught_exception
raise exc
File "/home/vishnu/.local/lib/python3.6/site-packages/rest_framework/views.py", line 502, in dispatch
response = handler(request, *args, **kwargs)
File "/home/vishnu/.local/lib/python3.6/site-packages/rest_framework/generics.py", line 242, in post
return self.create(request, *args, **kwargs)
File "/home/vishnu/.local/lib/python3.6/site-packages/rest_framework/mixins.py", line 19, in create
self.perform_create(serializer)
File "/home/vishnu/git_repos/Agora42core/users/views.py", line 23, in perform_create
return serializer.save(userprofile=profile)
File "/home/vishnu/.local/lib/python3.6/site-packages/rest_framework/serializers.py", line 213, in save
self.instance = self.create(validated_data)
File "/home/vishnu/.local/lib/python3.6/site-packages/rest_framework/serializers.py", line 951, in create
raise TypeError(msg)
TypeError: Got a `TypeError` when calling `UserProfile.objects.create()`. This may be because you have a writable field on the serializer class that is not a valid argument to `UserProfile.objects.create()`. You may need to make the field read-only, or override the UserProfileSerializer.create() method to handle this correctly.
Original exception was:
Traceback (most recent call last):
File "/home/vishnu/.local/lib/python3.6/site-packages/rest_framework/serializers.py", line 932, in create
instance = ModelClass._default_manager.create(**validated_data)
File "/home/vishnu/.local/lib/python3.6/site-packages/django/db/models/manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/vishnu/.local/lib/python3.6/site-packages/django/db/models/query.py", line 420, in create
obj = self.model(**kwargs)
File "/home/vishnu/.local/lib/python3.6/site-packages/django/db/models/base.py", line 501, in __init__
raise TypeError("%s() got an unexpected keyword argument '%s'" % (cls.__name__, kwarg))
TypeError: UserProfile() got an unexpected keyword argument 'userprofile'
If you're really creating a new UserProfile object, your perform_create() method should just pass the user into the serialiser's save() method:
def perform_create(self, serializer):
return serializer.save(user=self.request.user)
But if you already have a UserProfile, which looks like it's what your expecting since you're using get_object_or_404, then you should use a UpdateAPIView instead of a ListCreateAPIView:
class UserProfileView(UpdateAPIView):
serializer_class = UserProfileSerializer
permission_classes = [IsAuthenticated]
def get_queryset(self):
return UserProfile.objects.filter(user=self.request.user)
For PUT, PATCH, you need to define(override) create and update
Validation can be done at two levels. Both are shown below:
At Serializer level,
it is just validate_field_variable_name
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = ( 'mobile_number',
'current_location'
,'university','profile_image')
#For POST
def create(self, validated_data):
<your code,>
#for PATCH
def update(self, instance, validated_data):
<your code,>
#Validation
def validate_mobile_number(self, cell_number):
#Validate code here
More:
https://www.django-rest-framework.org/api-guide/validators/
Validation at Model level:
You can also do this kind of validation at model level, like length of string etc.
Particular to mobile number, there are other modules which can do this unless you want special cases to handle.
from django.db import models
from phone_field import PhoneField
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
mobile_number = PhoneField(blank=True, unique=True, null=True)
https://pypi.org/project/django-phone-field/

Django error creating object with many to many field

There are a few questions already mentioning this error but I couldn't find an answer in any of them.
File "/home/joao/.virtualenvs/courty/lib64/python3.6/site-packages/rest_framework/serializers.py", line 214, in save
self.instance = self.create(validated_data)
File "/home/joao/Code/projects/courty/courty-django/apps/matching/serializers.py", line 19, in create
return MatchFinder.objects.create(**validated_data)
File "/home/joao/.virtualenvs/courty/lib64/python3.6/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/joao/.virtualenvs/courty/lib64/python3.6/site-packages/django/db/models/query.py", line 392, in create
obj = self.model(**kwargs)
File "/home/joao/.virtualenvs/courty/lib64/python3.6/site-packages/django/db/models/base.py", line 568, in __init__
_setattr(self, prop, kwargs[prop])
File "/home/joao/.virtualenvs/courty/lib64/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 536, in __set__
manager = self.__get__(instance)
File "/home/joao/.virtualenvs/courty/lib64/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 513, in __get__
return self.related_manager_cls(instance)
File "/home/joao/.virtualenvs/courty/lib64/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 830, in __init__
(instance, self.pk_field_names[self.source_field_name]))
ValueError: "<MatchFinder: MatchFinder object>" needs to have a value for field "id" before this many-to-many relationship can be used.
Model
class MatchFinder(models.Model):
player = models.ForeignKey(Player)
start_datetime = models.DateTimeField(null=False)
venues = models.ManyToManyField(Venue, help_text='Pitches preferred by this player', blank=True)
View
class MatchFinderView(views.APIView):
def post(self, request, format=None):
serializer = MatchFinderSerialzer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Serializer
class MatchFinderSerialzer(BaseModelSerializer):
class Meta:
model = MatchFinder
fields = ('start_datetime', 'venues')
def create(self, validated_data):
return MatchFinder.objects.create(**validated_data)
Request
c = Client()
data = {
'start_datetime': now,
}
response = c.post('/matches/findmatch/', data)
Passing a list of 2 Venue objects in the venues on the post request results in the same error.
There are multiple issues,
Firstly, 'player' is a non nullable field - so you need to add it in the fields.
Secondly, For nested relationships you need to explicitly specify how the child relationships should be saved. I have modified the Serializer accordingly,
class MatchFinderSerialzer(BaseModelSerializer):
class Meta:
model = MatchFinder
fields = ('player', 'start_datetime', 'venues')
def create(self, validated_data):
venues_data = validated_data.pop('venues')
match_finder = MatchFinder.objects.create(**validated_data)
for venue_data in venues_data:
Venue.objects.create(match_finder=match_finder, **venue_data)
return match_finder
Also make sure you provide 'player id' in your post request.

Added Many2Many now getting "ValueError: XXX needs to have a value for field "id" before this many-to-many relationship can be used"

I've read a bunch of similar sounding questions of SO, but somehow none of them have helped me solve my particular case. I added a ManyToManyField to represent "Likes" to my Photo model:
class Photo(TimestampModerated):
owner = models.ForeignKey('auth.User', related_name='photos', on_delete=models.CASCADE)
uuid = models.UUIDField(default=uuid4, editable=False)
slug = models.SlugField(max_length=80, editable=False)
title = models.CharField(max_length=80, blank=False, null=False)
description = models.TextField(verbose_name='description of entity', blank=True, null=True)
photo = models.ImageField(upload_to=user_directory_path, height_field="height", width_field="width", blank=True)
height = models.IntegerField(blank=True)
width = models.IntegerField(blank=True)
tags = TaggableManager(blank=True)
hash = models.CharField(max_length=64, unique=True, null=True)
size = models.BigIntegerField('size of file in bytes', blank=True, null=True)
likes = models.ManyToManyField('auth.User', blank=True, null=True)
class Meta:
verbose_name_plural = "photos"
def __str__(self):
return self.title
def delete(self, using=None, keep_parents=False):
default_storage.delete("{}".format(self.photo))
super().delete()
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Photo, self).save(*args, **kwargs)
Here is the view (at least the part that should matter for creating):
class PhotoViewSet(viewsets.ModelViewSet):
queryset = Photo.objects.all()
serializer_class = PhotoSerializer
authentication_classes = (TokenAuthentication,)
permission_classes = (IsOwnerOrReadOnly, permissions.AllowAny,)
parser_classes = (MultiPartParser, FormParser)
def perform_create(self, serializer):
serializer.save(owner=self.request.user, likes=[])
And here is the serializer:
class PhotoSerializer(serializers.ModelSerializer, TaggitSerializer):
owner = serializers.CharField(source='owner.username', read_only=True)
tags = TagListSerializerField()
photo = Base64ImageField(
max_length=None, use_url=True,
)
class Meta:
model = Photo
fields = ('photo', 'height', 'width', 'owner', 'slug', 'uuid', 'title', 'id', 'created', 'updated',
'moderation_code', 'tags', 'hash', 'description', 'size', 'likes')
def create(self, validated_data):
photo = Photo.objects.create(owner=validated_data.pop('owner'),
**validated_data)
p = Photo.objects.get(uuid=photo.uuid)
[p.tags.add(tag) for tag in validated_data['tags']]
return photo
To be clear, the only thing that has been added is the likes field in the model. Also, I should note that I am able to actually POST new likes to photos that already existed in the DB before the migration. I'm just having issues creating new instances. Any ideas?
Here is the full error traceback:
Internal Server Error: /api/photos/
Traceback (most recent call last):
File "/Users/xxxxxx/_/.virtualenv/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
response = get_response(request)
File "/Users/xxxxxx/_/.virtualenv/lib/python3.6/site-packages/django/core/handlers/base.py", line 187, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/Users/xxxxxx/_/.virtualenv/lib/python3.6/site-packages/django/core/handlers/base.py", line 185, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/xxxxxx/_/.virtualenv/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
return view_func(*args, **kwargs)
File "/Users/xxxxxx/_/.virtualenv/lib/python3.6/site-packages/rest_framework/viewsets.py", line 86, in view
return self.dispatch(request, *args, **kwargs)
File "/Users/xxxxxx/_/.virtualenv/lib/python3.6/site-packages/rest_framework/views.py", line 489, in dispatch
response = self.handle_exception(exc)
File "/Users/xxxxxx/_/.virtualenv/lib/python3.6/site-packages/rest_framework/views.py", line 449, in handle_exception
self.raise_uncaught_exception(exc)
File "/Users/xxxxxx/_/.virtualenv/lib/python3.6/site-packages/rest_framework/views.py", line 486, in dispatch
response = handler(request, *args, **kwargs)
File "/Users/xxxxxx/_/.virtualenv/lib/python3.6/site-packages/rest_framework/mixins.py", line 21, in create
self.perform_create(serializer)
File "/Users/xxxxxx/_/photos/views.py", line 24, in perform_create
serializer.save(owner=self.request.user, likes=[])
File "/Users/xxxxxx/_/.virtualenv/lib/python3.6/site-packages/rest_framework/serializers.py", line 215, in save
self.instance = self.create(validated_data)
File "/Users/xxxxxx/_/photos/serializers.py", line 88, in create
**validated_data)
File "/Users/xxxxxx/_/.virtualenv/lib/python3.6/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/Users/xxxxxx/_/.virtualenv/lib/python3.6/site-packages/django/db/models/query.py", line 392, in create
obj = self.model(**kwargs)
File "/Users/xxxxxx/_/.virtualenv/lib/python3.6/site-packages/django/db/models/base.py", line 566, in __init__
_setattr(self, prop, kwargs[prop])
File "/Users/xxxxxx/_/.virtualenv/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 536, in __set__
manager = self.__get__(instance)
File "/Users/xxxxxx/_/.virtualenv/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 513, in __get__
return self.related_manager_cls(instance)
File "/Users/xxxxxx/_/.virtualenv/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 830, in __init__
(instance, self.pk_field_names[self.source_field_name]))
ValueError: "<Photo: photo-260561.jpeg>" needs to have a value for field "id" before this many-to-many relationship can be used.
Well, I solved this with one seemingly very simple line of code:
def create(self, validated_data):
validated_data.pop('likes') ## adding this line solved the issue
photo = Photo.objects.create(owner=validated_data.pop('owner'),
**validated_data)
p = Photo.objects.get(uuid=photo.uuid)
[p.tags.add(tag) for tag in validated_data['tags']]
return photo
If anyone can explain why this works, I'd be interested to know. I should point out that for this use case a photo would never be initiated with likes.

Django: Adding "created by" field to object

I need to store the user who is creating a specific object in the database, like so:
(models.py)
class Address(models.Model):
createdBy = models.ForeignKey(User)
address1 = models.CharField("Address Line 1", max_length=40)
address2 = models.CharField("Address Line 2", max_length=40, blank=True)
city = models.CharField(max_length=20)
state = models.CharField(max_length=3)
zipCode = models.CharField("Postal Code", max_length=10)
My view for handling the form is here (views.py):
def handlePopAdd(request, addForm, field):
if request.method == "POST":
form = addForm(request.POST)
if form.is_valid():
try:
newObject = form.save(request)
except forms.ValidationError, error:
newObject = None
if newObject:
return HttpResponse('<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");</script>'% (escape(newObject._get_pk_val()), escape(newObject)))
else:
form = addForm()
pageContext = {'form': form, 'field': field}
return render_to_response("address_popup.html", pageContext, context_instance=RequestContext(request))
And finally, here is my form code: (forms.py)
class AddressForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
return super(AddressForm, self).__init__(*args, **kwargs)
def save(self, *args, **kwargs):
obj = super(AddressForm, self).save(commit=False)
if self.request:
obj.createdBy = self.request.user
obj.save()
class Meta:
model = Address
exclude = ('createdBy',)
I am using the top answer suggested by this question, and have hit a wall after a few hours staring a hole through this.
Here's my traceback. Error is IntegrityError at /app/address/add/ (1048, "Column 'createdBy_id' cannot be null")
Traceback:
File "/usr/local/lib/python2.6/dist-packages/django/core/handlers/base.py" in get_response
111. response = callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python2.6/dist-packages/django/contrib/auth/decorators.py" in _wrapped_view
23. return view_func(request, *args, **kwargs)
File "/home/matthew/lessonhelper/../lessonhelper/lessons/views.py" in address_add
78. return handlePopAdd(request, AddressForm, 'address')
File "/usr/local/lib/python2.6/dist-packages/django/contrib/auth/decorators.py" in _wrapped_view
23. return view_func(request, *args, **kwargs)
File "/home/matthew/lessonhelper/../lessonhelper/lessons/views.py" in handlePopAdd
66. newObject = form.save(request)
File "/home/matthew/lessonhelper/../lessonhelper/lessons/forms.py" in save
29. obj.save()
File "/usr/local/lib/python2.6/dist-packages/django/db/models/base.py" in save
460. self.save_base(using=using, force_insert=force_insert, force_update=force_update)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/base.py" in save_base
553. result = manager._insert(values, return_id=update_pk, using=using)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/manager.py" in _insert
195. return insert_query(self.model, values, **kwargs)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/query.py" in insert_query
1436. return query.get_compiler(using=using).execute_sql(return_id)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/compiler.py" in execute_sql
791. cursor = super(SQLInsertCompiler, self).execute_sql(None)
File "/usr/local/lib/python2.6/dist-packages/django/db/models/sql/compiler.py" in execute_sql
735. cursor.execute(sql, params)
File "/usr/local/lib/python2.6/dist-packages/django/db/backends/util.py" in execute
34. return self.cursor.execute(sql, params)
File "/usr/local/lib/python2.6/dist-packages/django/db/backends/mysql/base.py" in execute
86. return self.cursor.execute(query, args)
File "/usr/lib/pymodules/python2.6/MySQLdb/cursors.py" in execute
166. self.errorhandler(self, exc, value)
File "/usr/lib/pymodules/python2.6/MySQLdb/connections.py" in defaulterrorhandler
35. raise errorclass, errorvalue
Exception Type: IntegrityError at /app/address/add/
Exception Value: (1048, "Column 'createdBy_id' cannot be null"
You specifically defined logic to add the request to the form, but are not using it.
You need to instantiate your form with request as a keyword argument (according to your code).
form = addForm(request.POST, request=request)
save(request) does nothing with the request.
Most people prefer just accepting a new argument in save().
def save(self, request):
obj = super(AddressForm, self).save(commit=False)
obj.createdBy = request.user
obj.save()
Finally, there's no point in the if block in the save method if createdBy is not nullable: it's required. There's no "if" about it.
You excluded the createdBy field in your form and according to your Model definition, it's a required field since you're using a ModelForm.