как показать поле django ModelForm как недоступное для редактирования - PullRequest
3 голосов
/ 17 августа 2011

принимая мои начальные уроки с django ModelForm, я хотел дать пользователю возможность редактировать запись в блоге. BlogEntry имеет date,postedTime, title and content. Я хочу показать пользователю форму редактирования, которая показывает все этиполя, но только с title and content as editable.date and postedTime should be shown as uneditable.

class BlogEntry(models.Model):
   title = models.CharField(unique=True,max_length=50)
   description = models.TextField(blank=True)
   date = models.DateField(default=datetime.date.today)
   postedTime = models.TimeField(null=True)

...

Для добавления записи я использую ModelForm обычным способом.

class BlogEntryAddForm(ModelForm):
    class Meta:
        model = BlogEntry
...

Но как мне создать форму редактирования? Я хочу этона show the date,postedTime as uneditable (но все равно покажите их в форме) и разрешите пользователю редактировать title and description.

, если я использую, exclude in class Meta для даты и postsTime, что приведет к тому, что они не появятся наform.Так как я могу показать их как недоступные для редактирования?

class BlogEntryEditForm(ModelForm):
    class Meta:
        model = BlogEntry
        ...?...

Ответы [ 5 ]

14 голосов
/ 17 августа 2011

В объекте формы объявите атрибут поля как readonly:

form.fields['field'].widget.attrs['readonly'] = True
3 голосов
/ 17 августа 2011

Поле date представляет дату, когда запись впервые была создана или когда она была изменена в последний раз?Если сначала, то используйте auto_now_add, иначе используйте auto_now.То есть:

date = models.DateField(auto_now_add=True)

установит date сейчас, когда будет создана запись.

auto_now_add делает поле недоступным для редактирования.В других случаях используйте опцию editable, чтобы сделать любое поле недоступным для редактирования.Например,

postedDate = models.TimeField(null=True, editable=False)

Также, вероятно, вы добавите логическое поле posted к модели Entry, поэтому удобно установить auto_now на postedDate.Он будет устанавливать postedDate на каждый раз, когда вы изменяете запись, в том числе запись, когда вы устанавливаете posted на True.

0 голосов
/ 13 октября 2017

Это не позволит любому пользователю взломать запрос:

self.fields['is_admin'].disabled = True

Пример пользовательской формы:

class MemberShipInlineForm(forms.ModelForm):
    is_admin = forms.BooleanField(required=False)

    def __init__(self, *args, **kwargs):

        super(MemberShipInlineForm, self).__init__(*args, **kwargs)

        if 'instance' in kwargs and kwargs['instance'].is_group_creator:
            self.fields['is_admin'].disabled = True

    class Meta:
        model = MemberShip
        fields = '__all__'
0 голосов
/ 16 июля 2015

Я реализовал это так: https://djangosnippets.org/snippets/10514/ эта реализация использует данные экземпляра модели для всех полей только для чтения, а не данные, полученные при обработке формы

ниже того же кода, но используя его пример

from __future__ import unicode_literals

from django.utils import six
from django.utils.encoding import force_str

__all__ = (
    'ReadOnlyFieldsMixin',
    'new_readonly_form_class'
)


class ReadOnlyFieldsMixin(object):
    """Usage:
    class MyFormAllFieldsReadOnly(ReadOnlyFieldsMixin, forms.Form):
        ...


    class MyFormSelectedFieldsReadOnly(ReadOnlyFieldsMixin, forms.Form):
        readonly_fields = ('field1', 'field2')
        ...
    """
    readonly_fields = ()

    def __init__(self, *args, **kwargs):
        super(ReadOnlyFieldsMixin, self).__init__(*args, **kwargs)
        self.define_readonly_fields(self.fields)

    def clean(self):
        cleaned_data = super(ReadOnlyFieldsMixin, self).clean()

        for field_name, field in six.iteritems(self.fields):
            if self._must_be_readonly(field_name):
                cleaned_data[field_name] = getattr(self.instance, field_name)

        return cleaned_data

    def define_readonly_fields(self, field_list):

        fields = [field for field_name, field in six.iteritems(field_list)
                  if self._must_be_readonly(field_name)]

        map(lambda field: self._set_readonly(field), fields)

    def _all_fields(self):
        return not bool(self.readonly_fields)

    def _set_readonly(self, field):
        field.widget.attrs['disabled'] = 'true'
        field.required = False

    def _must_be_readonly(self, field_name):
        return field_name in self.readonly_fields or self._all_fields()


def new_readonly_form_class(form_class, readonly_fields=()):
    name = force_str("ReadOnly{}".format(form_class.__name__))
    class_fields = {'readonly_fields': readonly_fields}
    return type(name, (ReadOnlyFieldsMixin, form_class), class_fields)

Использование:

class BlogEntry(models.Model):
    title = models.CharField(unique=True,max_length=50)
    description = models.TextField(blank=True)
    date = models.DateField(default=datetime.date.today)
    postedTime = models.TimeField(null=True)


# all fields are readonly    
class BlogEntryReadOnlyForm(ReadOnlyFieldsMixin, forms.ModelForm):
    class Meta:
        model = BlogEntry

# selected fields are readonly
class BlogEntryReadOnlyForm2(ReadOnlyFieldsMixin, forms.ModelForm):
    readonly_fields = ('date', 'postedTime')
    class Meta:
        model = BlogEntry

или используйте функцию

class BlogEntryForm(forms.ModelForm):
    class Meta:
        model = BlogEntry

BlogEntryFormReadOnlyForm = new_readonly_form_class(BlogEntryForm, readonly_fields=('description', ))
0 голосов
/ 17 августа 2011

Из документации ,

class BlogEntryEditForm(ModelForm):
    class Meta:
    model = BlogEntry
    readonly_fields = ['date','postedTime']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...