Dee*_*ena 9 python django django-rest-framework
我想在列表显示中隐藏模型的特定字段,
persons/并显示详细信息显示上的所有字段persons/jane
我对其余框架相对较新,文档感觉很难掌握.
这就是我想要实现的目标.
我有一个简单的Person模型,
# model
class Person(models.Model):
first_name = models.CharField(max_length=30, blank=True)
last_name = models.CharField(max_length=30, blank=True)
nickname = models.CharField(max_length=20)
slug = models.SlugField()
address = models.TextField(max_length=300, blank=True)
Run Code Online (Sandbox Code Playgroud)
和序列化器类
# serializers
class PersonListSerializer(serializers.ModelSerializer):
class Meta:
model = Person
fields = ('nickname', 'slug')
class PersonSerializer(serializers.ModelSerializer):
class Meta:
model = Person
fields = ('first_name', 'last_name', 'nickname', 'slug', 'address')
Run Code Online (Sandbox Code Playgroud)
和视图集.
# view sets (api.py)
class PersonListViewSet(viewsets.ModelViewSet):
queryset = Person.objects.all()
serializer_class = PersonListSerializer
class PersonViewSet(viewsets.ModelViewSet):
queryset = Person.objects.all()
serializer_class = PersonSerializer
Run Code Online (Sandbox Code Playgroud)
在网址上persons我想要显示人员列表,只需要字段nickname,slug并在网址上persons/[slug]我想显示模型的所有字段.
我的路由器配置,
router = routers.DefaultRouter()
router.register(r'persons', api.PersonListViewSet)
router.register(r'persons/{slug}', api.PersonViewSet)
Run Code Online (Sandbox Code Playgroud)
我猜第二种配置是错误的,我怎样才能实现我想做的事情?
更新:
输出到persons/slug是{"detail":"Not found."},但它适用于person/pk
谢谢
Liz*_*Liz 17
对于其他遇到此问题的人,我发现在视图集上覆盖 get_serializer_class 并为每个操作定义一个序列化器是 DRY-est 选项(保留单个视图集但允许动态序列化器选择):
class MyViewset(viewsets.ModelViewSet):
serializer_class = serializers.ListSerializer
permission_classes = [permissions.IsAdminUser]
renderer_classes = (renderers.AdminRenderer,)
queryset = models.MyModel.objects.all().order_by('-updated')
def __init__(self, *args, **kwargs):
super(MyViewset, self).__init__(*args, **kwargs)
self.serializer_action_classes = {
'list':serializers.AdminListSerializer,
'create':serializers.AdminCreateSerializer,
'retrieve':serializers.AdminRetrieveSerializer,
'update':serializers.AdminUpdateSerializer,
'partial_update':serializers.AdminUpdateSerializer,
'destroy':serializers.AdminRetrieveSerializer,
}
def get_serializer_class(self, *args, **kwargs):
"""Instantiate the list of serializers per action from class attribute (must be defined)."""
kwargs['partial'] = True
try:
return self.serializer_action_classes[self.action]
except (KeyError, AttributeError):
return super(MyViewset, self).get_serializer_class()
Run Code Online (Sandbox Code Playgroud)
希望这对其他人有帮助。
小智 10
您可以重写序列化器类的“get_fields”方法并添加类似的内容:
def get_fields(self, *args, **kwargs):
fields = super().get_fields(*args, **kwargs)
request = self.context.get('request')
if request is not None and not request.parser_context.get('kwargs'):
fields.pop('your_field', None)
return fields
Run Code Online (Sandbox Code Playgroud)
在这种情况下,当您获得详细视图时,会有'kwargs': {'pk': 404},当您获得列表视图时,会有'kwargs': {}
我编写了一个名为drf-action-serializer( pypi )的扩展,它添加了一个名为的序列化程序ModelActionSerializer,允许您在每个操作的基础上定义 fields/exclude/extra_kwargs(同时仍然有正常的 fields/exclude/extra_kwargs 可以依靠)。
实现很好,因为您不必覆盖 ViewSetget_serializer方法,因为您只使用一个序列化程序。相关的变化是在序列化程序的get_fields和get_extra_kwargs方法中,它检查视图操作,如果该操作存在于Meta.action_fields字典中,则它使用该配置而不是Meta.fields属性。
在您的示例中,您将执行以下操作:
from action_serializer import ModelActionSerializer
class PersonSerializer(ModelActionSerializer):
class Meta:
model = Person
fields = ('first_name', 'last_name', 'nickname', 'slug', 'address')
action_fields = {
'list': {'fields': ('nickname', 'slug')}
}
Run Code Online (Sandbox Code Playgroud)
您的 ViewSet 将类似于:
class PersonViewSet(viewsets.ModelViewSet):
queryset = Person.objects.all()
serializer_class = PersonSerializer
Run Code Online (Sandbox Code Playgroud)
你的路由器看起来也很正常:
router = routers.DefaultRouter()
router.register(r'persons', api.PersonViewSet)
Run Code Online (Sandbox Code Playgroud)
如果你好奇我是如何实现的:
get_action_config它获取当前视图操作并在action_fields字典中返回该条目:def get_action_config(self):
"""
Return the configuration in the `Meta.action_fields` dictionary for this
view's action.
"""
view = getattr(self, 'context', {}).get('view', None)
action = getattr(view, 'action', None)
action_fields = getattr(self.Meta, 'action_fields', {})
Run Code Online (Sandbox Code Playgroud)
get_field_names了ModelSerializer:从:
fields = getattr(self.Meta, 'fields', None)
exclude = getattr(self.Meta, 'exclude', None)
Run Code Online (Sandbox Code Playgroud)
到:
action_config = self.get_action_config()
if action_config:
fields = action_config.get('fields', None)
exclude = action_config.get('exclude', None)
else:
fields = getattr(self.Meta, 'fields', None)
exclude = getattr(self.Meta, 'exclude', None)
Run Code Online (Sandbox Code Playgroud)
get_extra_kwargs方法:从:
extra_kwargs = copy.deepcopy(getattr(self.Meta, 'extra_kwargs', {}))
Run Code Online (Sandbox Code Playgroud)
到:
action_config = self.get_action_config()
if action_config:
extra_kwargs = copy.deepcopy(action_config.get('extra_kwargs', {}))
else:
extra_kwargs = copy.deepcopy(getattr(self.Meta, 'extra_kwargs', {}))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7805 次 |
| 最近记录: |