Django:过滤请求结果以仅包含与请求用户相关的数据
Django: Filter request results to only contain data related to the requesting user
我是 Django 初学者(尽管我确实有使用 Sails.js + Angular 进行 Web 开发的经验)所以请耐心等待。
我有一个现有应用程序使用 REST API 在 Sails.js 后端和 AngularJS 前端之间进行通信。现在,我们发现后端不适合我们的目的,我们将在不久的将来改用 Django。 Sails.js 会自动为控制器创建 REST 方法,而 Django 不会,所以我想我将使用 Django Rest Framework 之类的东西来创建 API.
是的,我已经找到了大部分内容的相应功能。我还没有找到的东西是 Sails.js 功能的替代品 "policies"。它们是可以在对某些控制器操作的查询上执行的函数,并且可以定义为特定于模型、特定于模型-控制器操作和特定于请求类型。例如,您可以有一个“authAccess
”策略来检查请求的用户是否经过身份验证,并且在执行实际请求的控制器方法之前执行该策略。您还可以使用它们在将请求对象传递给控制器之前修改它们。现在解决我的实际问题:
假设我有一个 User
模型,它与另一个模型具有多对一关系,我们称它为 Book
,这意味着用户可以拥有很多书,但一本书可以只有一个主人。好样的。现在,我们有一个登录用户正在查询以查找他的所有书籍。他向 /book
发出 GET 请求。我想确保返回的 Book
对象被过滤,以便只返回他的书。
所以基本上在 Sails 中,我能够编写一个策略,将请求参数更改为类似于 {user: loggedInUser}
,因此生成的 Book
结果会自动过滤。这很方便,因为我也可以使用相同的策略来过滤其他模型,例如 DVD
或 Friend
等等。我的问题是 - 在 Django 中实现相同功能的最佳方式是什么?
查看文档:
http://www.django-rest-framework.org/api-guide/filtering/#filtering-against-the-current-user
很可能您最好在模型视图集中覆盖 get_queryset 方法。您可以通过为您的视图创建基础 class 来使其成为一种通用方法,例如:
from rest_framework import generics, viewsets, mixins, generics
class OwnerModelViewSet(viewsets.ModelViewSet):
def get_queryset(self):
"""
This view should return a list of all the records
for the currently authenticated user.
"""
return self.model.objects.filter(user=self.request.user)
您所有的模型视图集 classes 都可以从那个 class 继承。不过,它要求外键字段始终命名为 "user"。如果不是这种情况,这里有一个稍微老套的方法,你可以找到用户 table 的外键字段。小心使用。
from django.db.models.fields.related import ForeignKey
from accounts.models import User
def _get_related_user(self, obj):
'''
Search for FK to user model and return field name or False if no FK.
This can lead to wrong results when the model has more than one user FK.
'''
for f in self.model._meta.fields:
if isinstance(f, ForeignKey) and f.rel.to == User:
return f.name
return False
我是 Django 初学者(尽管我确实有使用 Sails.js + Angular 进行 Web 开发的经验)所以请耐心等待。
我有一个现有应用程序使用 REST API 在 Sails.js 后端和 AngularJS 前端之间进行通信。现在,我们发现后端不适合我们的目的,我们将在不久的将来改用 Django。 Sails.js 会自动为控制器创建 REST 方法,而 Django 不会,所以我想我将使用 Django Rest Framework 之类的东西来创建 API.
是的,我已经找到了大部分内容的相应功能。我还没有找到的东西是 Sails.js 功能的替代品 "policies"。它们是可以在对某些控制器操作的查询上执行的函数,并且可以定义为特定于模型、特定于模型-控制器操作和特定于请求类型。例如,您可以有一个“authAccess
”策略来检查请求的用户是否经过身份验证,并且在执行实际请求的控制器方法之前执行该策略。您还可以使用它们在将请求对象传递给控制器之前修改它们。现在解决我的实际问题:
假设我有一个 User
模型,它与另一个模型具有多对一关系,我们称它为 Book
,这意味着用户可以拥有很多书,但一本书可以只有一个主人。好样的。现在,我们有一个登录用户正在查询以查找他的所有书籍。他向 /book
发出 GET 请求。我想确保返回的 Book
对象被过滤,以便只返回他的书。
所以基本上在 Sails 中,我能够编写一个策略,将请求参数更改为类似于 {user: loggedInUser}
,因此生成的 Book
结果会自动过滤。这很方便,因为我也可以使用相同的策略来过滤其他模型,例如 DVD
或 Friend
等等。我的问题是 - 在 Django 中实现相同功能的最佳方式是什么?
查看文档: http://www.django-rest-framework.org/api-guide/filtering/#filtering-against-the-current-user
很可能您最好在模型视图集中覆盖 get_queryset 方法。您可以通过为您的视图创建基础 class 来使其成为一种通用方法,例如:
from rest_framework import generics, viewsets, mixins, generics
class OwnerModelViewSet(viewsets.ModelViewSet):
def get_queryset(self):
"""
This view should return a list of all the records
for the currently authenticated user.
"""
return self.model.objects.filter(user=self.request.user)
您所有的模型视图集 classes 都可以从那个 class 继承。不过,它要求外键字段始终命名为 "user"。如果不是这种情况,这里有一个稍微老套的方法,你可以找到用户 table 的外键字段。小心使用。
from django.db.models.fields.related import ForeignKey
from accounts.models import User
def _get_related_user(self, obj):
'''
Search for FK to user model and return field name or False if no FK.
This can lead to wrong results when the model has more than one user FK.
'''
for f in self.model._meta.fields:
if isinstance(f, ForeignKey) and f.rel.to == User:
return f.name
return False