Django error creating object with many to many field - django

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.

Related

how can i create Db table using ForiegnKey relationship in DRF

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.

Error when serializing foreign key object with django-rest-framework-gis to geojson

I am trying to serialize into geojson a model with a foreign key that has a geometry field. I am using the django-rest-framework-gis. I am using django 2.2
I'm stuck on this and none of the other related answers on Stack Overflow work for me. e.g. I have tried versions of this:
How can I flatten a foreignkey object with django-rest-framework-(gis)
Set serializer geo_field as PointField from another model - Django
The problem is I get this error:
Expected a Response, HttpResponse or HttpStreamingResponse to be returned from the view, but received a <class 'statements.models.Response'>
Models:
from django.contrib.gis.db import models
from django.contrib.gis.geos import Point
class Hexgrid_10km2(models.Model):
lng = models.FloatField()
lat = models.FloatField()
polygon = models.MultiPolygonField(srid=4326)
centroid = models.PointField(default=Point(0,0), srid=4326)
def __str__(self):
return f'lng: { self.lng } lat: {self.lat }'
class Response(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
statement = models.ForeignKey(Statement, on_delete=models.CASCADE)
hexgrid_10km2 = models.ForeignKey(Hexgrid_10km2, on_delete=models.CASCADE, null=True, blank=True)
#property
def polygon(self):
return self.hexgrid_10km2.polygon
Views
class ResponseHeatmapAPIView(APIView): #ReadOnly
def get(self, request, pk):
final = Response.objects.all()
serializer = ResponseHeatmapSerializer(final, many=True)
return Response(serializer.data)
Serializers
class ResponseHeatmapSerializer(GeoFeatureModelSerializer):
""" A class to serialize hex polygons as GeoJSON compatible data """
hexgrid_10km2 = GeometrySerializerMethodField()
def get_hexgrid_10km2(self, obj):
return obj.hexgrid_10km2.polygon
class Meta:
model = Response
geo_field = 'hexgrid_10km2'
id_field = False
fields = ('id',)
Traceback
OrderedDict([('type', 'FeatureCollection'), ('features', [OrderedDict([('id', 2), ('type', 'Feature'), ('geometry', GeoJsonDict([('type', 'MultiPolygon'), ('coordinates', [[[[0.52353663711945, 50.8631481850499], [0.538799411254891, 50.86870974483], [0.554062185390241, 50.8631481850499], [0.554062185390241, 50.852023074998], [0.548895002474644, 50.85013962], [0.540831980000019, 50.85013962], [0.53199000192362, 50.8489417564374], [0.52353663711945, 50.852023074998], [0.52353663711945, 50.8631481850499]]]])])), ('properties', OrderedDict([('response_date', '2020-04-15T21:04:04.599597Z'), ('agree', 1), ('hasLocation', False), ('location', GeoJsonDict([('type', 'Point'), ('coordinates', [0.550660257722784, 50.851541821108924])])), ('latitude', 50.851541821108924), ('longitude', 0.5506602577227836), ('locationAccuracy', 0.0), ('user', 1), ('statement', 1)]))])])])
Internal Server Error: /statements/api/heatmap/1
Traceback (most recent call last):
File "C:\Users\anton\OneDrive\Documents\django\karate-project-2.2\venv\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
response = get_response(request)
File "C:\Users\anton\OneDrive\Documents\django\karate-project-2.2\venv\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\anton\OneDrive\Documents\django\karate-project-2.2\venv\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\anton\OneDrive\Documents\django\karate-project-2.2\venv\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "C:\Users\anton\OneDrive\Documents\django\karate-project-2.2\venv\lib\site-packages\django\views\generic\base.py", line 71, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Users\anton\OneDrive\Documents\django\karate-project-2.2\venv\lib\site-packages\rest_framework\views.py", line 507, in dispatch
self.response = self.finalize_response(request, response, *args, **kwargs)
File "C:\Users\anton\OneDrive\Documents\django\karate-project-2.2\venv\lib\site-packages\rest_framework\views.py", line 419, in finalize_response
assert isinstance(response, HttpResponseBase), (
AssertionError: Expected a `Response`, `HttpResponse` or `HttpStreamingResponse` to be returned from the view, but received a `<class 'statements.models.Response'>`
[15/Apr/2020 21:55:04] "GET /statements/api/heatmap/1 HTTP/1.1" 500 89414
Serializer is waiting for data from you. I got the same error when I tried your view with a simple modeling. I think there is something wrong with the definition. can you try the presentation:
def get(self, request):
final = Response.objects.all()
serializer = ResponseHeatmapSerializer(data=final, many=True)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
EDITED:
Please excuse me because of my sleeplessness.
The BIG problem here is the name of the table: Response. You have to change the name; somehow it conflicts with the 'Response' that the RestAPI uses.
Change Response(model.Model)'s name to different name.
python manage.py makemigrations
python manage.py migrate
and the view is ready to run (I changed the model name to 'Strawberry':
class ResponseHeatmapList(APIView):
def get(self, request):
final = Strawberry.objects.all()
serializer = ResponseHeatmapSerializer(final, many=True)
return Response(serializer.data)
class ResponseHeatmapDetail(APIView):
def get_object(self, pk):
try:
return Strawberry.objects.get(pk=pk)
except Strawberry.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
final = self.get_object(pk)
serializer = ResponseHeatmapSerializer(final)
return Response(serializer.data)

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/

Getting error object has no attribute 'get' while using clean in django modelform

I am trying to custom validate my model form. For the purpose, I wrote the following code:
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = '__all__'
def clean(self):
batch_start_year = self.cleaned_data.get('batch_start_year',None)
I am getting error like:
'StudentForm' object has no attribute 'get'
I tried another solution, but it didn't work either.
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = '__all__'
def clean(self):
cleaned_data = super(StudentForm, self).clean()
batch_start_year = cleaned_data['batch_start_year']
Please help me to solve this.
Full stack trace:
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 149, in get_response
response = self.process_exception_by_middleware(e, request)
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 147, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/shahjahan/Desktop/jmialumniusa/jmialumniusa_app/views.py", line 18, in apply
if form.is_valid():
File "/usr/local/lib/python2.7/dist-packages/django/forms/forms.py", line 161, in is_valid
return self.is_bound and not self.errors
File "/usr/local/lib/python2.7/dist-packages/django/forms/forms.py", line 153, in errors
self.full_clean()
File "/usr/local/lib/python2.7/dist-packages/django/forms/forms.py", line 364, in full_clean
self._post_clean()
File "/usr/local/lib/python2.7/dist-packages/django/forms/models.py", line 377, in _post_clean
exclude = self._get_validation_exclusions()
File "/usr/local/lib/python2.7/dist-packages/django/forms/models.py", line 337, in _get_validation_exclusions
field_value = self.cleaned_data.get(field)
AttributeError: 'StudentForm' object has no attribute 'get'
You should return cleaned data from clean() method or raise error. You are not doing that.
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = '__all__'
def clean(self):
batch_start_year = self.cleaned_data.get('batch_start_year',None)
# do something
return self.cleaned_data
If you want to validate all your form, you can use clean method like this
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = '__all__'
def clean(self):
cleaned_data = super(StudentForm, self).clean()
batch_start_year = cleaned_data.get('batch_start_year')
In this case, you do not need to return anything. You will just raise validation error. If you want to validate some specific field, you will do it like this
def clean_field_name(self):
data = self.cleaned_data.get('field_name')
if "something" not in data:
raise forms.ValidationError("Validation message")
# Always return the cleaned data, whether you have changed it or
# not.
return data
Another possibility of error can be the way you are sending data to your form
student = Student.objects.get(pk=id)
form = StudentForm(intention) # An unbound form
The first argument to a form is the data but you are passing the instance. To properly pass the instance you should use:
student = Student.objects.get(pk=id)
form = StudentForm(instance=student) #

Current User inside nested serializer

I'm using Django Rest Framework 3.3.2 with Django 1.9.1
I have 2 serializers and I use one of them inside the other one.
class VideoSerializer(serializers.ModelSerializer):
current_username = serializers.SerializerMethodField()
is_deletable = serializers.SerializerMethodField()
tagged_users = EachUserSerializer(many=True, read_only=True)
print current_username
comments = CommentSerializer(many=True, read_only=True, context={'current_username': current_username})
place_taken = PlaceLimitedSerializer()
owner_user = EachUserSerializer()
class Meta:
model = Video
fields = ('tagged_users', 'comments', 'place_taken', 'video_id', 'video_url', 'like_count', 'caption', 'date',
'category', 'owner_user', 'current_username', 'is_deletable', )
def get_current_username(self, obj):
self.current_username = self.context['request'].user.username
return self.context['request'].user.username
def get_is_deletable(self, obj):
return obj.is_deletable_by(self.current_username)
class CommentSerializer(serializers.ModelSerializer):
current_username = serializers.SerializerMethodField()
is_deletable = serializers.SerializerMethodField()
is_editable = serializers.SerializerMethodField()
def get_current_username(self, obj):
self.current_username = self.context['current_username']
return self.current_username
def get_is_deletable(self, obj):
return obj.is_deletable(self.current_username)
def get_is_editable(self, obj):
return obj.is_editable(self.current_username)
class Meta:
model = Comment
fields = ('comment', 'username', 'comment_id', 'date', 'current_username', 'is_editable', 'is_deletable',)
My question is that I need current user's username in serializers. I managed to do that in VideoSerializer by setting a context in view like this.
class get_video(APIView):
def get(self, request):
video_id = str(request.query_params.get('video_id'))
if Video.objects.all().filter(video_id=video_id).exists():
video = Video.objects.get(video_id=video_id)
serializer = VideoSerializer(video, context={"request": request})
return JsonResponse(serializer.data)
else:
return JsonResponse({"result": "no_video"})
In VideoSerializer, I tried to set context and I want to pass 'current_user' to the CommentSerializer but it gives this error.
Internal Server Error: /video/get_video/
Traceback (most recent call last):
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/django/core/handlers/base.py", line 149, in get_response
response = self.process_exception_by_middleware(e, request)
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/django/core/handlers/base.py", line 147, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
return view_func(*args, **kwargs)
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/rest_framework/views.py", line 466, in dispatch
response = self.handle_exception(exc)
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/rest_framework/views.py", line 463, in dispatch
response = handler(request, *args, **kwargs)
File "/Users/mcagataybarin/molocate-dev/molocate_eb/video/views.py", line 96, in get
return JsonResponse(serializer.data)
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/rest_framework/serializers.py", line 503, in data
ret = super(Serializer, self).data
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/rest_framework/serializers.py", line 239, in data
self._data = self.to_representation(self.instance)
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/rest_framework/serializers.py", line 472, in to_representation
ret[field.field_name] = field.to_representation(attribute)
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/rest_framework/serializers.py", line 614, in to_representation
self.child.to_representation(item) for item in iterable
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/rest_framework/serializers.py", line 472, in to_representation
ret[field.field_name] = field.to_representation(attribute)
File "/Users/mcagataybarin/molocate-dev/env/lib/python2.7/site-packages/rest_framework/fields.py", line 1645, in to_representation
return method(value)
File "/Users/mcagataybarin/molocate-dev/molocate_eb/video/serializers.py", line 13, in get_current_username
self.current_username = self.context['current_username']
KeyError: 'current_username'
How can I fix that ? I checked the DRF documentation and also checked the stackoverflow but couldn't find the right answer. I'd appreciate if you help.
The context is available for anything that is under the top serializer - i.e. applies to Serializers and Fields as well.
Therefore in the CommentSerializer you should have:
self.current_username = self.context['request'].user.username
After a lot of google search, I fixed the problem like this.
class VideoSerializer(serializers.ModelSerializer):
current_username = serializers.SerializerMethodField()
is_deletable = serializers.SerializerMethodField()
tagged_users = EachUserSerializer(many=True, read_only=True)
comments = serializers.SerializerMethodField()
place_taken = PlaceLimitedSerializer()
owner_user = EachUserSerializer()
class Meta:
model = Video
field = ('tagged_users', 'comments', 'place_taken', 'video_id', 'video_url', 'like_count', 'caption', 'date',
'category', 'owner_user', 'is_deletable', )
def get_comments(self, obj):
serializer_context = {'current_username': self.current_username}
serializer = CommentSerializer(obj.comments, many=True, read_only=True, context=serializer_context)
return serializer.data
def get_current_username(self, obj):
self.current_username = self.context['request'].user.username
return self.context['request'].user.username
def get_is_deletable(self, obj):
return obj.is_deletable_by(self.current_username)
class CommentSerializer(serializers.ModelSerializer):
current_username = serializers.SerializerMethodField()
is_deletable = serializers.SerializerMethodField()
is_editable = serializers.SerializerMethodField()
def get_current_username(self, obj):
self.current_username = self.context.get('current_username')
return self.context.get('current_username')
def get_is_deletable(self, obj):
return obj.is_deletable(self.current_username)
def get_is_editable(self, obj):
return obj.is_editable(self.current_username)
class Meta:
model = Comment
fields = ('comment', 'username', 'comment_id', 'date', 'current_username', 'is_editable', 'is_deletable',)
I serialized the nested serialization inside SerializerMethodField and I've sent the current_username that I extract from context to the nester serializer's context. After doing this problem solved and it works :)