简体   繁体   English

当您从 Django 管理员 class 中排除字段时,这是否也会阻止在 POST 中设置该字段?

[英]When you exclude a field from a Django admin class, does that also prevent the field being set in a POST?

Say I have a model admin:假设我有一个 model 管理员:

class Customer(Model):
    name = CharField(max_length=255)
    secret = CharField(max_length=255, blank=True)


@register(Customer)
class CustomerAdmin(ModelAdmin):
    list_display = ['name']
    exclude = ['secret']

The secret field is not going to appear in the admin. secret字段不会出现在管理员中。 But if I programmatically create a POST with the secret field in, will Django prevent it from being set on the model?但是,如果我以编程方式创建一个包含secret字段的POST ,Django 会阻止它在 model 上设置吗? So is there any security risk in having an admin class for a model which has excluded fields that should not be written to from a web client?那么对于 model 的管理员 class 是否存在任何安全风险,其中排除了不应从 web 客户端写入的字段?

Answer is that this should be fine and using exclude should be enough to prevent the field being set by a malicious POST.答案是这应该没问题,并且使用exclude应该足以防止该字段被恶意 POST 设置。

The reason lies in construct_instance() (django 3.2) , which is used to populate a new or existing instance (the instance argument) with data from the POST (in the fields argument):原因在于construct_instance() (django 3.2) ,它用于使用来自 POST 的数据(在fields参数中)填充新的或现有的实例( instance参数):

def construct_instance(form, instance, fields=None, exclude=None):
    ...
    for f in opts.fields:
        ...
        if exclude and f.name in exclude:
            continue
        ...
        else:
            f.save_form_data(instance, cleaned_data[f.name])

Which gets called as:这被称为:

class BaseModelForm(BaseForm):
    ...
    def _post_clean(self):
        opts = self._meta
        ...
        try:
            self.instance = construct_instance(self, self.instance, opts.fields, opts.exclude)
        except ValidationError as e:
            ...

And the exclude is populated by the django.contrib.admin.options.ModelAdmin :并且excludedjango.contrib.admin.options.ModelAdmin填充:

class ModelAdmin(BaseModelAdmin):
    ...
    def get_exclude(self, request, obj=None):
        return self.exclude

    ...

    def get_form(self, request, obj=None, change=False, **kwargs):
        ...
        excluded = self.get_exclude(request, obj)
        exclude = [] if excluded is None else list(excluded)
        ...
        defaults = {
            ...
            'exclude': exclude,
            ...
        }
        ...
        try:
            return modelform_factory(self.model, **defaults)
        except FieldError as e:
            ...

And modelform_factory just passes that through to the form's options.modelform_factory只是将其传递给表单的选项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM