How to filter objects by user id with tastypie?

南楼画角 提交于 2020-01-04 03:56:06

问题


I have the following user resource:

class UserResource(ModelResource):
  class Meta:
    queryset = User.objects.all()
    resource_name = 'user'
    fields = ['username', 'first_name', 'last_name']
    allowed_methods = ['get']
    filtering = {
      'username': ALL,
      'id': ALL,
    }

and the following model resource:

class GoalResource(ModelResource):
  user = fields.ForeignKey(UserResource, 'user')

  class Meta:
    #authentication = BasicAuthentication()
    #authorization = ReadOnlyAuthorization()
    queryset = Goal.objects.all()
    resource_name = 'goal'
    filtering = {
      'user': ALL_WITH_RELATIONS,
    }

I want to be able to filter the goal by user id rather than username.

I can get a list of goals from certain usernames by doing a GET request on this:

http://localhost:8000/api/v1/goal/?user__username=test

But I want to be able to sort by user id instead:

http://localhost:8000/api/v1/goal/?user__id=1

How would I get the second part to work?

Also, what is the general procedure for accessing a currently logged in user's id through Javascript? I am using backbonejs, and I want to do a post for all of a logged in user's goal. I thought about putting a hidden field on the page with the user's id. Then extracting the value of the hidden field from the DOM, but I figured it's easy to use chrome's developer tools to change the id whenever I want. Of course, I will use authentication to check that the logged in user's id matches the one that I extract from the hidden field, though. But what is the accepted way?


回答1:


I am not sure if what I propose here can work in your authorization. It works for me using ApiKeyAuthorization and Authorization.

I read the idea from: http://django-tastypie.readthedocs.org/en/latest/cookbook.html [Section: Creating per-user resources ]

My suggestion is:

What about uncommenting authentication and authorization, and overriding obj_create and apply_authorization. I am using that in my project, and it works. In the code of the method apply_authorization, I just added the if condition checking for superuser, you can just return the object_list+filter without checking that (I do it cause if is not superuser, I return data related to groups of users).

class GoalResource(ModelResource):
  user = fields.ForeignKey(UserResource, 'user')

  class Meta:
    authentication = BasicAuthentication()
    authorization = ReadOnlyAuthorization()
    queryset = Goal.objects.all()
    resource_name = 'goal'
    filtering = {
      'user': ALL_WITH_RELATIONS,
    }

   def obj_create(self, bundle, request=None, **kwargs):
       return super(EnvironmentResource, self).obj_create(bundle, request, user=request.user)


   def apply_authorization_limits(self, request, object_list):
       if request.user.is_superuser:
           return object_list.filter(user__id=request.GET.get('user__id',''))

Hope is what you were asking, and it helps. best with that!




回答2:


Note - apply_authorization_limits is deprecated.

The alternative way to filter by the current user, is to override read_list in you authorization class. This is what I have. My class overrides DjangoAuthorization.

 def read_list(self, object_list, bundle):
    klass = self.base_checks(bundle.request, object_list.model)

    if klass is False:
        return []

    # GET-style methods are always allowed.

    # Filter by user
    if not hasattr(bundle.request, 'user'):
        return None

    object_list = object_list.filter(user__id=bundle.request.user.id)

    return object_list


来源:https://stackoverflow.com/questions/9884529/how-to-filter-objects-by-user-id-with-tastypie

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!