how to create a comment system using drf - django

halo i'm working on a project that requires user to give a feedback whenever possible using django rest_framework
but im getting an some difficulties doing that
below is my code snippet & err msg
##mode file
class Review(models.Model):
school = models.ForeignKey(
Profile, on_delete=models.CASCADE, related_name='review')
name = models.CharField(max_length=250, blank=True, null=True)
reviewer_email = models.EmailField()
rating = models.CharField(
max_length=250, blank=True, null=True)
review = models.TextField()
##serializer file
class ReviewSerializer(serializers.ModelSerializer):
class Meta:
model = Review
fields = ('name', 'review', 'id', 'reviewer_email', 'rating')
def perform_create(self, serializer):
id = self.request
print(self.request.user.profile)
serializer.save(school=self.request.user.profile.school_id)
##apiView
class ReviewAPIView(generics.CreateAPIView):
serializer_class = ReviewSerializer
permissions = [permissions.AllowAny]
queryset = Review.objects.all()
err msg
File "/home/olaneat/Desktop/files/project/django/schMrk/lib/python3.8/site-packages/rest_framework/views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "/home/olaneat/Desktop/files/project/django/schMrk/lib/python3.8/site-packages/rest_framework/views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "/home/olaneat/Desktop/files/project/django/schMrk/lib/python3.8/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
raise exc
File "/home/olaneat/Desktop/files/project/django/schMrk/lib/python3.8/site-packages/rest_framework/views.py", line 506, in dispatch
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/lib/python3.8/site-packages/rest_framework/mixins.py", line 19, in create
self.perform_create(serializer)
File "/home/olaneat/Desktop/files/project/django/schMrk/sch-market/schoolDetail/apiviews.py", line 213, in perform_create
print(self.request.user.profile)
AttributeError: 'AnonymousUser' object has no attribute 'profile'
[04/Aug/2021 16:00:59] "POST /school-detail/add-review HTTP/1.1" 500 105554
can anyone help pls

You didn't share the request body.
My guess(from the error) is that you didn't specify the id of the school object it should be related to

You should limit access for non-authorized users. Otherwise, self.request.user could be an AnonymousUser object, which has no a profile relation.
permissions = [permissions.IsAuthenticated]

Related

Django restframework viewset serializer KeyError

I try to POST request but I got KeyError.
Exception Location: C:\github\dj-postgres-heroku\get_staff\serializers.py, line 32, in create
Here is error location and that line is this.
def create(self, validated_data):
**profile_data = validated_data.pop('profile')**
I try to POST data like this.
enter image description here
enter image description here
{
"profile":1,
"title": "일단 10만원, 업무 마친 후 바로 입금",
"hourly_pay": 12500,
"start_date": "2020-05-06",
"end_date": "2020-05-09",
"start_time": "09:00:00",
"end_time": "18:00:00",
"content": "간단업무입니다.",
"jobs":[1, 2]
}
Here are my code all.
models.py
class GetStaffPost(models.Model):
profile = models.ForeignKey(Profile, null=True, on_delete=models.CASCADE) # default=1 -> pk=1
title = models.CharField(max_length=30)
jobs = models.ManyToManyField(Job, blank=True) # tag랑 비슷
hourly_pay = models.IntegerField(null=True)
start_date = models.DateField(null=True)
end_date = models.DateField(null=True)
start_time = models.TimeField(null=True)
end_time = models.TimeField(null=True)
created_at = models.DateTimeField(null=True, auto_now_add=True)
content = models.TextField(default='content')
class Meta:
ordering = ['-created_at']
def __str__(self):
return f'{self.pk}: {self.title} - {self.profile.nickname}'
serializers.py
class GetStaffPostSerializer(serializers.ModelSerializer):
profile = serializers.PrimaryKeyRelatedField(read_only=True)
jobs = serializers.PrimaryKeyRelatedField(read_only=True, many=True)
class Meta:
model = GetStaffPost
# fields = ['id', 'profile', 'title', 'jobs', 'hourly_pay', 'start_date', 'end_date',
# 'start_time', 'end_time', 'created_at', 'content']
fields = "__all__"
def create(self, validated_data): # profile, jobs
profile_data = validated_data.pop('profile')
profile_id = profile_data
profile = Profile.objects.get(pk=profile_id)
jobs_data = validated_data.pop('jobs') # list?
post = GetStaffPost.objects.create(**validated_data,
profile=profile) # Direct assignment to the forward side of a many-to-many set is prohibited. Use jobs.set() instead.
for job_data in jobs_data:
post.jobs.add(Job.objects.get(pk=job_data))
return profile
views.py
class GetStaffPostViewSet(viewsets.ModelViewSet):
queryset = GetStaffPost.objects.all()
serializer_class = GetStaffPostSerializer
def perform_create(self, serializer):
serializer.save()
when POST request , I want to write only profile pk and jobs pk list. not all fields in model Profile and Jobs.
And when GET request, I want to show all fields.
This is Traceback.
[17/Nov/2021 12:31:43] "GET /get_staff/post/ HTTP/1.1" 200 16613
Internal Server Error: /get_staff/post/
Traceback (most recent call last):a
File "C:\github\dj-postgres-heroku\venv\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "C:\github\dj-postgres-heroku\venv\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\github\dj-postgres-heroku\venv\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "C:\github\dj-postgres-heroku\venv\lib\site-packages\rest_framework\viewsets.py", line 125, in view
return self.dispatch(request, *args, **kwargs)
File "C:\github\dj-postgres-heroku\venv\lib\site-packages\rest_framework\views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "C:\github\dj-postgres-heroku\venv\lib\site-packages\rest_framework\views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "C:\github\dj-postgres-heroku\venv\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception
raise exc
File "C:\github\dj-postgres-heroku\venv\lib\site-packages\rest_framework\views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "C:\github\dj-postgres-heroku\venv\lib\site-packages\rest_framework\mixins.py", line 19, in create
self.perform_create(serializer)
File "C:\github\dj-postgres-heroku\get_staff\views.py", line 21, in perform_create
serializer.save()
File "C:\github\dj-postgres-heroku\venv\lib\site-packages\rest_framework\serializers.py", line 205, in save
self.instance = self.create(validated_data)
File "C:\github\dj-postgres-heroku\get_staff\serializers.py", line 32, in create
profile_data = validated_data.pop('profile')
KeyError: 'profile'
As you add profile field read_only=True thats why validated_data doesn't have profile key.
Provode profile primary key in request body and remove read_only=True from profile field.

