taking my initial lessons with django ModelForm ,I w开发者_JAVA技巧anted to give the user ,ability to edit an entry in a blog.The BlogEntry has a date,postedTime, title and content.I want to show the user an editform which shows all these fields,but with only title and content as editable. The 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)
...
For adding an entry ,I use a ModelForm in the normal way..
class BlogEntryAddForm(ModelForm):
    class Meta:
        model = BlogEntry
...
But how do I create the edit form?I want it to show the date,postedTime as uneditable (but still show them on the form) and let the user edit the title and description.
if I use,exclude in class Meta for date and postedTime,that will cause them not to appear on the form.So,how can I show them as uneditable?
class BlogEntryEditForm(ModelForm):
    class Meta:
        model = BlogEntry
        ...?...
In the form object, declare the attribute of the field as readonly:
form.fields['field'].widget.attrs['readonly'] = True
Is date field represent a date when the entry first created or when it was modified last time?  If first then use auto_now_add option else use auto_now.  That is:
date = models.DateField(auto_now_add=True)
will set date to now when entry will be created.
auto_now_add makes field uneditable.  For other cases use editable option to make any field uneditable.  For example
postedDate = models.TimeField(null=True, editable=False)
Also, likely you will add posted boolean field to Entry model, so it is convinient to set auto_now on postedDate.  It will set postedDate to now every time you modify a Entry including one when you set posted to True.
I implemented it this way: https://djangosnippets.org/snippets/10514/ this implementation uses the data of model instance for all read-only fields and not the data obtained while processing the form
below the same code but using his example
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)
Usage:
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
or use the function
class BlogEntryForm(forms.ModelForm):
    class Meta:
        model = BlogEntry
BlogEntryFormReadOnlyForm = new_readonly_form_class(BlogEntryForm, readonly_fields=('description', ))
This will prevent any user from hacking the request:
self.fields['is_admin'].disabled = True
Custom form example:
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__'
From the documentation,
class BlogEntryEditForm(ModelForm):
    class Meta:
    model = BlogEntry
    readonly_fields = ['date','postedTime']
 
         
                                         
                                         
                                         
                                        ![Interactive visualization of a graph in python [closed]](https://www.devze.com/res/2023/04-10/09/92d32fe8c0d22fb96bd6f6e8b7d1f457.gif) 
                                         
                                         
                                         
                                         加载中,请稍侯......
 加载中,请稍侯......
      
精彩评论