仅具有查看权限的Django模型形式将所有字段都排除在外

时间:2019-07-16 12:12:16

标签: python django django-forms

如果在仅具有查看权限的用户中呈现表单(Django 2.1中的新增功能),则在我的默认(Django管理员)更改视图中使用自定义ModelForm会给我一个空变量self.fields

这是我的代码:

# models.py

class Door(ValidateOnSaveMixin, models.Model):
    ...

    motor_type = models.ForeignKey(
        MotorType,
        on_delete=models.SET_NULL,
        default=None,
        blank=True,
        null=True)
    ...
    door_type = models.CharField(
        max_length=3,
        choices=DOOR_TYPES,
        null=True,
        default=None)
    ...
    vehicle_variant = models.ForeignKey(
        VehicleVariant,
        on_delete=models.CASCADE)

    class Meta:
        unique_together = ("vehicle_variant", "location", "motor_type")

    ...



# admin.py

@admin.register(Door)
class DoorAdmin(ImportExportModelAdmin):
    form = DoorAdminForm

    list_display = ('descriptor', 'get_customer_link', 'get_variant', 'location', 'get_motor_type_link',
                    'window_type', 'door_type', 'drum_diameter', 'dist_per_motor_rotation')
    fields = ('vehicle_variant', 'description', 'location', 'motor_type',
              'drum_diameter', 'window_type', 'door_type')

    ...

# forms.py

class DoorAdminForm(ModelForm):

    class Meta:
        model = Door
        fields = '__all__'
        widgets = {
            'motor_type': DoorMotorTypeWidget,
        }

    def __init__(self, *args, **kwargs):
        super(DoorAdminForm, self).__init__(*args, **kwargs)
        # this line is crashing on access with a user who has only the view permission, as self.fields is empty
        self.fields['vehicle_variant'].queryset = VehicleVariant.objects.all().prefetch_related('customer').order_by('customer__name', 'name')

根本原因与DoorAdminForm中Meta类的exclude属性有关。 无论我写什么字段/排除属性,总是将模型的所有字段自动放入排除列表并阻止填充self.fields。这会使我的代码崩溃。

我当然可以检查'verhicle_variant' in self.fields,但我不了解这种行为的原因。在django源代码中也找不到该部分,该部分用所有模型字段填充了exclude属性。

有人想知道这是否有意吗?导致该行为的根本原因是什么(忽略字段并排除Meta类的属性)?

1 个答案:

答案 0 :(得分:1)

将所有字段放入exclude的地方在这里: https://github.com/django/django/blob/cf79f92abee2ff5fd4fdcc1a124129a9773805b8/django/contrib/admin/options.py#L674

我从未使用仅具有“查看”权限的django admin。尚未真正找到有关以下内容的大量信息:django-admin带有添加视图和更改视图,但没有viewonly-view?几乎看起来它真的不知道该如何处理没有“更改”权限的用户。它将它们定向到change_view,然后注意到它们不允许更改任何内容,因此显示为空格式?
我想您可以只将所有字段声明为viewonly-view的只读字段?


更新:
字段vehicle_variant将不在form.fields中,因为由于没有更改权限,该字段仍将被排除,但至少您不会在表单的初始化时崩溃。除了所有内容都是只读的,我仍然不知道没有更改权限的change_view应该是什么样子。

class DoorAdminForm(ModelForm):
    qs = VehicleVariant.objects.prefetch_related('customer').order_by('customer__name', 'name')
    model_field = Door._meta.get_field('vehicle_variant')

    vehicle_variant = model_field.formfield(queryset=qs)

    class Meta:
        model = Door
        fields = '__all__'
        widgets = {
            'motor_type': DoorMotorTypeWidget,
        }