2011-02-09 86 views
11

Tengo un modelo como este:¿Cómo puedo desactivar un campo modelo en una forma Django

class MyModel(models.Model): 
    REGULAR = 1 
    PREMIUM = 2 
    STATUS_CHOICES = ((REGULAR, "regular"), (PREMIUM, "premium")) 
    name = models.CharField(max_length=30) 
    status = models.IntegerField(choices = STATUS_CHOICES, default = REGULAR) 

class MyForm(forms.ModelForm): 
    class Meta: 
     model = models.MyModel 

En una vista que inicializar un campo y trato de hacerlo no editable:

myform = MyForm(initial = {'status': requested_status}) 
myform.fields['status'].editable = False 

Pero el usuario aún puede cambiar ese campo.

¿Cuál es la forma real de lograr lo que busco?

Respuesta

33

Paso 1: Deshabilitar el widget frontend

uso del HTML readonly atributo:
http://www.w3schools.com/tags/att_input_readonly.asp

O disabled atributo:
http://www.w3.org/TR/html401/interact/forms.html#adef-disabled

Puede inyectarse pares de valores clave arbitrarias HTML a través la propiedad attrs del widget:

myform.fields['status'].widget.attrs['readonly'] = True # text input 
myform.fields['status'].widget.attrs['disabled'] = True # radio/checkbox 

Paso 2: Asegúrese de que el campo se desactivará efectivamente el backend

anular su método limpio para su campo de manera que independientemente de la entrada POST (alguien puede fingir un POST, editar el HTML puro, etc.) obtienes el valor de campo que ya existe.

def clean_status(self): 
    # when field is cleaned, we always return the existing model field. 
    return self.instance.status 
+0

El atributo readonly es. ¡Gracias! – jammon

+2

Y el truco con 'self.instance.status' es realmente bueno. – jammon

+2

¡Oh, no! Lo intenté, y 'readonly' no hace la diferencia. Y (http://www.w3schools.com/tags/att_input_readonly.asp) dice 'El atributo readonly se puede usar con o .' En mi caso, es un botón de selección o de radio. Entonces, ¿más ideas? – jammon

5

¿Ha intentado utilizar la función de exclusión?

algo como esto

class PartialAuthorForm(ModelForm): 
class Meta: 
    model = Author 
    fields = ('name', 'title') 

class PartialAuthorForm(ModelForm): 
class Meta: 
    model = Author 
    exclude = ('birth_date',) 

Reference Here

+1

Quería modificar la forma _per instance_, por lo que 'exclude' no me funciona. – jammon

+0

@jammon: (1) "por instancia" no tiene sentido.Puede tener varias subclases diferentes con diferentes combinaciones de campos. (2) Por favor ** actualice ** la pregunta para explicar lo que quiere. –

+0

@ S.Lott: Tienes razón. Para (1) y (2). Mi culpa. – jammon

4

Sólo personalizar el widget de ejemplo para el campo de estado:

class MyModel(models.Model): 
    REGULAR = 1 
    PREMIUM = 2 
    STATUS_CHOICES = ((REGULAR, "regular"), (PREMIUM, "premium")) 
    name = models.CharField(max_length=30) 
    status = models.IntegerField(choices = STATUS_CHOICES, default = REGULAR) 

class MyForm(forms.ModelForm): 
    status = forms.CharField(widget=forms.TextInput(attrs={'readonly':'True'})) 

    class Meta: 
     model = models.MyModel 

véase: Django Documentation

2

De Django 1.9:

self.fields['whatever'].disabled = True 
Cuestiones relacionadas