禁用在django rest框架中创建嵌套对象

时间:2014-08-01 20:50:46

标签: django angularjs foreign-key-relationship django-rest-framework

您好,

您能帮助我禁用创建嵌套对象吗?

我有这样的序列化程序:
(员工对团队有ForeignKey)

class TeamSerializer(serializers.ModelSerializer):
    class Meta:
        model = Team
        fields = ('id', 'name')
class EmployeeSerializer(serializers.ModelSerializer):
    class Meta:
        model = Employee
        fields = ('id', 'name', 'surname', 'team')
        depth = 1

或者可能是:

class EmployeeSerializer(serializers.ModelSerializer):
    team = TeamSerializer()
    class Meta:
        model = Employee
        fields = ('id', 'name', 'surname', 'team')

当我发布json(创建员工)

{
    name: "name",
    surname: "surname",
    team: {
           id: 1,
           name: "Web Team"
          }
}

对象员工创建但也是对象团队...... 有没有办法禁止与员工一起创建团队对象? 我只想创建员工并将选定的团队(在数据库中)设置为员工

在GET(列表)上,我希望能够检索 数据如:

{
 name: "name",
 surname: "surname",
 team: {
    id: 1,
    name: "Web Team"
 }

不喜欢

{
 name: "name",
 surname: "surname",
 team: 1
}

在django rest框架中是否有任何方法(也使用angular)
此致

更新

目前序列化器:

class TeamSerializer(serializers.ModelSerializer):
    class Meta:
        model = Team

class EmployeeSerializer(serializers.ModelSerializer):
    team = TeamSerializer()

    class Meta:
        model = Employee

我不能使用serializers.RelatedField(),因为它只返回 unicode 我需要'id'和'name'(我想)

这是我的POST json :( Restangular.all('employee')。post(data))

data: {
        name: "emp1",
        photo: "",
        skype: "",
        surname: "qweqwe",
        team: {
              id: 1,
              name: "Web",
        }
}

和DRF返回了json:

employee: {
    id: 2,
    name: "emp1",
    photo: "",
    skype: "",
    surname: "qweqwe",
    team: {
        id:3, <-- NEW ID!
        name: "Web"
    }   
}

所以是的,我确信创建了新的团队对象。那么现在呢?:)

3 个答案:

答案 0 :(得分:2)

我发现最新版本的DRF中不存在ModelSerializer.to_native()ModelSerializer.from_native()。我想出了以下解决方案得出的以下内容:

class PlayerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Player
        fields = ('id', 'name', 'team')

    def to_internal_value(self, data):
        # If team is not a dict, such as when submitting via the Browseable UI, this would fail.
        try:
            data['team'] = data['team']['id']
        except TypeError:
            pass
        return super(PlayerSerializer, self).to_internal_value(data)

    def to_representation(self, instance):
        return ReadPlayerSerializer(instance).data


class ReadPlayerSerializer(serializers.ModelSerializer):
    team = TeamSerializer()

    class Meta(PlayerSerializer.Meta):
        pass

实际上,from_native现在to_representation似乎to_native不是to_internal_value

答案 1 :(得分:1)

好的,首先,您确定已创建嵌套对象吗?因为DRF不是为了创建嵌套对象而设计的,所以这是一种非常奇怪的行为(更确切地说,这是work in progress,正如其创建者Tom Christie所说的那样。

然后,为了获得所需的序列化程序表示,您必须遵循一些规则:

  1. 为每个模型创建一个简单的序列化程序(就像在第一个代码段中一样)

  2. 在EmployeeSerializer上添加FK关系:(小心,要使其正常工作,您必须将您的FK命名为'team') team = serializers.RelatedField()

  3. 在TeamSerializer上添加ManyToOne关系:(只有在获得Team对象时还希望拥有所有员工时才需要这样做;如果没有,则可以跳过此部分) employees = EmployeeSerializer(required = False,many = True)
  4. 此外,您应该从序列化程序中删除 depth 属性,他是使序列化变得扁平化的属性(或者您可以将其设置为2)。希望这会有所帮助。

    <强>更新

    查看多个序列化程序:

    def get_serializer_class(self):
        if self.request.method == 'GET':
            return ReadEmployeeSerializer
        elif self.request.method == 'POST':
            return WriteEmployeeSerializer
        else:
            return DefaultSerializer
    
    class WriteEmployeeSerializer(serializers.ModelSerializer):
        class Meta:
            model = Employee
            fields = ('id', 'name', 'surname', 'team')
    
    class ReadEmployeeSerializer(serializers.ModelSerializer):
        team = TeamSerializer()
        class Meta:
            model = Employee
            fields = ('id', 'name', 'surname', 'team')
    

    有点多余,但应该做好工作。

答案 2 :(得分:0)

解决问题:

class ReadEmployeeSerializer(serializers.ModelSerializer):
    team = TeamSerializer()

    class Meta:
        model = Employee
        fields = ('id', 'name', 'surname', 'team',)


class WriteEmployeeSerializer(serializers.ModelSerializer):

    def from_native(self, data, files):
        data['team'] = data['team']['id']
        return serializers.ModelSerializer.from_native(self, data, files)

    def to_native(self, obj):
        return ReadEmployeeSerializer(obj).data

    class Meta:
        model = Employee
        fields = ('id', 'name', 'surname', 'team',)

post / put方法使用主键(WriteEmployeeSerializer) - 在将dict替换为主键之前

get方法使用完整对象(ReadEmployeeSerializer)