简体   繁体   English

为相关模型创建Django表单

[英]Creating django form for related models

I have the following models defined: 我定义了以下模型:

class Question(models.Model):
    date_added = models.DateTimeField(auto_now_add=True)
    question = models.CharField(max_length=200)
    number_of_answers = models.IntegerField(default=0)

class Answer(models.Model):
    question = models.ForeignKey(Question)
    answer = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

I want the user to be able to create a question along with its corresponding answers. 我希望用户能够创建一个问题及其相应的答案。

Basically, I want to create a form that will ask the user to enter a question and the number of answers for the question. 基本上,我想创建一个表格,要求用户输入一个问题以及该问题的答案数量。 Based on the number-of-answers specified, I want to then create that many text fields for each answer. 根据指定的答案数量,我想为每个答案创建那么多文本字段。 I want to be able to connect each answer to its corresponding question in the database. 我希望能够将每个答案连接到数据库中其对应的问题。

What is the best way to do this in Python Django? 在Python Django中执行此操作的最佳方法是什么? I have provided images of what this would look like visually. 我提供的图像看起来像什么。 Getting question and number of answers, getting answers based on question and number of answers specified 获取问题和答案数量, 根据指定的问题和答案数量获取答案

Have a look of formsets .And combine with django-dynamic-forms can help you custom a web page to add question with answer. 看一下表单集 。与django-dynamic-forms结合使用可以帮助您自定义网页以添加带有答案的问题。

Here is a demo of add a team with it's player. 这是添加与玩家一起的团队的演示。

models.py models.py

class Player(models.Model):
    name = models.CharField(max_length=50)
    score = models.IntegerField()
    age = models.IntegerField()

    def __str__(self):
        return self.name


class Team(models.Model):
    name = models.CharField(max_length=100)
    players = models.ManyToManyField(Player)

    def __str__(self):
        return self.name

forms.py 表格

from django import forms
from django.forms.formsets import formset_factory
from .models import *


class PlayerForm(forms.ModelForm):
    class Meta:
        model = Player
        fields = '__all__'


PlayerFormset = formset_factory(PlayerForm)


class TeamForm(forms.Form):
    name = forms.CharField()
    players = PlayerFormset()

views.py views.py

from django.shortcuts import render

from .forms import *
from .models import *


def post(request):
    if request.method == 'POST':
        form = TeamForm(request.POST)

        player_instances = PlayerFormset(request.POST)
        if form.is_valid():
            if player_instances.is_valid():
                team = Team(name=form.cleaned_data['name'])
                team.save()
                args = {'form': form}
                for item in player_instances:
                    if item.is_valid():
                        player = item.save()
                        team.players.add(player)
                    else:
                        print('-----------error occur')
                team.save()
                return render(request, 'app1.html', args)

        args = {'form': form}
        return render(request, 'app1.html', args)
    else:
        form = TeamForm()
        args = {'form': form}
        return render(request, 'app1.html', args)

app1.html app1.html

<html>
<head>

    <title>gffdfdf</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="/static/jquery.formset.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

</head>
<body>

<div class="container">

    <form id="myForm" action="" method="post" class="">
        {% csrf_token %}
        <h2> Team</h2>
        {% for field in form %}
            {{ field.errors }}
            {{ field.label_tag }} : {{ field }}
        {% endfor %}
        {{ form.players.management_form }}

        <h3> Product Instance(s)</h3>
        <table id="table-product" class="table">
            <thead>
            <tr>
                <th>player name</th>
                <th>highest score</th>
                <th>age</th>
            </tr>

            </thead>
            {% for player in form.players %}
                <tbody class="player-instances">

                <tr>
                    <td>{{ player.name }}</td>
                    <td>{{ player.score }}</td>
                    <td>{{ player.age }}</td>
                </tr>

                </tbody>
            {% endfor %}
        </table>
        <button type="submit" class="btn btn-primary">save</button>

    </form>
</div>
<script>
    $(function () {
        $('#myForm tbody tr').formset();
    })
</script>
</body>
</html>

screen like: 屏幕像: 在此处输入图片说明

I would tackle this problem by using modelForms for creating questions, and then redirecting to a page where you can add the number of questions you specified when you created the question. 我将通过使用modelForms创建问题,然后重定向到页面来添加创建问题时指定的问题数量,以解决此问题。 This add_answers page won't use Django forms, we can just use a simple html form and then get the form data in the view. 这个add_answers页面不会使用Django表单,我们可以只使用一个简单的html表单,然后在视图中获取表单数据。 Here are the views: 这里是视图:

views.py : views.py

from django.shortcuts import render, redirect
from .forms import QuestionForm
from .models import Question, Answer

# Create your views here.

def add_question(request):
    form = QuestionForm(request.POST or None)
    if request.method == "POST":
        if form.is_valid():
            question = form.cleaned_data.get('question')
            number_of_answers = form.cleaned_data.get('number_of_answers')
            create_question = Question.objects.create(question=question, number_of_answers=number_of_answers)
            create_question.save()
            return redirect('home:add-answers', id=create_question.id)
    return render(request, 'home/add_question.html', {'form': form})


def add_answers(request, id):
    question = Question.objects.get(id=id)
    if request.method == "POST":
        for i in request.POST.getlist('answers'):
            _ = Answer.objects.create(answer=i, question=id)
            _.save()

    num_answers = question.number_of_answers
    context = {"num_answers":range(num_answers), 'question':question}
    return render(request, 'home/add_answers.html', context)

add_question uses model forms: add_question使用模型形式:

forms.py : form.py

from django import forms
from .models import Question, Answer

class QuestionForm(forms.ModelForm):

    class Meta:
        model = Question
        fields = ['question','number_of_answers']

We can access this form in the template: 我们可以在模板中访问此表单:

<form method="POST" action=".">
    {{ form }}
    {% csrf_token %}
    <input type="submit">Submit</input>
</form>

For add_answers , we do the following: 对于add_answers ,我们执行以下操作:

<form method="POST" action=".">
    {% for i in num_answers %}
        <input type="text" name="answers"></input>
        <br />
    {% endfor %}
    {% csrf_token %}
    <input type="submit">Submit</input>
</form>

Where num_answers is a context variable that is range(number_of_answers) . 其中num_answers是一个范围为range(number_of_answers)的上下文变量。

Edit: here is the urls.py file: 编辑:这是urls.py文件:

from django.conf.urls import url, include
from . import views

urlpatterns = [
    url(r'^add-answers/(?P<id>\d+)/$', views.add_answers, name="add-answers"),
    url(r'^add-question/$', views.add_question, name="add-question"),
]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM