Atualizar dinamicamente classe Meta do ModelForm

votos
22

Estou esperando para atualizar dinamicamente classe Meta linha de um ModelForm do meu ponto de vista. Embora esse código parece atualizar a lista de exclusão na classe Meta, a saída as_p(), as_ul()etc não reflete a Meta atualizada excluir.

Presumo então que o html é gerado quando o ModelForm é criado não quando o as_*()é chamado. Existe uma maneira de forçar a atualização do HTML?

É isso mesmo a melhor maneira de fazê-lo? Eu só assumiu este deve trabalhar.

Pensamentos?

from django.forms import ModelForm

from testprogram.online_bookings.models import Passenger

class PassengerInfoForm(ModelForm):

    def set_form_excludes(self, exclude_list):
        self.Meta.exclude = excludes_list

    class Meta:
        model = Passenger
        exclude = []
Publicado 18/11/2008 em 00:44
fonte usuário
Em outras línguas...                            


4 respostas

votos
55

A classe Meta é usado para construir dinamicamente a definição do formulário - então no momento em que você criou a instância de ModelForm, os campos não no excluem já foram adicionadas como atributos o novo objeto.

O caminho normal para fazê-lo seria apenas para ter várias definições de classe para cada possível lista de exclusão. Mas se você quer a própria forma de ser dinâmico, você terá que criar uma definição de classe na mosca. Algo como:

def get_form(exclude_list):
    class MyForm(ModelForm):
        class Meta:
            model = Passenger
            exclude = exclude_list
    return MyForm

form_class = get_form(('field1', 'field2'))
form = form_class()

ATUALIZAÇÃO : Eu só revisitada este post e pensei que eu ia postar um pouco mais idiomática para lidar com uma classe dinâmica:

def PassengerForm(exclude_list, *args, **kwargs):
    class MyPassengerForm(ModelForm):
        class Meta:
            model = Passenger
            exclude = exclude_list

        def __init__(self):
            super(MyPassengerForm, self).__init__(*args, **kwargs)

    return MyPassengerForm()

form = PassengerForm(('field1', 'field2'))
Respondeu 18/11/2008 em 01:38
fonte usuário

votos
13

Outra forma:

class PassengerInfoForm(ModelForm):
    def __init__(self, *args, **kwargs):
        exclude_list=kwargs.pop('exclude_list', '')

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

        for field in exclude_list:
            del self.fields[field]

    class Meta:
        model = Passenger

form = PassengerInfoForm(exclude_list=['field1', 'field2'])
Respondeu 01/04/2009 em 03:54
fonte usuário

votos
3

abordagem semelhante, objetivo um pouco diferente (ModelForm genérico para modelos arbitrárias):

from django.contrib.admin.widgets import AdminDateWidget
from django.forms import ModelForm
from django.db import models

def ModelFormFactory(some_model, *args, **kwargs):
    """
    Create a ModelForm for some_model
    """
    widdict = {}
    # set some widgets for special fields
    for field in some_model._meta.local_fields:
        if type(field) is models.DateField:
            widdict[field.name] = AdminDateWidget()

    class MyModelForm(ModelForm): # I use my personal BaseModelForm as parent
        class Meta:
            model = some_model
            widgets = widdict

    return MyModelForm(*args, **kwargs)
Respondeu 01/10/2010 em 17:02
fonte usuário

votos
2

Use modelform_factory( doc ):

from django.forms.models import modelform_factory

from testprogram.online_bookings.models import Passenger

exclude = ('field1', 'field2')
CustomForm = modelform_factory(model=Passenger, exclude=exclude)  # generates ModelForm dynamically
custom_form = CustomForm(data=request.POST, ...)  # form instance
Respondeu 13/11/2015 em 02:31
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more