marin marin - 1 month ago 16
JSON Question

Django DRF serializer on PrimaryKeyRelatedField

Question about PrimaryKeyRelatedField serialization in Django DRF version 3.4.7.

models



class UserModel(AbstractEmailUser):

created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

def __str__(self):
return str(self.email)
class Conversation(models.Model):
admin = models.ForeignKey('UserModel', db_index=True, related_name='admin_user')
patient = models.ForeignKey('UserModel', db_index=True)

subject = models.CharField(max_length=255, db_index=True)

user_reply = models.BooleanField(default=False)
admin_seen = models.BooleanField(default=False)

expire = models.DateTimeField()

conversation_type = models.ForeignKey('ConversationType', db_index=True)

created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

def __str__(self):
return str(self.admin)


class ConversationMessages(models.Model):

text = models.TextField(db_index=True)

conversation = models.ForeignKey('Conversation', db_index=True, related_name='msg_conv')
user = models.ForeignKey('UserModel', db_index=True)

created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

def __str__(self):
return str(self.user)


class ConversationFiles(models.Model):
message = models.ForeignKey('ConversationMessages', db_index=True, related_name='message')
file = models.FileField(upload_to='conversations', db_index=True)

def __str__(self):
return str(self.user)


Every model has related field for Rest Framework.
Logic is create conversation, then take ID from conversation and save message model.

serialize's



class MessagesSerializer(serializers.ModelSerializer):
text = serializers.CharField(required=False)
conversation = serializers.PrimaryKeyRelatedField(queryset=Conversation.objects.all(), required=False)
user = serializers.PrimaryKeyRelatedField(queryset=UserModel.objects.all(), required=False)

class Meta:
model = ConversationMessages



class ConversationSerializer(serializers.ModelSerializer):

admin = serializers.PrimaryKeyRelatedField(queryset=UserModel.objects.all(), required=False)
msg_conv = MessagesSerializer()

class Meta:
model = Conversation

def create(self, validated_data):
msg_conv = validated_data.pop('msg_conv', None)
admin_user = Conversation.objects.create(**validated_data)
ConversationMessages.objects.create(conversation_id=Conversation.objects.get(id=admin_user.id).id, **msg_conv)

return admin_user


Serializer is problem on POST method. Everything works great POST object create data in database, but problem is when serializer save object i get this message: 'RelatedManager' object has no attribute 'conversation'.

View



class ConversationView(APIView):

authentication_classes = (JSONWebTokenAuthentication,)

@parser_classes((FormParser, MultiPartParser, FileUploadParser))
def post(self, request):
admin = request.user.id
data = request.data

my_time = datetime.datetime.strptime('07/05/15', '%m/%d/%y')
my_time = my_time.replace(hour=23, minute=59)

data['admin'] = admin
data['expire'] = my_time

data['msg_conv']['user'] = admin

serializer = ConversationSerializer(data=data)

if serializer.is_valid():
serializer.save()

return Response(data={'success': True, 'user': serializer.data}, status=status.HTTP_200_OK)
else:
return Response(data={'success': False, 'msg': serializer.errors}, status=status.HTTP_400_BAD_REQUEST)


POST json



{

"subject":"aloha",
"conversation_type":1,
"patient":3,

"msg_conv":{
"text":"ovo je neki teks"
}
}


Can't figure out how to return data from serializer to view.

Django version : 1.10.2
Python: 3.4.3

Answer

The issue is there:

class ConversationSerializer(serializers.ModelSerializer):

    msg_conv = MessagesSerializer()

By doing this, you are saying that Conversation has a FK to Message. Therefore DRF tries to do the mapping and fails because it's the oposit.

You just need to add the many=True argument to let DRF knows this is a reversed FK.