3

悪い例に入る前に要約すると、他:すべてのモデルでコードを記述して、現在ログインしているアカウントに選択肢を制限する必要がないアプリケーションを作成しようとしています(使用していません)認証、またはアカウントまたはログインの組み込み機能)。

つまり、私はこのようなことをする必要はありません

class Ticket(models.Model):
        account = models.ForeignKey(Account)
        client = models.ForeignKey(Client)  # A client will be owned by one account.
        content = models.CharField(max_length=255)

class TicketForm(forms.ModelForm):
        class Meta:
                model = Ticket
                exclude = ('account',)  #First sign of bad design?

        def __init__(self, *args, **kwargs):
                super(OrderForm, self).__init__(*args, **kwargs)
                if self.initial.get('account'):
                        # Here's where it gets ugly IMHO. This seems almost
                        # as bad as hard coding data. It's not DRY either.
                        self.fields['client'].queryset = Client.objects.filter(account=self.initial.get('account'))

私のアイデアはAccount(models.Model)、次のカスタムマネージャーを使用してモデルを作成し、すべてのモデルでマルチテーブル継承を使用してモデルをサブクラス化することです。しかし、それは私に大きな脳の痛みを与えています。account各モデルに外部キーが必要ですか?特定のモデルインスタンスの親クラスアカウントにアクセスできますか?

class TicketManager(models.Manager):
    def get_query_set(self):
        return super(TicketManager, self).get_query_set().filter(account=Account.objects.get(id=1))
        # Obviously I don't want to hard code the account like this.
        # I want to do something like this:
        # return super(ProductManager, self).get_query_set().filter(account=self.account)
        # Self being the current model that's using this manager
        # (obviously this is wrong because you're not inside a model
        # instance , but this is where the confusion comes in for me.
        # How would I do this?).

激しい構文エラーは無視してください。このすべてをここに入力しました。

これを行うためのアイデアを思いついたのはここです:Django名前空間プロジェクト

4

3 に答える 3

7

Djangoに関しては、密接に関連する2つの問題があります。

1つは、テーブルレベルの権限を持つ通常のDjango認証フレームワークとは対照的に、ユーザー/アカウントがテーブル内の特定の行(オブジェクト)を表示するために特定の権限を必要とする行レベルの権限です。

リンクしたプロジェクトは、行のアクセス許可を実装しようとしているいくつかのプロジェクトの1つです。 django-granular-permissionsはもう1つで、3番目(私のお気に入りで最もアクティブ/維持されている)はdjango-authorityです。

Django 1.2の次のリリースには、行レベルのアクセス許可の実装を容易にするフックがあり、django-authorityの作成者はプロジェクトの統合に取り組みます。

2番目の関連する問題は、行のアクセス許可のバリエーションであるマルチテナントデータベースと呼ばれるものです。このスキームでは、たとえば、1つの会社の複数のユーザーがいて、そのすべてのユーザーがその会社のデータにアクセスできるが、他の会社(テナント)にはアクセスできない場合があります。

これはあなたが探しているものではないと思いますが、同じテクニックのいくつかを使用できるかもしれません。Djangoおよびマルチテナントのdjangoアプリケーションでアカウントの分離を強制する方法をご覧ください。どちらも非常にまばらな答えですが、Railsアプリとこの記事のマルチテナントアーキテクチャを検討するための出発点です。

あなたの質問に対するより具体的な答えについては、django-authorityを使用するか、カスタムマネージャーを作成し、開発中にレコード所有権スクリーナーを使用して、クエリがカスタムマネージャーをバイパスしていないことを確認する必要があると思います。

于 2010-01-25T21:51:11.077 に答える
2

ここでの基本的な問題はdjango.contrib.auth、現在ログインしているユーザーに関する情報がビューでのみ利用可能であり、モデルでは利用できない場合でも、この情報はリクエストにバインドされているためです。したがって、ビューでは常に次のようなことを行う必要があります。

def some_view(request):
    account = get_account_by_request(request)

次に、アカウントを使用してモデルをフィルタリングできます。ミドルウェアまたはデコレータを使用することで、このアプローチをいつでもよりエレガントにすることができますが、トリッキーになりすぎないように注意してください。継承されたマネージャなどとの多重継承が多すぎるために、予期しない時点(私に起こった)で設計が破損する可能性があります。シンプルで予測可能なものにしてください。

于 2010-01-25T19:10:21.900 に答える
1

現在のユーザーをコードに取り込むために、threadlocalsミドルウェアを使用できますが、それについては特別なことは何もありません。大きなハックが1つしかないので、注意してください:)

個人的には、そのようなロジックをモデルに組み込むのは悪いことだと思います。なぜなら、それらは単なるデータであり、そのようなことを認識してはならないからです。

于 2010-01-25T19:54:19.187 に答える