Django: отображать общую модель или заданную форму - PullRequest
2 голосов
/ 04 марта 2010

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

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

Для 3-й модели у меня определен класс 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, но что, если я хочу, чтобы это также было динамическим? Что-то вроде проверки, если: modelname + 'Form' существует. Я не уверен, как динамически отправить пользователя в предопределенную форму, если она существует.

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

Ответы [ 2 ]

1 голос
/ 26 апреля 2010

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

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 не будет работать так, как ожидалось, поскольку еще раз это строка, а не логическое значение, и, следовательно, она также будет проверяться как true.

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

0 голосов
/ 04 марта 2010

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

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

Обязательные аргументы:

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

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

...