How to redirect to post detail page after deleting a comment in Django?

Can someone help me out please.
I want to redirect to a post detail page after deleting a comment of a given pk.
I got an AttributeError when ever I hit the comment delete button.
Error: function object has no attribute 'format'
If I change my success_url of the comment delete view to redirect to post list page with no argument, it works well but that's not what I want. I need the user to be redirected to post detail page after deleting a comment.
Here's my Post model
class Post(models.Model):
STATUS_CHOICES = (
('draft', 'Draft'),
('published', 'Published'),
)
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250, unique_for_date='publish')
author = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, related_name='blog_posts')
body = models.TextField()
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='published')
objects = models.Manager()
published = PublishedManager()
tags = TaggableManager()
class Meta:
ordering = ('-publish',)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post_detail', args=[self.pk, self.slug])
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super().save(*args, **kwargs)'''
Comment model
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
author = models.ForeignKey(get_user_model(), on_delete=models.CASCADE,)
comment = models.TextField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=True)
class Meta:
ordering = ('created',)
def __str__(self):
return f'Comment by {self.author} on {self.post}'
def get_absolute_url(self):
return self.post.get_absolute_url() + f'#comment-{self.pk}'
CommentDeleteView
class CommentDeleteView(DeleteView):
model = Comment
template_name = 'comment_delete.html'
def success_url(self):
post = Post.objects.get(pk=self.object.post.pk)
return post.get_absolute_url()
And the full error
Internal Server Error: /blog/13/comment_delete/
Traceback (most recent call last):
File "C:\Users\SUNNY\blog_folder\ven\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
response = get_response(request)
File "C:\Users\SUNNY\blog_folder\ven\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\SUNNY\blog_folder\ven\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\SUNNY\blog_folder\ven\lib\site-packages\django\views\generic\base.py", line 71, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Users\SUNNY\blog_folder\ven\lib\site-packages\django\views\generic\base.py", line 97, in dispatch
return handler(request, *args, **kwargs)
File "C:\Users\SUNNY\blog_folder\ven\lib\site-packages\django\views\generic\edit.py", line 218, in post
return self.delete(request, *args, **kwargs)
File "C:\Users\SUNNY\blog_folder\ven\lib\site-packages\django\views\generic\edit.py", line 212, in delete
success_url = self.get_success_url()
File "C:\Users\SUNNY\blog_folder\ven\lib\site-packages\django\views\generic\edit.py", line 222, in get_success_url
return self.success_url.format(**self.object.__dict__)
AttributeError: 'function' object has no attribute 'format'
[19/Jun/2020 11:50:28] "POST /blog/13/comment_delete/ HTTP/1.1" 500 88418
To configure the DeleteView success URL, you have to override the method get_success_url(). See that the method where you are implementing the success URL doesn't match that name, instead, its super class is trying to access the success_url property in the default get_success_url(), giving you that error.

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/

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.

DRF Serializer fields DictField() AttributeError: 'str' object has no attribute 'items'

In django rest framework If i use DictField() in serializer its given me AttributeError at /api/v1/analytics/reports-configuration/1/
‘str’ object has no attribute ‘items’ error.please take a look.
serializers.py
import json
from rest_framework import serializers
from models import ReportConfiguration
class ReportConfigurationSerializer(serializers.ModelSerializer):
report_type = serializers.ChoiceField(choices=['query', 'activity', 'summary'])
read_only = serializers.BooleanField(required=True)
query_data = serializers.DictField(required=True)
class Meta:
model = ReportConfiguration
fields = ('id', 'title', 'query_data', 'created_by', 'last_activity_by', 'deleted',
'deleted_by', 'added_at', 'last_activity_at', 'report_type', 'read_only')
def validate(self, data):
if data['report_type'] is not 'summary' and data['read_only'] is True:
raise serializers.ValidationError("If read only true then report type should be summary")
if data['report_type'] is 'summary' and data['read_only'] is not True:
raise serializers.ValidationError("If read only not true then report type should not be summary")
return data
def create(self, validated_data):
validated_data['created_by'] = self.context['request'].user
validated_data['last_activity_by'] = self.context['request'].user
return ReportConfiguration.objects.create(**validated_data)
views.py
class ReportConfigurationViewSet(viewsets.ModelViewSet):
serializer_class = ReportConfigurationSerializer
queryset = ReportConfiguration.objects.all()
permission_classes = (permissions.IsAuthenticated,)
filter_backends = (DjangoFilterBackend,)
filter_class = ReportFilter
def list(self, request):
response = super(ReportConfigurationViewSet, self).list(request)
for data in response.data['results']:
data['query_data'] = json.loads(data['query_data'])
return response
def retrieve(self, request, pk=None):
response = super(ReportConfigurationViewSet, self).retrieve(request, pk=pk)
response.data['query_data'] = json.loads(response.data['query_data'])
return response
models.py
class ReportConfiguration(models.Model):
class ReportTypeChoice(Choice):
QueryReport = 'query'
ActivityReport = 'activity'
SummaryList = 'summary'
title = models.CharField(max_length=300, unique=True, blank=False, null=False)
query_data = JSONField(default={})
created_by = models.ForeignKey(User, null=True, blank=True, related_name='report_created_by')
last_activity_by = models.ForeignKey(User, null=True, blank=True,related_name='last_active_in_report')
deleted = models.BooleanField(default=False)
deleted_by = models.ForeignKey(User, null=True, blank=True, related_name='report_deleted_by')
added_at = models.DateTimeField(auto_now_add=True)
last_activity_at = models.DateTimeField(default=timezone.now)
report_type = models.CharField(max_length=15, choices=ReportTypeChoice)
read_only = models.BooleanField(default=False)
Error:
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
ERROR Internal Server Error: /api/v1/analytics/reports-configuration/1/
Traceback (most recent call last):
File "/Users/ranvijay.s/.virtualenvs/my_project/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/ranvijay.s/.virtualenvs/my_project/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/ranvijay.s/.virtualenvs/my_project/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
return view_func(*args, **kwargs)
File "/Users/ranvijay.s/.virtualenvs/my_project/lib/python2.7/site-packages/rest_framework/viewsets.py", line 83, in view
return self.dispatch(request, *args, **kwargs)
File "/Users/ranvijay.s/.virtualenvs/my_project/lib/python2.7/site-packages/rest_framework/views.py", line 477, in dispatch
response = self.handle_exception(exc)
File "/Users/ranvijay.s/.virtualenvs/my_project/lib/python2.7/site-packages/rest_framework/views.py", line 437, in handle_exception
self.raise_uncaught_exception(exc)
File "/Users/ranvijay.s/.virtualenvs/my_project/lib/python2.7/site-packages/rest_framework/views.py", line 474, in dispatch
response = handler(request, *args, **kwargs)
File "/Users/ranvijay.s/wk/project/django/dhanalytics/views.py", line 47, in retrieve
response = super(ReportConfigurationViewSet, self).retrieve(request, pk=pk)
File "/Users/ranvijay.s/.virtualenvs/my_project/lib/python2.7/site-packages/rest_framework/mixins.py", line 58, in retrieve
return Response(serializer.data)
File "/Users/ranvijay.s/.virtualenvs/my_project/lib/python2.7/site-packages/rest_framework/serializers.py", line 527, in data
ret = super(Serializer, self).data
File "/Users/ranvijay.s/.virtualenvs/my_project/lib/python2.7/site-packages/rest_framework/serializers.py", line 262, in data
self._data = self.to_representation(self.instance)
File "/Users/ranvijay.s/.virtualenvs/my_project/lib/python2.7/site-packages/rest_framework/serializers.py", line 496, in to_representation
ret[field.field_name] = field.to_representation(attribute)
File "/Users/ranvijay.s/.virtualenvs/my_project/lib/python2.7/site-packages/rest_framework/fields.py", line 1601, in to_representation
for key, val in value.items()
AttributeError: 'str' object has no attribute 'items'