27

インライン化したい Django モデル フィールドがあります。フィールドは多対多の関係です。そのため、「プロジェクト」と「ユーザー プロファイル」があります。各ユーザー プロファイルは、任意の数のプロジェクトを選択できます。

現在、「表形式」のインライン ビューが機能しています。ユーザープロファイルからプロジェクトを簡単に追加および削除できるように、「水平フィルター」を使用する方法はありますか?

例として添付の写真をご覧ください。ここに画像の説明を入力

ユーザー プロファイルのモデル コードは次のとおりです。

class UserProfile(models.Model):
    user = models.OneToOneField(User, unique=True)
    projects = models.ManyToManyField(Project, blank=True, help_text="Select the projects that this user is currently working on.")

プロジェクトのモデル コード:

class Project(models.Model):
    name = models.CharField(max_length=100, unique=True)
    application_identifier = models.CharField(max_length=100)
    type = models.IntegerField(choices=ProjectType)
    account = models.ForeignKey(Account)
    principle_investigator = models.ForeignKey(User)
    active = models.BooleanField()

ビューの管理コード:

class UserProfileInline(admin.TabularInline):
    model = UserProfile.projects.through
    extra = 0
    verbose_name = 'user'
    verbose_name_plural = 'users'

class ProjectAdmin(admin.ModelAdmin):
    list_display = ('name', 'application_identifier', 'type', 'account', 'active')
    search_fields = ('name', 'application_identifier', 'account__name')
    list_filter = ('type', 'active')
    inlines = [UserProfileInline,]
admin.site.register(Project, ProjectAdmin)
4

3 に答える 3

52

問題はインラインを持つことではありません。ModelFormそれは一般的に、仕事のやり方からです。関連するマネージャー属性ではなく、モデルの実際のフィールドのフォーム フィールドのみを構築します。ただし、この機能をフォームに追加できます。

from django.contrib.admin.widgets import FilteredSelectMultiple

class ProjectAdminForm(forms.ModelForm):
    class Meta:
        model = Project

    userprofiles = forms.ModelMultipleChoiceField(
        queryset=UserProfile.objects.all(),
        required=False,
        widget=FilteredSelectMultiple(
            verbose_name='User Profiles',
            is_stacked=False
        )
    )

    def __init__(self, *args, **kwargs):
        super(ProjectAdminForm, self).__init__(*args, **kwargs)
            if self.instance.pk:
                self.fields['userprofiles'].initial = self.instance.userprofile_set.all()

    def save(self, commit=True):
        project = super(ProjectAdminForm, self).save(commit=False)  
        if commit:
            project.save()

        if project.pk:
            project.userprofile_set = self.cleaned_data['userprofiles']
            self.save_m2m()

        return project

class ProjectAdmin(admin.ModelAdmin):
    form = ProjectAdminForm
    ...

少しウォークスルーが必要です。まず、userprofilesフォーム フィールドを定義します。を使用しModelMultipleChoiceField、デフォルトでは複数選択ボックスになります。これはモデルの実際のフィールドではないため、単に に追加することはできません。代わりに、 にリストされている場合にfilter_horizontal使用するのと同じウィジェット を使用するように指示します。FilteredSelectMultiplefilter_horizontal

クラス定義のこの段階では、フォームはインスタンス化されていないため、まだ設定されてUserProfileいないため、ここではまだフィルタリングできませinstanceん。その結果、__init__フィルタリングされたクエリセットをフィールドの初期値として設定できるようにオーバーライドします。

最後に、saveメソッドをオーバーライドして、関連するマネージャーのコンテンツをフォームの POST データと同じものに設定できるようにします。これで完了です。

于 2012-07-25T20:36:40.290 に答える
3

それ自体との多対多の関係を扱うときのマイナーな追加。選択肢から自分自身を除外したい場合があります。

if self.instance.pk:
        self.fields['field_being_added'].queryset = self.fields['field_being_added'].queryset.exclude(pk=self.instance.pk)
        self.fields['field_being_added'].initial = """Corresponding result queryset"""
于 2014-04-30T22:07:22.473 に答える