Reputation: 656
Instead of posting entire Server
json, I want to post only ip
field and get the object from it's model.
But if I post the data, it complains; if I posting with other key than Server
by creating ServerIP = serializers.CharField()
, it shows AttributeError. How can I achieve this?
curl -X POST --header 'Content-Type: application/json' --header 'Accept: text/plain' -d ' \
{ \
"Destination": "destination information", \
"Server": "165.213.100.100" \
} \
' 'http://localhost:8001/api/server/registration'
{
"Server": {
"non_field_errors": [
"Invalid data. Received str instead of dictionary."
]
}
}
class Server(models.Model):
class Meta:
unique_together = ('ip',)
hostname = models.CharField(default=None, null=True, blank=True, max_length=100)
ip = models.GenericIPAddressField(default=None, null=True, blank=True)
class Registration(models.Model):
class Meta:
unique_together = ('Server', 'Destination')
Server = models.ForeignKey(Server, default=None, blank=True, \
null=True, on_delete=models.SET_NULL, related_name='firewall_server')
Destination = models.CharField(default=None, blank=True, null=True, max_length=100)
class RegistrationView(ListCreateAPIView):
serializer_class = RegistrationSerializer
queryset = Registration.objects.all()
def get_serializer(self, *args, **kwargs):
if self.request.method.lower() == 'post':
data = kwargs.get('data')
kwargs['many'] = isinstance(data, list)
return super(RegistrationView, self).get_serializer(*args, **kwargs)
def perform_create(self, serializer):
return serializer.save()
class RegistrationSerializer(serializers.ModelSerializer):
class Meta:
model = Registration
fields = '__all__'
validators = []
Server = ServerSerializer(read_only=False, many=False, required=False)
def create(self, validated_data):
destination = validated_data.pop('Destination')
server_ip = validated_data.pop('Server') # <<= Here. It can't parse string.
server = Server.objects.get(ip=server_ip)
serialized, _ = Registration.objects.update_or_create(
Type=security_type, Server=server, Destination=destination,
defaults=validated_data)
return serialized
Upvotes: 0
Views: 38
Reputation: 88499
Since you are using nested serializer, DRF expects a dictionary-like object during the deserialization process.
class RegistrationSerializer(serializers.ModelSerializer):
# other piece of code
Server = serializers.CharField()
def to_representation(self, instance):
rep = super().to_representation(instance)
rep['Server'] = ServerSerializer(instance.Server).data
return rep
Reference: DRF: Simple foreign key assignment with nested serializers?
Upvotes: 2