[英]Upgrading from Tastypie 0.9.11 to 0.11 obj_get_list
Code that worked in api.py With Python 2.6, Django 1.4.1, Tastypie 0.9.11 (Running on 2.6.32-48-generic-pae #110-Ubuntu SMP) 在api.py中使用Python 2.6,Django 1.4.1,Tastypie 0.9.11的代码(在2.6.32-48-generic-pae#110-Ubuntu SMP上运行)
class DriveResource(CommonModelResource):
driver = fields.ForeignKey(DriverResource, 'driver')
bus = fields.ForeignKey(BusResource, 'bus')
route = fields.ForeignKey(RouteResource, 'route')
class Meta(CommonModelResource.Meta):
queryset = Drive.objects.all()
allowed_methods = ['get', 'put']
excludes = ('bus_location',)
filtering = {
'updated': ('gt', 'gte', 'lt', 'lte', 'exact'),
'id': ('exact',),
}
def get_object_list(self, request):
whole_list = super(DriveResource, self).get_object_list(request)
todays_day_name = datetime.now().strftime('%w')
filtered_list = whole_list.filter(driver__user=request.user).filter(day=todays_day_name)
return filtered_list
def dehydrate_driver(self, bundle):
return bundle.obj.driver.person_id
def dehydrate_bus(self, bundle):
return bundle.obj.bus.number
def dehydrate_route(self, bundle):
return bundle.obj.route.id
def hydrate_bus_location(self, bundle):
# Guard against the method being called twice
if not hasattr(bundle, 'geopoint_processed'):
lon = bundle.data['bus_location'][0] / 1e6
lat = bundle.data['bus_location'][1] / 1e6
bundle.data['bus_location'] = Point(lon, lat)
bundle.geopoint_processed = True
return bundle
class DriveFullResource(CommonModelResource):
driver = fields.ForeignKey(DriverResource, 'driver', full=True, blank=True, null=True)
bus = fields.ForeignKey(BusResource, 'bus', full=True, blank=True, null=True)
route = fields.ForeignKey(RouteResource, 'route', full=True)
class Meta(CommonModelResource.Meta):
queryset = Drive.objects.all()
resource_name = 'drive'
allowed_methods = ['get', 'put']
excludes = ('bus_location',)
def obj_get_list(self, request=None, **kwargs):
whole_list = super(DriveFullResource, self).obj_get_list(request, **kwargs)
todays_day_name = datetime.now().strftime('%w')
filtered_list = whole_list.filter(driver__user=request.user).filter(day=todays_day_name)
return filtered_list
def hydrate_bus_location(self, bundle):
# Guard against the method being called twice
if not hasattr(bundle, 'geopoint_processed'):
lon = bundle.data['bus_location'][0] / 1e6
lat = bundle.data['bus_location'][1] / 1e6
bundle.data['bus_location'] = Point(lon, lat)
bundle.geopoint_processed = True
return bundle
def put_detail(self, request, **kwargs):
deserialized = self.deserialize(request, request.raw_post_data, format=request.META.get('CONTENT_TYPE', 'application/json'))
deserialized = self.alter_deserialized_detail_data(request, deserialized)
bundle = self.build_bundle(data=dict_strip_unicode_keys(deserialized), request=request)
try:
drive = Drive.objects.get(pk=kwargs['pk'])
bundle = self.hydrate_bus_location(bundle)
drive.bus_location = bundle.data['bus_location']
drive.save()
return http.HttpNoContent()
except:
return http.HttpBadRequest()
Does not work with Python 2.6, Django 1.5, Tastypie 0.11 (Running on Centos 5) 不适用于Python 2.6,Django 1.5,Tastypie 0.11(在Centos 5上运行)
Calling server with : https://api.server.com/api/full/drive/?format=json&limit=50&user=12345 呼叫伺服器: https : //api.server.com/api/full/drive/?format=json&limit=50&user=12345
I tried changing to: 我尝试更改为:
def obj_get_list(self, bundle, **kwargs):
request = bundle.request
whole_list = super(DriveFullResource, self).get_object_list(request)
todays_day_name = datetime.now().strftime('%w')
filtered_list = whole_list.filter(driver__user=request.user).filter(day=todays_day_name)
return filtered_list
and 和
def obj_get_list(self, bundle, **kwargs):
request = bundle.request
whole_list = super(DriveFullResource, self).obj_get_list(bundle, **kwargs)
todays_day_name = datetime.now().strftime('%w')
filtered_list = whole_list.filter(driver__user=request.user).filter(day=todays_day_name)
return filtered_list
Still get error messages of the type below: 仍然会收到以下类型的错误消息:
{"error_message": "obj_get_list() got multiple values for keyword
argument 'bundle'", "traceback": "Traceback (most recent call
last):\n\n File
\"/usr/lib/python2.6/site-packages/tastypie/resources.py\", line 195,
in wrapper\n\n File
\"/usr/lib/python2.6/site-packages/tastypie/resources.py\", line 426,
in dispatch_list\n\n File
\"/usr/lib/python2.6/site-packages/tastypie/resources.py\", line 458,
in dispatch\n\n File
\"/usr/lib/python2.6/site-packages/tastypie/resources.py\", line 1266,
in get_list\n\n File
\"/home/django_projects/project/src/routes/api.py\", line 110, in
obj_get_list\n request = bundle.request\n\nTypeError:
obj_get_list() got multiple values for keyword argument 'bundle'\n"}
{"error_message": "obj_get_list() got multiple values for keyword
argument 'bundle'", "traceback": "Traceback (most recent call
last):\n\n File
\"/usr/lib/python2.6/site-packages/tastypie/resources.py\", line 195,
in wrapper\n\n File
\"/usr/lib/python2.6/site-packages/tastypie/resources.py\", line 426,
in dispatch_list\n\n File
\"/usr/lib/python2.6/site-packages/tastypie/resources.py\", line 458,
in dispatch\n\n File
\"/usr/lib/python2.6/site-packages/tastypie/resources.py\", line 1266,
in get_list\n\n File
\"/home/django_projects/project/src/routes/api.py\", line 114, in
obj_get_list\n return filtered_list\n\nTypeError: obj_get_list()
got multiple values for keyword argument 'bundle'\n"}
I tested the method on Tastypie 0.11 and seems to work ok. 我在Tastypie 0.11上测试了该方法,并且工作正常。 But in my opinion you are taking wrong and error prone approach.
但是我认为您正在采用容易出错和容易出错的方法。 I prepared solution that will eliminate them.
我准备了可以消除它们的解决方案。
Problem definition 问题定义
You didn't defined what is your code supposed to do. 您没有定义代码应该做什么。 Reviewing code I assume you want to have resource that returns object for currently logged user and filtered by day name.
查看代码,我假设您想拥有返回当前登录用户的对象并按日期名称过滤的资源。 In other words you want to limit access to resource - And this is.. I think you know, authorization.
换句话说,您想限制对资源的访问-这是..我想您知道,授权。
Why not obj_get_list? 为什么不使用obj_get_list?
You see that Tastypie obj_get_list
is quite Django ORM specific and not documented well. 您将看到Tastypie
obj_get_list
相当Django的ORM具体的,而不是记录良好。 I don't really know how to use it. 我真的不知道如何使用它。 I wouldn't dare to deal with it.
我不敢处理。
Solution 解
Let's define Authorization class for your resource: 让我们为您的资源定义Authorization类:
from datetime import datetime
from tastypie.authorization import Authorization
class DriverAuthorization(Authorization):
def read_list(self, object_list, bundle):
todays_day_name = datetime.now().strftime('%w')
return object_list.filter(driver__user=bundle.request.user,
day=todays_day_name)
def read_detail(self, object_list, bundle):
todays_day_name = datetime.now().strftime('%w')
return bundle.obj.day == todays_day_name and bundle.obj.driver.user == bundle.request.user
def create_list(self, object_list, bundle):
return []
def create_detail(self, object_list, bundle):
return False
def update_list(self, object_list, bundle):
return []
def update_detail(self, object_list, bundle):
object_before_update = object_list.get(pk=bundle.obj.pk)
return object_before_update.driver.user == bundle.request.user
def delete_list(self, object_list, bundle):
return []
def delete_detail(self, object_list, bundle):
return False
Now attach authorization to resource: 现在将授权附加到资源:
class DriveResource(CommonModelResource):
driver = fields.ForeignKey(DriverResource, 'driver')
bus = fields.ForeignKey(BusResource, 'bus')
route = fields.ForeignKey(RouteResource, 'route')
class Meta(CommonModelResource.Meta):
queryset = Drive.objects.all()
allowed_methods = ['get', 'put']
excludes = ('bus_location',)
authorization = DriverAuthorization()
filtering = {
'updated': ('gt', 'gte', 'lt', 'lte', 'exact'),
'id': ('exact',),
}
def dehydrate_driver(self, bundle):
return bundle.obj.driver.person_id
def dehydrate_bus(self, bundle):
return bundle.obj.bus.number
def dehydrate_route(self, bundle):
return bundle.obj.route.id
def hydrate_bus_location(self, bundle):
# Guard against the method being called twice
if not hasattr(bundle, 'geopoint_processed'):
lon = bundle.data['bus_location'][0] / 1e6
lat = bundle.data['bus_location'][1] / 1e6
bundle.data['bus_location'] = Point(lon, lat)
bundle.geopoint_processed = True
return bundle
Benefits 优点
1. Code now is much more clearer to read 1.现在,代码更加清晰易读
2. You have control on what user can do or cannot do in one place. 2.您可以控制用户在一处可以做什么或不能做什么。
3. No obj_get_list
means no more problems. 3.没有
obj_get_list
意味着没有更多问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.