Использование нескольких форм в одном представлении - PullRequest
3 голосов
/ 18 января 2011

Я пытаюсь изучить фреймворк django с несколькими примерами приложений.В настоящее время я работаю над приложением обратной связи / опроса.В нем используются следующие модели:

class Survey(models.Model):
    title = models.CharField(_(max_length=255)
    slug = models.SlugField(_(max_length=255, unique=True)
    description= models.TextField(blank=True)


class Question(models.Model):
    survey = models.ForeignKey(Survey, related_name='questions')
    question = models.TextField()

class Answer(models.Model):
    question = models.ForeignKey(Question, related_name='answers')
    answer = models.TextField()

В основном опрос будет содержать вопросы, и их ответы будут сохранены в ответе.

Теперь я не понимаю, как создать формукоторый будет отображать все вопросы опроса при вызове представления.Я пытался создать форму, подобную этой:

class BaseAnswerForm(Form):
    answer = None
    def __init__(self, question,*args, **kwdargs):
        self.question = question
        #self.answer = None
        super(BaseAnswerForm, self).__init__(*args, **kwdargs)
        answer = self.fields['answer']
        answer.label = question.question

    def save(self, commit=True):
        ans = self.answer
        if ans is None:
            ans = Answer()
        ans.question = self.question
        ans.answer = self.cleaned_data['answer']
        if commit: ans.save()
        return ans

class TextAnswerForm(BaseAnswerForm):
    answer = CharField()

def forms_for_survey(survey, request):
    if request.POST:
        post = request.POST
    else:
        post = None
    return [TextAnswerForm(q,data=post)
            for q in survey.questions.all()]

. Это выглядит как

def show_questions(request, slug):
    survey = get_object_or_404(Survey.objects, slug=slug)
    forms = forms_for_survey(survey, request)
    context = {
        'survey':survey,
        'forms':forms,
        }
    if (request.POST and all(form.is_valid() for form in forms)):
        for form in forms:
            form.save()
        return HttpResponseRedirect(reverse('show_surveys',))
    return render_to_response(
        'feedback/show_questions.html',
        context,
        context_instance = RequestContext(request)
        )

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

Ответы [ 3 ]

2 голосов
/ 18 января 2011

Возможно, причина в том, что имена полей формы конфликтуют.

Вы можете обойти эту проблему, но вы уже изучили документацию Formsets ?

Набор форм - это уровень абстракции для работы с несколькими формами на одной странице.

1 голос
/ 18 января 2011

Аргумент prefix используется для предотвращения конфликтов имен, возникающих при неоднократном использовании одной и той же формы (ее используют FormSets) или использовании форм с конфликтующими именами полей - присваивайте каждому Form уникальныйprefix, который будет добавлен перед каждым сгенерированным именем поля.Было бы идеально использовать идентификатор вопроса:

return [TextAnswerForm(q,data=post, prefix='q_%s' % q.pk)
        for q in survey.questions.all()]
1 голос
/ 18 января 2011

Вы не можете получить из объекта запроса, сколько формы было на клиентской странице www.Разрешается использовать множественную форму в HTML-документе, но единственное отличие состоит в том, что данные POST / GET содержат только поля из отправленной формы.Поэтому поместите все свои входные данные в одну форму, а затем самое простое решение - написать что-то подобное в вашем шаблоне

<form action="your_viw" method="post">
    {% for q in questions %}
        {{q.question}}<input name="q_{{q.id}}" type="text" />
    {% endfor %}
</form>

и на ваш взгляд

def show_questions(request, slug):
    survey = get_object_or_404(Survey.objects, slug=slug)
    context = {
        'survey':survey,
        'questions': survey.questions_set,
        }
    fields=[(int(name[2:]), val) for name, val in request.POST.items() if name.startswith('q_')]   # (question id, answer) list
    if fields:
         #validate fields
         # rest of work...
    return ...

Извините, если естьслово с ошибкой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...