Визуализация списка форм в Джанго - PullRequest
0 голосов
/ 13 мая 2019

Я пытаюсь создать базовый личностный тест в Django как подтверждение концепции на работе. Я новичок в Django (и Python в целом), исходя из C # .NET фона.

Я пытаюсь составить список объектов формы (заполненный информацией, извлеченной из объектов вопросов, хранящихся в базе данных), а затем отобразить их в HTML.

Это только частично работает; Я могу визуализировать атрибуты формы индивидуально в цикле for (вызывая, например, question.pk), но ничего не рендерится с помощью стандартного тега Django {{form}}, и попытка отправить список форм нарушает все это.

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

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

Заранее спасибо!

DISCQuestionForm в forms.py:

class DISCQuestionForm(forms.Form):
    # create new form object from database question object
    def __init__(
            self,
            pk,
            disc_query,
            dom_answer,
            infl_answer,
            stead_answer,
            con_answer,
            ):
        super().__init__()
        self.pk = pk
        self.disc_query = disc_query
        self.dom_answer = dom_answer
        self.infl_answer = infl_answer
        self.stead_answer = stead_answer
        self.con_answer = con_answer
        self.disc_response = forms.DecimalField(
            max_value=4,
            widget=forms.NumberInput
            )

метод disc_create в views.py

# Create a new DISC assessment for current user
def disc_create(request, pk):
    profile = User.objects.get(pk=pk)
    user = int(profile.pk)
    name = profile.name
    rawquestionset = DISCQuestion.objects.all()

    discformset = []
    for item in rawquestionset:
        question = DISCQuestionForm(
            pk=item.pk,
            disc_query=item.disc_query,
            dom_answer=item.dom_answer,
            infl_answer=item.infl_answer,
            stead_answer=item.stead_answer,
            con_answer=item.con_answer,
        )
        discformset.append(question)

    if request.method == 'POST':
        questionset = discformset[request.POST]
        if questionset.is_valid():
            dom = 0
            infl = 0
            stead = 0
            con = 0

            for discquestion in questionset:
                if discquestion.disc_response == discquestion.dom_answer:
                    dom += 1
                if discquestion.disc_response == discquestion.infl_answer:
                    infl += 1
                if discquestion.disc_response == discquestion.stead_answer:
                    stead += 1
                if discquestion.disc_response == discquestion.con_answer:
                    con += 1

            disctest = DISCTest(
                user=user,
                name=name,
                dom=dom,
                infl=infl,
                stead=stead,
                con=con,
            )
            disctest.save()
    else:
        questionset = discformset

    context = {
        "pk": user,
        "name": name,
        "discquestionset": questionset
    }

    return render(request, "disc_create.html", context)

DISCTest и DISCQuestion модели в models.py:

class DISCTest(models.Model):
    user = models.ForeignKey('User', on_delete=models.CASCADE)
    name = user.name
    created_on = models.DateTimeField(auto_now_add=True)
    dom = models.DecimalField(max_digits=3, decimal_places=0)
    infl = models.DecimalField(max_digits=3, decimal_places=0)
    stead = models.DecimalField(max_digits=3, decimal_places=0)
    con = models.DecimalField(max_digits=3, decimal_places=0)


class DISCQuestion(models.Model):
    disc_query = models.TextField()
    disc_response = models.DecimalField(max_digits=1, decimal_places=0, null=True)
    dom_answer = models.DecimalField(max_digits=1, decimal_places=0)
    infl_answer = models.DecimalField(max_digits=1, decimal_places=0)
    stead_answer = models.DecimalField(max_digits=1, decimal_places=0)
    con_answer = models.DecimalField(max_digits=1, decimal_places=0)

и, наконец, disc_create.html в шаблонах:

{% extends "base.html" %}

{% block page_content %}
<div class="col-md-8 offset-md-2">
    <h1>Take your DISC assessment</h1>
    <hr>
    <h3>Insert instructions here</h3>
    <hr>
    <form action="/assessment/create/{{pk}}/" method="post">
        {% csrf_token %}
        <div>
            {% for question in discquestionset %}
                <p>{{question.pk}}</p>
                <p>{{ question.disc_query }}</p>
                {{ form }}
            {% endfor %}
        </div>
        <button type="submit">Submit</button>
    </form>
</div>
{% endblock %}

1 Ответ

1 голос
/ 13 мая 2019

Ваш DiscQuestionForm не имеет полей.disc_response определяется как атрибут формы, но для Django это не поле, потому что оно не добавляется в self.fieldsform не определен в вашем шаблоне в цикле for, только question (это форма), поэтому {{ question }} напечатает форму, если у нее есть какие-либо поля.

Но тогда проблема в том, что каждое из ваших question полей формы будет иметь одинаковые атрибуты "name", потому что они не имеют префикса, чтобы сделать их уникальными.

Вы должны прочитать этот документ внимательно, чтобы понять ModelForm и modelformset.В основном вам необходимо:

class DISCQuestionForm(forms.ModelForm):
    class Meta:
        model = DISCQuestion

    def __init__(...):
        ...

С помощью modelformset_factory создать правильный ModelFormSet, который можно инициализировать с помощью request.POST при отправке.

DISCQuestionFormSet = modelformset_factory(DISCQuestionForm, form = DISCQuestionForm)  # note DISCQuestionForm not needed if you don't customise anything in your form.

и по вашему мнению:

formset = DISCQuestFormSet(request.POST or None)

тогда в вашем шаблоне вы можете перебирать формы в наборе форм:

{% for form in formset %}{{ form }}{% endfor %}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...