为相关模型创建 Django 表单
Creating django form for related models
我定义了以下模型:
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)
我希望用户能够创建问题及其相应的答案。
基本上,我想创建一个表单,要求用户输入问题和问题的答案数。根据指定的答案数,我想为每个答案创建那么多的文本字段。我希望能够将每个答案连接到数据库中相应的问题。
在 Python Django 中执行此操作的最佳方法是什么?我已经提供了视觉效果的图像。
Getting question and number of answers,
getting answers based on question and number of answers specified
看看formsets.And combine with django-dynamic-forms可以帮助您自定义网页以添加问题和答案。
这里有一个添加球队及其球员的演示。
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
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
<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>
屏幕如下:
我会通过使用 modelForms 创建问题来解决这个问题,然后重定向到一个页面,您可以在其中添加创建问题时指定的问题数量。这个 add_answers
页面不会使用 Django 表单,我们可以只使用一个简单的 html 表单,然后在视图中获取表单数据。以下是观点:
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
使用模型形式:
forms.py:
from django import forms
from .models import Question, Answer
class QuestionForm(forms.ModelForm):
class Meta:
model = Question
fields = ['question','number_of_answers']
我们可以在模板中访问此表单:
<form method="POST" action=".">
{{ form }}
{% csrf_token %}
<input type="submit">Submit</input>
</form>
对于 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>
其中 num_answers
是上下文变量,即 range(number_of_answers)
。
编辑:这里是 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"),
]
我定义了以下模型:
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)
我希望用户能够创建问题及其相应的答案。
基本上,我想创建一个表单,要求用户输入问题和问题的答案数。根据指定的答案数,我想为每个答案创建那么多的文本字段。我希望能够将每个答案连接到数据库中相应的问题。
在 Python Django 中执行此操作的最佳方法是什么?我已经提供了视觉效果的图像。 Getting question and number of answers, getting answers based on question and number of answers specified
看看formsets.And combine with django-dynamic-forms可以帮助您自定义网页以添加问题和答案。
这里有一个添加球队及其球员的演示。
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
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
<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>
屏幕如下:
我会通过使用 modelForms 创建问题来解决这个问题,然后重定向到一个页面,您可以在其中添加创建问题时指定的问题数量。这个 add_answers
页面不会使用 Django 表单,我们可以只使用一个简单的 html 表单,然后在视图中获取表单数据。以下是观点:
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
使用模型形式:
forms.py:
from django import forms
from .models import Question, Answer
class QuestionForm(forms.ModelForm):
class Meta:
model = Question
fields = ['question','number_of_answers']
我们可以在模板中访问此表单:
<form method="POST" action=".">
{{ form }}
{% csrf_token %}
<input type="submit">Submit</input>
</form>
对于 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>
其中 num_answers
是上下文变量,即 range(number_of_answers)
。
编辑:这里是 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"),
]