Reputation: 33
I am learning how to use djangorestframework by building a microblog and I want users to be able to upload multiple (kind of like how twitter works). I got a particular error(check below) after using a particular approach(check code).
I have attached my models.py, serializers.py and views.py file:
MODELS.PY FILE:
class TweetFile(models.Model):
tweep = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
file = models.FileField(upload_to='images')
class Tweets(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
texts = models.TextField()
file_content = models.ManyToManyField(TweetFile, related_name='file_content')
date_posted = models.DateTimeField(auto_now_add=True)
tweep = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
likes = models.PositiveIntegerField(default=0)
liker = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='user_like')
# link = models.URLField()
class Meta:
# verbose_name = _('my thing')
verbose_name_plural = _('Tweets')
def __str__(self):
return f"{self.texts}"
SERIALIZERS.PY FILE:
class TweetSerializer(serializers.ModelSerializer):
tweep = serializers.SerializerMethodField('get_tweep_username')
likes = serializers.SerializerMethodField('get_tweet_likes')
liker = serializers.StringRelatedField(many=True)
class Meta:
model = Tweets
fields = ['id','texts', 'file_content', 'date_posted', 'tweep', 'likes', 'liker']
extra_kwargs = {
"file_content": {
"required": False,
}
}
VIEWS.PY FILE:
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def create_tweet(request):
user = request.user
if request.method == 'POST':
serializer = TweetSerializer(data=request.data)
if serializer.is_valid():
serializer.save(tweep=user)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
return Response(serializer.errors, status=status.HTTP_405_METHOD_NOT_ALLOWED)
This particular approach gave me this error in my postman:
{ "file_content": [ "Incorrect type. Expected pk value, received InMemoryUploadedFile." ] }.
Could anybody tell me what I am doing wrong? or what I need to do? any help will be appreciated, thanks.
Upvotes: 1
Views: 172
Reputation: 33
Okay, so I found a solution to this issue....and this is the code, hopefully someone finds it helpful:
models.py file
class TweetFile(models.Model):
tweep = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
media = models.FileField(upload_to='images')
def __str__(self):
return f"{self.tweep.username}'s media images"
class Tweets(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
texts = models.TextField()
file_content = models.ManyToManyField(TweetFile, related_name='file_content', blank=True, null=True)
date_posted = models.DateTimeField(auto_now_add=True)
tweep = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
class Meta:
verbose_name_plural = _('Tweets')
def __str__(self):
return f"{self.texts}"
Serializer.py file
from rest_framework import serializers
from tweets.models import Tweets, TweetFile, Comments
class TweetSerializer(serializers.ModelSerializer):
tweep = serializers.SerializerMethodField('get_tweep_username')
class Meta:
model = Tweets
fields = ['id','texts', 'file_content', 'date_posted', 'tweep']
extra_kwargs = {
"file_content": {
"required": False,
}
}
# function that returns the owner of a tweet
def get_tweep_username(self, tweets):
tweep = tweets.tweep.username
return tweep
Views.py file
@api_view(['POST'])
@permission_classes([IsAuthenticated])
@parser_classes([MultiPartParser, FormParser])
def create_tweet(request):
user = request.user
if request.method == 'POST':
files = request.FILES.getlist('file_content')
if files:
request.data.pop('file_content')
serializer = TweetSerializer(data=request.data)
if serializer.is_valid():
serializer.save(tweep=user)
tweet_qs = Tweets.objects.get(id=serializer.data['id'])
uploaded_files = []
for file in files:
content = TweetFile.objects.create(tweep=user, media=file)
uploaded_files.append(content)
tweet_qs.file_content.add(*uploaded_files)
context = serializer.data
context["file_content"] = [file.id for file in uploaded_files]
return Response(context, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
serializer = TweetSerializer(data=request.data)
if serializer.is_valid():
serializer.save(tweep=user)
context = serializer.data
return Response(context, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
return Response(serializer.errors, status=status.HTTP_405_METHOD_NOT_ALLOWED)
configure your urls.py files appropriately and test the endpoint on POSTMAN, everything should work fine.
Upvotes: 1