【问题标题】:Passing user credentials from Tastypie to Django Model将用户凭据从 Tastypie 传递到 Django 模型
【发布时间】:2013-10-16 12:46:17
【问题描述】:

我在 Django-Tastypie 中使用自定义身份验证,它在身份验证成功时返回用户名和密码。在 ModelResource 实例中,一旦认证成功,用户名和密码就可用了:

class TestResource(ModelResource):

    class Meta:
        queryset = Test.remote_supported.get_all(username,password)
        resource_name = 'test'
        filtering = {
            'id' : ALL,
        }
        detail_allowed_methods = ['get', 'post', 'patch']       
        authorization = Authorization()
        authentication = MyCustomAuth()
        always_return_data = True

    def __init__(self, api_name=None):
        self.username = None
        self.password = None
        super(TestResource, self).__init__(api_name)

    def is_authenticated(self, request):
        auth_result = self._meta.authentication.is_authenticated(request)

        if isinstance(auth_result, HttpResponse):
            raise ImmediateHttpResponse(response=auth_result)

        if not auth_result is True:
            raise ImmediateHttpResponse(response=http.HttpUnauthorized())

        # this is where I receive the username and password from my custom auth
        self.username, self.password = self._meta.authentication.get_credentials()

这段代码显然不起作用,因为那个用户名和那个密码在元类中不可用,即使是,改变它也不会只影响这个实例,而是所有实例,这不是我的意图,因为用户名和密码的范围应该是每个 RESTful 查询。

这是我的模型的样子:

class RemoteAuthSupported(models.Manager):
    def get_all(self, username, password):
        # ... here I do some custom operations with the username and password
        return super(RemoteAuthSupported, self).get_query_set()  

class Test(models.Model):
    objects = models.Manager()
    remote_supported = RemoteAuthSupported()

    # ... the field declarations follow here ... #

我尝试这样做的原因是我在我的 Django 应用程序中使用了非 ORM 数据源,它需要自己的身份验证,但使用相同的用户名和密码。处理从 Tastypie ModelResource 传递到 Django 模型的参数的方法是什么?我可能应该在这里提一下,没有使用用户模型。

【问题讨论】:

    标签: python django tastypie


    【解决方案1】:

    您可以做的是覆盖返回请求资源列表的obj_get_list 方法。此外,您可以将用户名和密码设置为 request 对象本身,这样参数就可以通过请求-响应路径进行传递。此外,您需要将queryset 设置为all()

    def obj_get_list(self, bundle, **kwargs):
        original = super(TestResource, self).obj_get_list(bundle, **kwargs)
        request = bundle.request
        return original.get_all(request.username, request.password)
    

    或者反过来 - 您可以添加自定义授权来过滤对象列表。 request 属性部分仍然有效。

    class MyAuth(Authorization):
       def authorized_read_list(self, objects, bundle):
           request = bundle.request
           return objects.get_all(request.username, request.password)
    

    如果您宁愿使用get_all 来模仿queryset 而不仅仅是交替列表端点,您可以覆盖get_object_list

    def get_object_list(self, request):
        original = super(TestResource, self).get_object_list(request)
        return original.get_all(request.username, request.password)
    

    【讨论】:

    • 为什么我必须使用all()?根据this example,这不是必需品。
    • 这不是必需的,但是从queryset 属性中推断出一些数据,包括模型类。如果您将 get_all 方法添加到您的查询集,那么您可以随时过滤任何查询集,而无需 ModelManager。由相应 ModelManager 支持的自定义查询集方法确实让生活更轻松
    【解决方案2】:

    我查看了 Tastypie 文档,似乎以下可能是一个解决方案,尽管是业余的:

    class TestResource(ModelResource):
    
        class Meta:
            queryset = Test.remote_supported.get_all('dummyusername','dummypassword')
            resource_name = 'test'
            filtering = {
                'id' : ALL,
            }
            detail_allowed_methods = ['get', 'post', 'patch']       
            authorization = Authorization()
            authentication = MyCustomAuth()
            always_return_data = True
    
        def get_object_list(self, request):
            """
            This method calls a clone of the queryset declared in the Metaclass.
            It is called every time a query is executed.
            Here the actual username and password is passed to the model.
            """         
            return Site.remote_supported.get_all(self.username,self.password)
    

    问题是查询集声明只在 Metaclass 中发生一次,而不是每个查询,因此从 http 请求获取的用户名和密码无法传递给 Meta 级别的查询。但是由于get_object_list() 克隆了声明并使用更新参数值执行实际调用,因此可以完成工作。它对我有用,但我觉得应该有更好的解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-09
      • 1970-01-01
      • 2021-05-26
      • 2013-11-19
      • 1970-01-01
      • 2012-10-15
      相关资源
      最近更新 更多