如何为模型添加权限,以便任何用户都可以添加新实例,但是只有登录用户才能添加特定属性?
Django models.py
:
class Ingredient(models.Model):
name = models.CharField(max_length=100, unique=True)
recipes = models.ManyToManyField(Recipe, related_name='ingredients', blank=True)
DRF views.py
:
class IngredientViewSet(viewsets.ModelViewSet):
queryset = Ingredient.objects.all()
serializer_class = IngredientSerializer
permission_classes = (IsUserForRecipeOrBasicAddReadOnly,)
DRF permissions.py
:
class IsUserForRecipeOrBasicAddReadOnly(permissions.BasePermission):
"""
Custom permission to only allow logged in users to add an ingredient AND associate its recipe(s).
"""
message = 'You must be logged in to add an Ingredient to a Recipe.'
# using this method so I can access the model obj itself
def has_object_permission(self, request, view, obj):
# Read permissions are allowed to any request,
if request.method in permissions.SAFE_METHODS:
return True
# Check if we are creating, and if the recipes are included, and if they are not a user. If so, return False
if request.method == 'POST' and obj.recipes.all().count() > 0 and request.user.is_anonymous:
return False
else:
return True
我看到了对自定义权限类的适当调用/打印,但是我仍然可以通过配方id
的列表发出POST请求,并且不会出现错误消息。
注释-
答案 0 :(得分:2)
我认为一种更好的方法是使用2个不同的序列化器(其中一个具有Recipes作为可写字段,另一个没有),然后覆盖get_serializer_class
:
class yourMOdelviewset():
...
...
def get_serializer_class(self):
if self.action == 'create':
if self.request.user.is_authenticated:
return SerializerThatHasRecipesAsAWriteableField
else:
return SerializerThatHasNot
return super().get_serializer_class()
p.s。 Drf使用对象级别权限进行检索或更新(基本上应该已经有一个对象),因为在create
中还没有对象,因此drf从不检查对象级别权限。
答案 1 :(得分:2)
@changak提出的解决方案是一个很好的解决方案。将其包括在内是对提出的问题的更直接解决方案。在DRF中,Ionic
明确地用于数据库中已经存在的对象,但是您可以使用has_object_permission
。摘录自the docs,解释了为什么您看不到被称为has_permission
的原因:
注意:实例级的has_object_permission方法仅适用于 如果视图级别的has_permission检查已通过,则调用此方法。
在has_object_permission
中,您仍然有权访问数据,并可以添加支票。假设您的has_permission
有一个IngredientSerializer
字段,则可以使用以下内容进行检查:
recipes