rav*_*shi 32 django django-rest-framework
我正在使用Django REST Framework来序列化Django模型.我有一个ListCreateAPIView视图列出对象和一个RetrieveUpdateDestroyAPIView视图来检索/更新/删除单个对象.该模型存储用户自己提交的信息.他们提交的信息包含一些私人信息和一些公共信息.我希望所有用户能够列出和检索公共信息,但我只希望所有者列出/检索/更新/删除私人信息.因此,我需要每个字段的权限而不是对象权限.
我找到的最接近的建议是https://groups.google.com/forum/#!topic/django-rest-framework/FUd27n_k3U0,它会根据请求类型更改序列化程序.这对我的情况不起作用,因为我当时没有查询集或对象来确定它是否归用户所有.
当然,我的前端隐藏了私人信息,但聪明的人仍然可以窥探API请求以获取完整的对象.如果需要代码,我可以提供它,但我的请求适用于vanilla Django REST Framework设计.
jho*_*jho 37
如何根据用户切换序列化程序类?
在文档中:
http://www.django-rest-framework.org/api-guide/generic-views/#get_serializer_classself
def get_serializer_class(self):
if self.request.user.is_staff:
return FullAccountSerializer
return BasicAccountSerializer
Run Code Online (Sandbox Code Playgroud)
Tod*_*dor 14
前几天我遇到了类似的问题.这是我的方法:
DRF 2.4解决方案.class PrivateField(serializers.Field):
def field_to_native(self, obj, field_name):
"""
Return null value if request has no access to that field
"""
if obj.created_by == self.context.get('request').user:
return super(PrivateField, self).field_to_native(obj, field_name)
return None
#Usage
class UserInfoSerializer(serializers.ModelSerializer):
private_field1 = PrivateField()
private_field2 = PrivateField()
class Meta:
model = UserInfo
Run Code Online (Sandbox Code Playgroud)
class PrivateField(serializers.ReadOnlyField):
def get_attribute(self, instance):
"""
Given the *outgoing* object instance, return the primitive value
that should be used for this field.
"""
if instance.created_by == self.context['request'].user:
return super(PrivateField, self).get_attribute(instance)
return None
Run Code Online (Sandbox Code Playgroud)
这次我们ReadOnlyField只是扩展,因为to_representation没有在serializers.Field类中实现.
这里:
--models.py:
class Article(models.Model):
name = models.CharField(max_length=50, blank=False)
author = models.CharField(max_length=50, blank=True)
def __str__(self):
return u"%s" % self.name
class Meta:
permissions = (
# name
('read_name_article', "Read article's name"),
('change_name_article', "Change article's name"),
# author
('read_author_article', "Read article's author"),
('change_author_article', "Change article's author"),
)
Run Code Online (Sandbox Code Playgroud)
-- 序列化器.py:
class ArticleSerializer(serializers.ModelSerializer):
class Meta(object):
model = Article
fields = "__all__"
def to_representation(self, request_data):
# get the original representation
ret = super(ArticleSerializer, self).to_representation(request_data)
current_user = self.context['request'].user
for field_name, field_value in sorted(ret.items()):
if not current_user.has_perm(
'app_name.read_{}_article'.format(field_name)
):
ret.pop(field_name) # remove field if it's not permitted
return ret
def to_internal_value(self, request_data):
errors = {}
# get the original representation
ret = super(ArticleSerializer, self).to_internal_value(request_data)
current_user = self.context['request'].user
for field_name, field_value in sorted(ret.items()):
if field_value and not current_user.has_perm(
'app_name.change_{}_article'.format(field_name)
):
errors[field_name] = ["Field not allowed to change"] # throw error if it's not permitted
if errors:
raise ValidationError(errors)
return ret
Run Code Online (Sandbox Code Playgroud)
我想出了办法.在序列化程序中,我可以访问对象和发出API请求的用户.因此,我可以检查请求者是否是对象的所有者并返回私人信息.如果不是,序列化程序将返回一个空字符串.
class UserInfoSerializer(serializers.HyperlinkedModelSerializer):
private_field1 = serializers.SerializerMethodField('get_private_field1')
class Meta:
model = UserInfo
fields = (
'id',
'public_field1',
'public_field2',
'private_field1',
)
read_only_fields = ('id')
def get_private_field1(self, obj):
# obj.created_by is the foreign key to the user model
if obj.created_by != self.context['request'].user:
return ""
else:
return obj.private_field1
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9561 次 |
| 最近记录: |