如果在仅具有查看权限的用户中呈现表单(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类的属性)?
答案 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,
}