代码之家  ›  专栏  ›  技术社区  ›  wakey

不要在django中创建子对象

  •  1
  • wakey  · 技术社区  · 7 年前

    Status -还有一把外键 地位 从一个 Object 地位 条目(有一组5个预定义的条目迁移到数据库中)。我相信我已经找到了如何构造序列化程序的方法,以便只重用现有的 但我不确定这样做是否是最好的方式。。。

    一些简化代码:

    class StatusSerializer(serializers.ModelSerializer):
        class Meta:
            model = Status
            fields = ('name',)
    
        def to_representation(self, obj):
            return obj.name
    
        def to_internal_value(self, data):
            return {
                'name': data
            }
    
    
    class ObjectSerializer(serializers.ModelSerializer):
    
        status = StatusSerializer(read_only=True)
    
        class Meta:
            model = Object
            fields = ('obj_name', 'status',)
    
        def create(self, validated_data):
            # We do not want to create new statuses - only use existing ones
            status = Status.objects.get(name=self.initial_data['status'])
            return Object.objects.create(status=status, **validated_data)
    
        def update(self, instance, validated_data):
    
            instance.obj_name = validated_data.get('obj_name', instance.obj_name)
    
            # We do not want to create new statuses - only use existing ones
            instance.status = Status.objects.get(name=self.initial_data['status']) if 'status' in self.initial_data else instance.status
    
            return instance
    

    如上图所示,我还将 地位 对象显示时-例如,我转动以下

    {
        'obj_name': 'ObjectName',
        'status': {
            'name': 'StatusName'
        }
    }
    

    进入这个

    {
        'obj_name': 'ObjectName',
        'status': 'StatusName'
    }
    

    这看起来很好——但是 名字。 现在,api将弹出一个 Status.DoesNotExist 其中一个 Status.objects.get(...) 请求-我是否应该捕获它并重新引发序列化程序/视图所期望的内容?

    编辑:意识到我的问题不太清楚。。。

    1. 地位 对象-并强制 对象 created将使用这些状态之一?
    2. 对象 带着一个病人 名字?
    1 回复  |  直到 7 年前
        1
  •  1
  •   Ritesh Agrawal    7 年前

    你可以用 validate 中的方法 ObjectSerializer

    class ObjectSerializer(serializers.ModelSerializer):
    
        status = StatusSerializer(read_only=True)
    
        class Meta:
            model = Object
            fields = ('obj_name', 'status',)
    
        def validate(self, attrs):
             validated_data = super().validate(attrs)
             status = self.initial_data.get('status')
             # Here assuming that None is not the valid value for status
             if status is not None:
                 status_obj = Status.objects.filter(name=status)
                 if not status_obj:
                     raise serializer.ValidationError('Invalid Status')
                 status_obj = status_obj[0]
                 validated_data['status'] = status_obj
            return validated_data
    
        # Nothing special to be done in create/update since we are sending data
        # in validated_data which will directly sent to the instance.
    
        # def create(self, validated_data):
            # We do not want to create new statuses - only use existing ones
            # status = Status.objects.get(name=self.initial_data['status'])
            #return Object.objects.create(status=status, **validated_data)
    
        #def update(self, instance, validated_data):
    
            # instance.obj_name = validated_data.get('obj_name', instance.obj_name)
    
            # We do not want to create new statuses - only use existing ones
            # instance.status = Status.objects.get(name=self.initial_data['status']) if 'status' in self.initial_data else instance.status
    
            # return instance
    

    如果你能用不同的键来写和读 status ,则可以修改 对象序列化程序 这样地:

    class ObjectSerializer(serializer.ModelSerializer):
        status = serializer.SlugRelatedField(slug_field='name', queryset=Status.objects.all(), write_only=True)
        status_data = StatusSerializer(read_only=True, source='status')
    
        class Meta:
            model = Object
            fields = ('obj_name', 'status', 'status_data')
    

    {'obj_name': 'ObjectName', 'status': 'StatusName'} 数据到序列化程序,序列化程序将首先检查 StatusName 价值 name all )如果不是有效的加薪 ValidationError 地位 在实例的字段中。