Django: отображать Generic ModelForm или предопределенную форму

У меня есть 3 модели с различными полями в каждой. Для двух моделей я могу использовать общую форму (через create_object Django) для запроса данных. Я написал функцию, которая принимает имя модели и отправляет пользователя в общую форму.

url(r'^add_(?P<modelname>\w+)/$', generic_add),

def generic_add(request, modelname):
    mdlnm_model = models.get_model('catalog',modelname)
    return create_object(request,
        model = mdlnm_model,
        template_name = 'create.html',
        post_save_redirect = '/library/',
        extra_context = {'func': 'Create ' + modelname},
        login_required =  'True'
    )

Для третьей модели у меня определен класс ModelForm, поэтому я могу опустить одно из полей в этой модели, когда пользователь увидит форму.

url(r'^create_actor/$', create_object, Actor_Input, name='db_actor_create'),

Actor_Input = {
   'form_class': ActorForm,
   'template_name': 'create.html',
   'post_save_redirect': '/library/',
   'extra_context': {'func': 'Create Actor'},
   'login_required': 'True'
}

class ActorForm(forms.ModelForm):
    class Meta:
          model = Actor
          fields = ('name','age','height','short_description',
                   'long_description')

Есть ли способ для Django отображать определенную ModelForm, если она существует, но в противном случае отображать полностью общую форму, если определенная форма не была создана? Я ожидаю создания гораздо большего количества моделей и предпочел бы не создавать URL-адрес для каждой отдельной модели, которую необходимо разделить так, как это делает Актер.

Иными словами, я хочу изменить функцию generic_add, чтобы она использовала форму ActorForm (если она существует), а в остальном — универсальную форму ModelForm. Я знаю, как проверить существование класса ActorForm, но что, если я хочу, чтобы он также был динамическим? Что-то вроде проверки существования: имя модели + «Форма». Я не уверен, как динамически отправить пользователя в предопределенную форму, если она существует.

Какие-либо предложения? Есть ли лучший способ взглянуть на эту проблему?


person Ed.    schedule 04.03.2010    source источник
comment
Мне трудно понять, чего вы пытаетесь достичь в целом из вашего описания. Вам удобно вставлять соответствующие биты в корзину для вставки куда-нибудь, чтобы мы могли видеть, что у вас есть на данный момент?   -  person Brian Luft    schedule 04.03.2010
comment
Извините, см. исправленный вопрос   -  person Ed.    schedule 04.03.2010


Ответы (2)


Вот как я, вероятно, подошел бы к тому, что вы пытаетесь сделать:

url(r'^add_(?P<model_name>\w+)/$', generic_add),

model_presets = {
    'Actor': {
        'extra_context': {'func': 'Create Actor'},
        'form_class': ActorForm,
        'login_required': True,
        'post_save_redirect': '/library/',
        'template_name': 'create.html'
    },
    'default': {
        'extra_context': {'func': 'Oops, something went wrong if you are seeing \
                                   this, it should have been overwritten!'},
        'form_class': None,
        'login_required': True,
        'model': None,
        'post_save_redirect': '/library/',
        'template_name': 'create.html'
    }
}

def _create_object_conf_helper(request, model_name):
    if model_name in model_presets:
        conf = model_presets[model_name]
    else:
        try:
            named_model = models.get_model('catalog', model_name)
        except:
            # do something here to protect your app!
        conf = model_presets['default']
        conf['model'] = named_model
        conf['extra_context']['func'] = 'Create %s' % model_name
    conf['request'] = request
    return conf

def generic_add(request, model_name):
    return create_object(**_create_object_conf_helper(request, model_name))

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

Кроме того, вы также можете сделать еще один шаг и создать еще один уровень в словаре model_presets, чтобы позволить аналогичной вспомогательной функции создавать конфигурации для любых других общих представлений, которые вы можете использовать.

Кстати, нет необходимости заключать True в кавычки, просто не забудьте использовать заглавную букву T, а не rue, и она будет преобразована в 1-битную логическую константу. Использование «True» использует (примерно) минимум 32 бита в качестве строки. Оба проверят истинность в выражении if, и поэтому это не так уж важно. С другой стороны, использование «False» не будет работать должным образом, так как снова это строка, а не логическое значение, и поэтому она также будет проверяться как истинная.

См. http://docs.python.org/library/stdtypes.html#truth-value-testing .

person Beau    schedule 26.04.2010

Было бы очень полезно увидеть эту функцию, о которой вы говорите.
Обычный способ использования create_object действительно заключается в том, чтобы указать модель или форму, которую вы хотите использовать, что приведет к трем URL-адресам в вашем случае.

Из документации :

Требуемые аргументы:

  • Требуется либо form_class, либо model.
    Если вы указываете form_class, это должен быть подкласс django.forms.ModelForm. Используйте этот аргумент, когда вам нужно настроить форму модели. См. документацию ModelForm для получения дополнительной информации.
    В противном случае model должен быть классом модели Django, а используемая форма будет стандартной ModelForm для модели.

Видите ли, вы можете указать форму для использования. Возможно, это уже помогает вам, но без дополнительной информации мы не можем сделать больше.

person Felix Kling    schedule 04.03.2010
comment
Я пересмотрел свой вопрос выше. Но в основном я хочу иметь возможность использовать form_class, если он существует, но в противном случае стандартный ModelForm - person Ed.; 04.03.2010