2017-06-26 48 views
2

大家好!Django Rest框架ParentRelatedField元数据选择

我有最新Django的休息框架,我试图使串行显示可能的选择为每个字段上OPTIONS请求。

这里是我的模型

# models.py 
class Task(models.Model): 
    parent = models.ForeignKey('self', 
          blank=True, null=True, related_name='child_tasks') 
    title = models.CharField(max_length=128) 
    status = models.CharField(max_length=16, choices=STATUS_CHOISES, default='new') 
    priority = models.CharField(max_length=16, choices=PRIORITY_CHOISES, default='1') 
    chief = models.ForeignKey('users.SystemUser', related_name='tasks', 
          blank=True, null=True) 

的一部分,这里的串行

# serializers.py 
class ParentRelatedField(serializers.PrimaryKeyRelatedField): 
    def get_queryset(self): 
     obj = self.context['view'].get_object() 
     return Task.objects.exclude(pk=obj.pk) 


def get_user_choices(): 
    return tuple([(i.id, i.system_name) for i in SystemUser.objects.all()]) 


class TaskDetailSerializer(serializers.Serializer): 
    title = serializers.CharField() 
    parent = ParentRelatedField(
     required=False, allow_null=True 
    ) 
    status = serializers.ChoiceField(choices=STATUS_CHOISES) 
    priority = serializers.ChoiceField(choices=PRIORITY_CHOISES) 
    chief = serializers.ChoiceField(choices=get_user_choices(), required=False) 

我实现了为chief场使用get_user_choices功能,所以我得到:

"chief": { 
    "type": "choice", 
    "required": false, 
    "read_only": false, 
    "label": "Chief", 
    "choices": [ 
     { 
      "value": 1, 
      "display_name": "First User Name" 
     } 
    ] 
} 

ParentRelatedField的伟大工程用于验证,但不用于元数据:

"parent": { 
    "type": "field", 
    "required": false, 
    "read_only": false, 
    "label": "Parent" 
} 

我不能使用ChoiceField与功能(如在chief)对于因为parent选择必须排除当前Task对象。

回答

2

解决了这个问题。

解决方法发现在drf 3.4 announcementdrf issue comments

我改变了我的领域,使之更加普遍

class SelfExcludingRelatedField(serializers.PrimaryKeyRelatedField): 
    def get_queryset(self): 
     obj = self.context['view'].get_object() 
     return self.queryset.exclude(pk=obj.pk) 

然后写定制metadata类(从GitHub复制)。

class CustomMetadata(SimpleMetadata): 
    def get_field_info(self, field): 
     field_info = super().get_field_info(field) 

     if (not field_info.get('read_only') and 
       isinstance(field, SelfExcludingRelatedField) and 
       hasattr(field, 'choices')): 
      field_info['choices'] = [ 
       { 
        'value': choice_value, 
        'display_name': choice_name 
       } 
       for choice_value, choice_name in field.choices.items() 
      ] 

     return field_info 

并把它添加到settings

REST_FRAMEWORK = { 
    'DEFAULT_METADATA_CLASS': 'api_v0.metadata.CustomMetadata', 
}