2

私は、Django TastyPie を使用してモデルを更新しようとしています。デフォルトの Django ユーザー モデルのラッパーとして機能する Identity モデルがあります。

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()

私は現在、ModelResourceobj_updateメソッドを使用してfirst_name、last_nameを正常に更新していますIdentityResource:

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必要に応じてユーザー モデルまたは ID モデル (ユーザーの first_name、last_name、または ID のアバター フィールド) のフィールドを更新したいと考えています。上記のように、バンドル データから各フィールドに手動でアクセスしてモデルに手動で設定する必要はありません。

TastyPieでこれを自然に行うにはどうすればよいですか? 誰かがこの問題を解決するためのより良いアプローチを説明できますか? どんな方向でも大歓迎です。:)

4

3 に答える 3

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

この例でサポートされているのは次のとおりです。

  • フラット化された User+Identity リソースを取得する
  • フラット化された User+Identity リソースを PUT し、両方のモデルを更新します

おそらく IdentityResource ではなく、UserResource を API に登録する必要があります。

于 2012-08-23T05:20:48.553 に答える
0

たぶん私は要点を見逃していますが、PATCH-methodリクエストを試しましたか?Tastypieは、送信されたすべての属性を取得し、データベース内でそれらを更新して、送信されていないすべての属性を変更しません。

于 2012-08-20T13:20:43.637 に答える
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])
于 2012-08-17T04:42:05.110 に答える