Dorr
Dorr

Reputation: 656

How to get model object with certain key

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

Answers (1)

JPG
JPG

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

Related Questions