3

私はこのようなことをしようとしています:

モデル limit_choices_to={'user': user}

いくつかの違いがあります。

モデルによっては、次のように説明できます。

class Job(models.Model):
    name = models.CharField(max_length=200)
    operators = models.ManyToManyField(User)

class Activity(models.Model):
    job = models.ForeignKey(Job)
    job_operators = models.ManyToManyField(User, limit_choices_to={user: Job.operators} blank=True, null=True)

注: 構文は必ずしも正しいものではありませんが、説明用です。

さて、SOに関するいくつかの回答が示すように、ミドルウェアを使用して現在のユーザーを取得することにある程度成功しましたが、アクティビティが保存された場合、request.POSTを介して現在のジョブを取得できることを望んでいました、現在のジョブを識別することができるため、オペレーターとしてのユーザーのサブセットが、アクティビティモデルで選択するユーザーセットになります。

つまり、親フィールドの ManyToManyField の選択に基づいて、そのサブ選択を子フィールドに提供するか、John、Jim、Jordan、および Jesse がジョブに取り組んでいる場合は、それらの名前のみから選択して作業を説明します。そのジョブ内にあり、そのジョブに属しているアクティビティ。

ところで、ミドルウェアでの私の素朴な試みは次のとおりです。

# threadlocals middleware
try:
    from threading import local
except ImportError:
    from django.utils._threading_local import local

_thread_locals = local()
def get_current_user():
    return getattr(_thread_locals, 'user', None)

def get_current_job():
    return getattr(_thread_locals, 'job', None)

class ThreadLocals(object):
    """Middleware that gets various objects from the
    request object and saves them in thread local storage."""
    def process_request(self, request):
        _thread_locals.user = getattr(request, 'user', None)
        _thread_locals.job = getattr(request.POST["job"], 'job', None)

そしてActivityモデル:

operators = modes.ManyToManyField(User, limit_choices_to=dict(Q(User.objects.filter(job==threadlocals.get_current_job)))

ありがとうございました。

4

3 に答える 3

2

わかりました、私はあなたの作品にモンキー レンチを投げるのが嫌いですが、真剣にスレッドローカル ハックを使用する必要はありません。

ユーザーはリクエストオブジェクトに含まれているため、ミドルウェアを使用して抽出する必要はありません。すべてのビューに引数として渡されます。

したがって、フォームの選択を制限する秘訣は、モデルで選択を制限するのではなく、フォームで使用されるクエリセットを動的に変更することです。

したがって、フォームは次のようになります。

# forms.py
from django import forms
from project.app.models import Activity
class ActivityForm(forms.ModelForm):
    class Meta:
        model Activity

ビューは次のようになります。

# views.py
...
form = ActivityForm(instance=foo)
form.fields['job_operators'].queryset = \
    User.objects.filter(operators__set=bar)
...

これは簡単なスケッチに過ぎませんが、一般的な考え方は理解できるはずです。

admin で threadlocals を回避する方法を知りたい場合は、James Bennett によるUsers and the adminをお読みください。

編集: Collin Grady による Django での便利なフォームのトリック は、フォーム __init__ メソッドでクエリセットを動的に設定する例も示しています。これは、上記の例よりもクリーンです。

于 2009-02-26T00:58:54.170 に答える
2

しかし、list_filter で定義するフィールドはどうでしょうか? それらは limit_choices_to のみを尊重します。したがって、Django 管理フィルターの選択肢を制限したい場合は、 limit_choices_to といくつかのミドルウェアを使用して、現在のユーザーに基づいてそれらをフィルター処理する必要があります。または、より簡単な解決策はありますか?

于 2011-03-25T22:18:31.743 に答える
0

モンキーレンチは友達を歓迎します!

直接的ではないように見えますが、別の方法も見つけました。

class ActivityForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(ActivityForm, self).__init__(*args, **kwargs)

        if self.initial['job_record']:
            jr = JobRecord.objects.get(pk=self.initial['job_record'])
            self.fields['operators'].queryset = jr.operators

    class Meta:
        model = Activity
        exclude = ('duration',)  

あなたのやり方の方がいいと思います!ありがとうございます!

于 2009-02-26T01:31:53.420 に答える