POST、PATCH &複数のビューセットのDELETEメソッドをオーバーライドして、必須のバックエンドパラメータを追加できるようにするにはどうすればよいですか?POST、PATCH&DELETEメソッドをオーバーライド
ロジック。すべての関連するテーブルに「tenant_id」を持つマルチテナントアプリを構築していますか?このtenant_idはテナントを識別します。したがって、すべてのリクエストには、ユーザが自分のものでないコンテンツを表示または変更しないようにするために、この親キーを含める必要があります。
クエリを取得するために、私は、その後経由して、すべてのビューセットクラスにこのフィルタを追加した
class CustomFilterBackend(filters.BaseFilterBackend):
"""
Filter that only allows users to see entries related to their tenant.
"""
def filter_queryset(self, request, queryset, view):
tenant_id = get_tenant_id_from_token(request)
return queryset.filter(is_deleted=False, tenant_id=tenant_id)
ユーザーが得ることができるものを制限するための必須フィルタオブジェクトを追加するために私を可能にするカスタムフィルタのバックエンドを作成しましたfilter_backends =()
オプション
質問POST、PATCH、DELETEリクエストでも同じことを達成する方法はありますか?
私の現在の考えは、すべてのモデルでmodel.save
メソッドをオーバーライドするということですか?しかし、それはHTTP DELETE
メソッドの世話をしません。
透明tenant_id:モデルで
、tenant_idはもちろん必須です。しかし、私はユーザーのJWTトークンから取得できるので、web/mobileクライアントに常にtenant_idを提供するよう強制したくありません。テナントIDはウェブ/モバイルアプリに対して透過的である必要があります。
EDIT 2
問題は、私は黙っ/静か/舞台裏はウェブ/モバイルアプリが意識することなくtenant_id
を追加したい、です。意味私はtenant_id
JSONキーを送信するAPIを使用してアプリをしたくない。
すべてのビューセットにfilter_backendsを追加することによりサンプルモデル
class SampleModel(models.Model):
"""
Sample model
"""
title = models.CharField(max_length=100)
tenant = models.ForeignKey(Tenant, on_delete=models.PROTECT)
class CustomFilterBackend(filters.BaseFilterBackend):
"""
Filter that only allows users to see entries related to their tenant.
"""
def filter_queryset(self, request, queryset, view):
tenant_id = get_tenant_id_from_token(request)
return queryset.filter(is_deleted=False, tenant_id=tenant_id)
class SampleViewSet(ListCreateRetrieveUpdateViewSet):
"""
Sample viewset
"""
serializer_class = SampleModelSerializer
permission_classes = (HasPermission)
queryset = SampleModel.objects.all()
filter_backends = (CustomFilterBackend,)
は、すべてのGETクエリが今tenant_idが含まれます。だから私が望むのは、他のすべてのHTTPメソッド、特にPOSTとPATCHと同じものを達成することです。
シリアライザをオーバーライドする必要があると思われます。それはDRY方法でそれをすることは可能ですか?
{
"exp": 1477069682,
"is_superuser": true,
"email": "[email protected]",
"tenant_id": 1, #THE TENANT ID
"user_id": 1,
"username": "[email protected]"
}
Djangoの認証を使用しています。また、 'ForeignKey'は' _id'を使って宣言されていません。与えられたサンプルモデルを修正しました。あなたの提案では、私は 'CurrentTenantDefault'をどこに置くのですか?また、テナント識別子は、JWTトークンのプライベートセクションからフェッチされます。 'django-rest-framework-jwt'を使用しています。ログイン時にtenant_idをトークンに追加しました。私が質問に追加した例を見てください。 – lukik
私は通常、 'serializers'モジュールに入れています。あるいは、シリアライザがいくつかのモジュールに分割されている場合、' serializers.core'のようなものです。あなたの 'get_tenant_id_from_token'関数を使って' CurrentTenantDefault'の例で答えを更新しました。 –
ありがとうございます。これは期待通りに機能し、理解しやすい – lukik