首页 > 解决方案 > 如何获取具有特定键的模型对象

问题描述

我不想发布整个Serverjson,而是只想发布ip字段并从它的模型中获取对象。

但是如果我发布数据,它就会抱怨;如果我使用其他键而不是Server通过创建发布ServerIP = serializers.CharField(),它会显示 AttributeError。我怎样才能做到这一点?

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

标签: django

解决方案


由于您使用的是嵌套序列化程序,因此 DRF 在反序列化过程中需要一个类似字典的对象。

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

参考: DRF:使用嵌套序列化程序的简单外键分配?


推荐阅读