Динамически обновлять Мета-класс ModelForm - PullRequest
23 голосов
/ 18 ноября 2008

Я надеюсь динамически обновить встроенный мета-класс ModelForm, на мой взгляд. Хотя этот код, по-видимому, обновляет список исключений в классе Meta, выходные данные as_p(), as_ul() и т. Д. Не отражают обновленное исключение Meta.

Я предполагаю, что HTML генерируется при создании ModelForm, а не при вызове as_*(). Есть ли способ форсировать обновление HTML?

Это даже лучший способ сделать это? Я просто предположил, что должно работать.

Мысли

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 = []

Ответы [ 4 ]

56 голосов
/ 18 ноября 2008

Мета-класс используется для динамического построения определения формы - поэтому к моменту создания экземпляра ModelForm поля, не входящие в исключение, уже были добавлены в качестве атрибутов нового объекта.

Обычный способ сделать это - просто иметь несколько определений классов для каждого возможного списка исключений. Но если вы хотите, чтобы сама форма была динамичной, вам придется создавать определение класса на лету. Что-то вроде:

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()

ОБНОВЛЕНИЕ : Я только что вернулся к этому посту и подумал, что опубликую немного более идиоматический способ обработки динамического класса:

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'))
13 голосов
/ 01 апреля 2009

Другой способ:

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'])
3 голосов
/ 13 ноября 2015

Использование modelform_factory ( документ ):

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
3 голосов
/ 01 октября 2010

Аналогичный подход, несколько иная цель (универсальная ModelForm для произвольных моделей):

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...