我想使用tastypie创建一个视图来暴露相同类型的某些对象,但是使用以下两个三个曲折:
我不清楚如何进入tastypie生命周期来实现这一目标。添加“虚拟”字段的推荐方法是在脱水方法中,该方法只知道它正在操作的包。
更糟糕的是,没有正式的方法来加入查询集。
如果我能让tastypie接受查询集以外的东西,我的问题就会消失。在这种情况下,我可以传递一个我的对象的子类列表,并添加了附加字段。
我愿意接受任何其他合理的解决方案。
编辑:添加了扭曲3 - 每用户数据。
答案 0 :(得分:8)
在最后一个版本中,您应该覆盖脱水方法,例如
def dehydrate(self, bundle):
bundle.data['full_name'] = bundle.obj.get_full_name()
return bundle
答案 1 :(得分:7)
在此遇到类似问题。在我的情况下,列表中的项目可以由用户“检查”。
首先,我认为hydrate()
和dehydrate()
方法是这项工作的最佳匹配,但事实证明在这些方法中访问request
对象存在问题。所以我选择了alter_data_to_serialize()
和obj_update()
。我认为没有必要覆盖obj_create()
,因为我认为,首次创建项目时无法检查项目。
以下是代码,但请注意,它尚未经过正确测试。
class ItemResource(ModelResource):
def get_object_checked_status(self, obj, request):
if hasattr(request, 'session'):
session = request.session
session_data = session.get(get_item_session_key(obj), dict())
return session_data.get('checked', False)
return False
def save_object_checked_status(self, obj, data, request):
if hasattr(request, 'session'):
session_key = get_item_session_key(obj)
session_data = request.session.get(session_key, dict())
session_data['checked'] = data.pop('checked', False)
request.session[session_key] = session_data
# Overridden methods
def alter_detail_data_to_serialize(self, request, bundle):
# object > resource
bundle.data['checked'] = \
self.get_object_checked_status(bundle.obj, request)
return bundle
def alter_list_data_to_serialize(self, request, to_be_serialized):
# objects > resource
for bundle in to_be_serialized['objects']:
bundle.data['checked'] = \
self.get_object_checked_status(bundle.obj, request)
return to_be_serialized
def obj_update(self, bundle, request=None, **kwargs):
# resource > object
save_object_checked_status(bundle.obj, bundle.data, request)
return super(ItemResource, self)\
.obj_update(bundle, request, **kwargs)
def get_item_session_key(obj): return 'item-%s' % obj.id
答案 2 :(得分:1)
好的,这是我的解决方案。代码如下。
注意事项:
obj_get_list
完成。这就是我运行查询的地方,可以访问请求。obj_get_list
返回一个列表。obj_*
方法(如obj_get
,obj_create
等)。queryset
中没有Meta
,我需要提供一个object_class
来告诉tastypie内省提供哪些字段。 obj_get_list
中创建),我需要为其添加一个字段声明。代码:
from tastypie.resources import ModelResource
from tastypie import fields
from models import *
import logging
logger = logging.getLogger(__name__)
class CompanyResource(ModelResource):
role = fields.CharField(attribute='role')
class Meta:
allowed_methods = ['get']
resource_name = 'companies'
object_class = CompanyUK
# should probably have some sort of authentication here quite soon
#filters does nothing. If it matters, hook them up
def obj_get_list(self, request=None, **kwargs):
# filters = {}
# if hasattr(request, 'GET'):
# # Grab a mutable copy.
# filters = request.GET.copy()
# # Update with the provided kwargs.
# filters.update(kwargs)
# applicable_filters = self.build_filters(filters=filters)
try:
#base_object_list = self.get_object_list(request).filter(**applicable_filters)
def add_role(role):
def add_role_company(link):
company = link.company
company.role = role
return company
return add_role_company
director_of = map(add_role('director'), DirectorsIndividual.objects.filter(individual__user=request.user))
member_of = map(add_role('member'), MembersIndividual.objects.filter(individual__user=request.user))
manager_of = map(add_role('manager'), CompanyManager.objects.filter(user=request.user))
base_object_list = director_of + member_of + manager_of
return base_object_list #self.apply_authorization_limits(request, base_object_list)
except ValueError, e:
raise BadRequest("Invalid resource lookup data provided (mismatched type).")
答案 3 :(得分:0)
你可以这样做(未经测试):
def alter_list_data_to_serialize(self, request, data):
for index, row in enumerate(data['objects']):
foo = Foo.objects.filter(baz=row.data['foo']).values()
bar = Bar.objects.all().values()
data['objects'][index].data['virtual_field'] = bar
return data