【问题标题】:Django: OneToOne dropdown in the admin interface and unique associationsDjango:管理界面中的 OneToOne 下拉菜单和唯一关联
【发布时间】:2018-11-29 05:17:03
【问题描述】:

参考Django - one-to-one modelAdmin,我仍在寻找解决 Django 管理界面和我的 OneToOne 关系问题的解决方案。

我有以下模型,它使用附加属性 is_thing_staff 扩展了标准用户模型:

class ThingStaff(models.Model):
    """ Extends the django user model by a separate model relationship which holds additional user
    attributes
    """
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    # by default a new user is not a staff member which take care of the thing administration
    is_thing_staff = models.BooleanField(default=False)

    def __str__(self):
        return u"{}".format(self.user.username)

    class Meta:
        verbose_name = "Thing Staff"
        verbose_name_plural = "Thing Staff"

如果我在 django 管理界面中创建一个新的 ThingStaff 对象,我可以选择所有用户,即使用户已经存在关系。保存与用户具有重复关联的新对象会导致错误,即已经存在与该用户关联的 ThingStaff 对象。到目前为止,这或多或少都可以。

但是,如果可能的选择会在下一步中导致错误,为什么还要显示它们呢?所以我通过

排除了他们
from django import forms
from django.contrib import admin
from .models import ThingStaff

class ThingStaffForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(ThingStaffForm, self).__init__(*args, **kwargs)
        self.fields['user'].queryset = User.objects.exclude(
           id__in=ThingStaff.objects.values_list('user_id', flat=True)
        )

@admin.register(ThingStaff)
class ThingStaffAdmin(admin.ModelAdmin):
    form = ThingStaffForm

到目前为止很好:在创建新的 ThingStaff 对象期间,已关联的用户不会显示在下拉列表中。

但如果我想更改现有关联,相关用户也不会出现在下拉列表中,这使得无法重置 is_thing_staff 标志。

所以我的问题是:如何在 django 管理界面中为更改视图再次启用此特定用户?

【问题讨论】:

    标签: python django django-forms django-admin


    【解决方案1】:

    Django 的ModelForm 区分添加和更改视图(每个视图都有自己的方法)。这意味着您可以覆盖它:

    class ThingStaffAdmin(ModelAdmin):
         def add_view(self, *args, **kwargs):
             self.form = ThingStaffAddForm
             return super().add_view(*args, **kwargs)
    
         def change_view(self, *args, **kwargs):
             self.form = ThingStaffChangeForm
             return super().change_view(*args, **kwargs)
    

    文档中的更多内容:

    https://docs.djangoproject.com/en/2.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.change_view

    【讨论】:

    • 感谢您的信息。我选择@vorujack 的答案,因为我只需要一种方法即可。但使用 _view 方法更能自我记录代码实现的目标。
    【解决方案2】:

    您的排除列表必须更新,并且不得排除此 ThingStaff 的选定用户

    像这样更新你的表单

    class ThingStaffForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(ThingStaffForm, self).__init__(*args, **kwargs)
        exclude_user = ThingStaff.objects.all()
        if self.instance:
             exclude_user = exclude_user.exclude(pk=self.instance.pk)
        self.fields['user'].queryset = User.objects.exclude(id__in=exclude_user.values('user_id'))
    

    此代码检查当前表单是否为编辑表单,并有一个实例将其从排除列表中排除。

    【讨论】:

      最近更新 更多