2010-01-26 15 views
10

Al crear una página plana, quiero que el usuario seleccione una plantilla de una lista predefinida. Con el fin de mantener el modelo Flatpage intacta, prefiero ChoiceField sobre ModelChoiceField (este último proporciona la FC de la plantilla, pero necesito el nombre para el campo template_name):fields and base_fields - Django

class NewFlatpageForm(FlatpageForm): 

    template_name = forms.ChoiceField(choices = []) 
    def __init__(self, *args, **kwargs): 
     self.base_fields['template_name'].choices = ProjectTemplate.objects.values_list('path', 'name') 
     super(NewFlatpageForm, self).__init__(*args, **kwargs) 

puedo reemplazar __init__ o Django rellena opciones en inicio del servidor y no actualiza la lista a continuación.

No tengo experiencia en administración, pero hice cosas similares utilizando el atributo fields cuando no se usa admin. Sin embargo, en este caso, recibí una excepción que dice fields no es un atributo del formulario. __dict__ me mostró que hay un atributo base_fields y su uso funciona. Entonces, ¿por qué usar base_fields aquí, y por qué fields no está presente y finalmente estoy haciendo algo hacky?

Respuesta

11

fields no existe hasta que después de ha llamado super. Así que simplemente cambie el orden de las líneas, de modo que super es lo primero.

+0

Gracias Daniel .. – shanyu

8

Una lección de mi propia experiencia: la modificación de los campos base significa que tus modificaciones permanecen "para siempre" (hasta que Python se cierre). En su caso, eso probablemente no sea un problema, ya que siempre está utilizando el mismo nombre de campo, y está reemplazando sus valores con la asignación de ProjectTemplate ...

En mi caso, quería campos completamente diferentes en función de los parámetros en el constructor Dado que mis nombres de campo eran generalmente diferentes, cada vez que creaba una instancia de un formulario, añadía nuevos campos pero no eliminaba los de la última vez.

Al llamar súper temprano (como se indica aquí) y luego hacer mis cambios dinámicos en self.fields en vez de self.basefields, pude eliminar el problema de una lista de campos en constante crecimiento. Tiene mucho sentido ahora, pero no estaba familiarizado con todos los detalles de sintaxis y estaba pirateando en lugar de tratar de entenderlo primero.

3

Además de Joe Germuska. Si realmente necesita cambiar el formulario en función de la solicitud, puede utilizar una copia profunda para asegurarse de que no se modificó nada por referencia:

def get_form(self, request, obj=None, **kwargs): 
    form = super(ResourceAdmin, self).get_form(request, obj, **kwargs) 
    form = copy.deepcopy(form) 

    if obj: 
     form.base_fields['email'] = EmailField(initial=obj.user.email) 
    if not request.user.is_superuser: 
     form.base_fields['user'].widget = HiddenInput(attrs={'class': 'hide_form_row'}) 

    return form