仅具有查看权限的 Django 模型表单将所有字段排除在外
Posted
技术标签:
【中文标题】仅具有查看权限的 Django 模型表单将所有字段排除在外【英文标题】:Django model form with only view permission puts all fields on exclude 【发布时间】:2019-11-25 04:11:17 【问题描述】:如果表单为仅具有查看权限的用户呈现(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】:将所有字段放入exclude
的点在这里:
https://github.com/django/django/blob/cf79f92abee2ff5fd4fdcc1a124129a9773805b8/django/contrib/admin/options.py#L674
我从未使用过仅具有“查看”权限的 django admin。还没有真正找到很多关于这应该是什么样子的信息:django-admin
带有添加和更改视图等,但没有 viewonly-view
?几乎看起来它并不真正知道如何处理没有“更改”权限的用户。它将他们引导到 change_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,
【讨论】:
感谢您的链接!没看出来我认为他们在 CRUD 中实现 R 时做得很好 :) 所以 viewonly 视图实际上是更改视图,但不允许更改,这对我来说很有意义。如果我在管理类中使用 get_form 方法,我可以省略 change 参数并防止排除。但我目前不确定它会有什么副作用。我会调查的。 以其他方式设置vehicle_variant
的查询集可能更容易。在您的 DoorAdminForm
? 上明确声明该字段?
你会怎么做?我决定不使用 get_form 方法,而是检查 self.仅视图中的字段我实际上不需要查询优化。但是从 if 语句来看,为什么我需要检查键仍然不是很明显。所以我想有一些自我记录的实施方式。但现在我很高兴在这些线上设置一些 cmets。
更新了我的帖子,希望我没有遗漏一些明显的东西。
我也使用了您对更新的建议,它适用于 ForeignKey 关系,但不适用于 ManyToMany。以上是关于仅具有查看权限的 Django 模型表单将所有字段排除在外的主要内容,如果未能解决你的问题,请参考以下文章