我正在尝试使用Django TastyPie来更新我的模型。我有一个Identity模型,充当默认Django用户模型的包装器:
class Identity(ProfileBase):
user = models.OneToOneField(User, related_name='identity')
avatar = models.ImageField(upload_to=avatar_upload_path, blank=True,
null=True)
我有UserResource
:
class UserResource(ModelResource):
class Meta:
resource_name = 'user'
queryset = User.objects.all()
fields = ['email', 'first_name', 'last_name']
include_resource_uri = False
我有IdentityResource
:
class IdentityResource(ModelResource):
user = fields.ToOneField(UserResource, 'user', full=True)
class Meta:
resource_name = 'identity'
queryset = Identity.objects.select_related()
fields = ['user', 'avatar']
always_return_data = True
include_resource_uri = False
authentication = OAuthTokenAuthentication()
authorization = Authorization()
我目前正在使用obj_update
中的ModelResource IdentityResource
方法成功更新first_name,last_name:
def obj_update(self, bundle, request, **kwargs):
print 'updating object'
bundle = self.full_hydrate(bundle)
bundle.obj.user = request.user
user = bundle.data['user']
bundle.obj.user.first_name = user['first_name']
bundle.obj.user.last_name = user['last_name']
return super(IdentityResource, self).obj_update(bundle, request, user=request.user)
我想发出PUT
请求,并可选择更新用户或身份模型上的任何字段(用户的first_name,last_name或身份上的头像字段)。我愿意不必手动访问捆绑数据中的每个字段,并手动将它们设置在模型上,如上所述。
我怎样才能在TastyPie中自然地做到这一点?有人可以解释一个更好的方法来解决这个问题吗?任何方向都非常感谢。 :)
答案 0 :(得分:3)
这是我尝试尽可能多地利用Tastypie的答案。
它比OP的请求更通用(它将更新任何用户,而不仅仅是登录的用户)。在现实世界中,您可能希望添加某种身份验证/授权。
from tastypie.resources import ModelResource
from tastypie.authorization import Authorization
from django.contrib.auth.models import User
from myapp.account.models import Identity
class IdentityResource(ModelResource):
class Meta:
queryset = Identity.objects.all()
class UserResource(ModelResource):
class Meta:
queryset = User.objects.all()
allowed_list_methods = ['get']
allowed_detail_methods = ['get','put']
authorization = Authorization()
def dehydrate(self, bundle):
identity_bundle = self.build_identity_bundle(bundle)
identity_bundle = IdentityResource().full_dehydrate(identity_bundle)
return identity_bundle
def obj_update(self, bundle, request, **kwargs):
user_bundle = super(UserResource, self).obj_update(bundle, request, **kwargs)
identity_bundle = self.build_identity_bundle(user_bundle)
IdentityResource().obj_update(identity_bundle, request)
return user_bundle
def build_identity_bundle(self, user_bundle):
identity_bundle = IdentityResource().build_bundle(
obj=user_bundle.obj.get_profile(),
data=user_bundle.data
)
return identity_bundle
该示例支持的是:
您可能希望在API中注册UserResource,可能不是IdentityResource。
答案 1 :(得分:0)
你可以这样做。
# Find all properties in user model.
properties = [prop for prop in bunder.obj.user if not prop.startswith('__')]
bundle_user = bundle.data['user']
# Find the property in bundle user and set it back on user if it exists.
for property in properties:
if property in bundle_user:
setattr(bundle.obj.user, property, bundle_user[property])
答案 2 :(得分:0)
也许我错过了这一点,但您是否尝试过PATCH
- 方法请求? Tastypie将获取所有已发送的属性并在数据库中更新它们,保持所有未发送的属性不受影响。