I have my follow model:
class Follow(models.Model):
user = models.ForeignKey(
"User", related_name="follower", on_delete=models.CASCADE)
following_user = models.ForeignKey(
"User", related_name="following", blank=True, on_delete=models.CASCADE)
date_followed = models.DateTimeField(editable=False, default=timezone.now)
class Meta:
constraints = [
models.UniqueConstraint(
fields=['user', 'following_user'], name="unique_followers")
]
ordering = ["-date_followed"]
def __str__(self):
return f"{self.user.username} follows {self.following_user.username}"
and serializer:
class FollowSerializer(serializers.ModelSerializer):
class Meta:
model = Follow
fields = ['user', 'following_user', 'date_followed']
Then in my views I have an APIView that creates the follow:
class FollowingView(APIView):
permission_class = [permissions.IsAuthenticated]
queryset = Follow.objects.all()
serializer_class = FollowSerializer
def post(self, request):
user = request.data.get('user')
following_user = request.data.get('to_user')
try:
follow = Follow.objects.create(
user=user, following_user=following_user)
follow.save()
serializer = FollowSerializer(follow)
print(serializer.data)
def __str__(self):
return f"{self.request.username} follows {self.following_user_id.username}"
return Response(serializer.data, status=status.HTTP_201_CREATED)
except:
return Response(status=status.HTTP_400_BAD_REQUEST)
Not sure what is wrong. I am able to print the params but seems like the create function isn't going through.
Appreciate any help!
CodePudding user response:
First problem is in this line:
following_user = request.data.get('to_user')
There is no such to_user
field in your serializer, thus the value you are fetching from request is None
. Replace the variable accordingly.
following_user = request.data.get('following_user')
Secondly, are trying to create your Follow
objects directly with IDs instead of user instances, just fetch User instances before trying to create the object.
from rest_framework import permissions
from core.models import Follow
from core.api.serializers import FollowSerializer
from django.contrib.auth import get_user_model
class FollowingView(APIView):
permission_class = [permissions.IsAuthenticated]
queryset = Follow.objects.all()
serializer_class = FollowSerializer
def post(self, request):
user_id = request.data.get('user')
following_user_id = request.data.get('following_user')
user = get_object_or_404(get_user_model(), id=user_id)
following_user = get_object_or_404(get_user_model(), id=following_user_id)
try:
follow = Follow.objects.create(
user=user, following_user=following_user)
follow.save()
serializer = FollowSerializer(follow)
print(serializer.data)
def __str__(self):
return f"{self.request.username} follows {self.following_user_id.username}"
return Response(serializer.data, status=status.HTTP_201_CREATED)
except:
return Response(status=status.HTTP_400_BAD_REQUEST)
Edit: Refer to @Ankit Tiwari answer on how to properly use the serializer to validate data
CodePudding user response:
First set read_only=True
to user & following_user fields if it's not getting data from client.
class FollowSerializer(serializers.ModelSerializer):
user = serializers.PrimaryKeyRelatedField(many=False, read_only=True)
following_user = serializers.PrimaryKeyRelatedField(many=False, read_only=True)
class Meta:
model = Follow
fields = ['user', 'following_user', 'date_followed']
and inside your view just validate your serializer and save it with related fields
class FollowingView(APIView):
permission_class = [permissions.IsAuthenticated]
queryset = Follow.objects.all()
serializer_class = FollowSerializer
def post(self, request):
user = request.data.get('user')
following_user = request.data.get('to_user') # check if it's correct
try:
user = User.objects.get(id=user)
following_user = User.objects.get(id=following_user)
serializer = FollowSerializer(request.data)
if serializer.is_valid():
serializer.save(
user=user,
following_user=following_user
)
def __str__(self):
return f"{self.request.username} follows {self.following_user_id.username}"
return Response(serializer.data, status=status.HTTP_201_CREATED)
except:
return Response(status=status.HTTP_400_BAD_REQUEST)
CodePudding user response:
You need to remove .save()
method which used with object.create
.
object.create
used for save data object in table so, no need to .save()
follow = Follow.objects.create(user=user, following_user=following_user)
serializer = FollowSerializer(follow)
print(serializer.data)
You can also save data and serialize it with APIView()
approach like this
def post(self, request):
serializer = FollowSerializer(data=request.data)
print(serializer.is_valid()) ## for debug
print(serializer.errors) ## for debug
if serializer.is_valid():
serializer.save()
return Response({'msg':'Data Created'}, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)