如何将 django forms.py 选择项转换为 html 中的列表?
Posted
技术标签:
【中文标题】如何将 django forms.py 选择项转换为 html 中的列表?【英文标题】:How can I convert django forms.py select items to a list in html? 【发布时间】:2021-07-18 13:49:12 【问题描述】:我有一个表格,我打算用它来记录学生的分数。我有一个问题,比如我不知道最好的表达方式,所以我有所有学生的学生姓名和标记字段。调用 form
会带来带有选择下拉项目的表单(不是我想要的)。指定表单字段不会填充任何内容。即
% for field in form %
field.student
field.marks
% endfor %
这是表格
class AddMarksForm(forms.ModelForm):
def __init__(self, school,klass,term,stream,year, *args, **kwargs):
super(AddMarksForm, self).__init__(*args, **kwargs)
self.fields['student'] = forms.ModelChoiceField(
queryset=Students.objects.filter(school=school,klass__name__in=klass,stream__name=stream[0]))
class Meta:
model = Marks
fields = ('student','marks')
这就是我尝试 html 渲染的方式
<form method="post" enctype="multipart/form-data" action="% url 'add_marks' %">
% csrf_token %
% if form %
<table>
<tr>
<td>Student</td>
<td>Marks</td>
</tr>
% for field in form %
<tr>
<td> field.student </td>
<td> field.marks </td>
</tr>
</table>
% endfor %
<button class="btn btn-outline-primary">Save</button>
</form>
我的模型。
class Year(models.Model):
year = models.IntegerField(validators=[MinValueValidator(2018), MaxValueValidator(4000),])
year_term = models.ForeignKey('exams.Term',on_delete=models.SET_NULL,related_name='year_term', null=True,blank=True)
class Subject(models.Model):
name = models.CharField(max_length=50)
teacher = models.ForeignKey(TeacherData,on_delete=models.CASCADE)
students = models.ManyToManyField(Students)
class Term(models.Model):
year = models.ForeignKey(Year,on_delete=models.CASCADE)
name = models.CharField(max_length=30)
exam_term = models.ForeignKey('exams.Exam',on_delete=models.SET_NULL,null=True,blank=True,related_name='exam_term')
class Exam(models.Model):
school = models.ForeignKey(School,on_delete=models.CASCADE)
year = models.ForeignKey(Year,on_delete=models.SET_NULL, null=True)
term = models.ForeignKey(Term,on_delete=models.SET_NULL, null=True)
name = models.CharField(max_length=20)
klass = models.ManyToManyField("students.Klass", related_name='klass',null=True,blank=True)
class Marks(models.Model):
exam = models.ForeignKey(Exam,on_delete=models.SET_NULL,null=True,blank=True)
subject = models.ForeignKey(Subject,on_delete=models.SET_NULL,null=True,blank=True)
student = models.ForeignKey(Students,on_delete=models.SET_NULL,null=True,blank=True)
marks = models.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(100),] ,null=True,blank=True)
更多型号
class Klass(models.Model):
name = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(4),], help_text='E.g 1,2,3, 4')
school = models.ForeignKey(School,on_delete=models.CASCADE)
exam = models.ForeignKey("exams.Exam",on_delete=models.CASCADE, related_name='exam',null=True,blank=True)
class Stream(models.Model):
name = models.CharField(max_length=50,help_text='Name of the stream')
klass = models.ForeignKey(Klass,on_delete=models.CASCADE,help_text='Choose a class the stream belongs to')
class Students(models.Model):
id = models.AutoField(primary_key=True)
#student_user = models.OneToOneField(User, on_delete=models.CASCADE,null=True,blank=True)
school = models.ForeignKey(School,on_delete=models.CASCADE,help_text='A school must have a name')
adm = models.IntegerField(unique=True,validators=[MinValueValidator(1), MaxValueValidator(1000000),],help_text="Student's admission number" )
name = models.CharField(max_length=200,help_text="Student's name")
kcpe = models.IntegerField(validators=[MinValueValidator(100), MaxValueValidator(500),], help_text='What the student scored in primary')
klass = models.ForeignKey(Klass, on_delete=models.CASCADE,null=True,help_text="Student's Class/Form")
stream = models.ForeignKey(Stream,on_delete=models.CASCADE,blank=True,null=True,help_text="Student's Stream")
gender = models.ForeignKey(Gender,on_delete=models.CASCADE,null=True,help_text="Student's Gender")
notes = models.TextField(blank=True,null=True,help_text='Anything to say about the student. Can always be edited later')
【问题讨论】:
你好,请问可以添加Marks
型号吗?
我添加了模式;
我理解正确吗,您基本上想要一个表格,在左栏中您只有一个名称(无法更改),然后在右栏中有一个用于标记的数字字段?
你说的很对,这就是我所需要的。
【参考方案1】:
这是我基于问题 cmets 讨论的建议。
# models.py
class User(models.Model):
is_teacher = models.BoolField(default=False)
is_student = models.BoolField(default=False)
class Subject(models.Model):
taught_by = models.ForeignKey(User, on_delete=models.PROTECT, limit_choices_to="is_teacher": True)
students = models.ManyToManyField(User, limit_choices_to="is_student": True)
class Exam(models.Model):
subject = models.ForeignKey(Subject, on_delete=models.CASCADE)
class Marks(models.Model):
exam = models.ForeignKey(Exam, on_delete=models.CASCADE)
student = models.ForeignKey(User, on_delete=models.CASCADE, limit_choices_to="is_student": True)
marks = models.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(100),], null=True, blank=True)
# no need for a subject field here, that is linked through the Exam object
class Meta:
unique_togetger = [('exam', 'student'),]
我只写了重要的字段,你可以添加更多你需要的字段。
# views.py
class AddMarks(views.View):
def get(self, request, exam_id):
try:
exam = Exam.objects.get(id=exam_id)
except Exam.DoesNotExist:
# some kind of handler that returns (important!)
context =
"students": exam.subject.students.all()
"current_marks": Marks.objects.filter(exam=exam)
return render("add_marks.html", context=context)
def post(self, request, exam_id):
try:
exam = Exam.objects.get(id=exam_id)
except Exam.DoesNotExist:
# some kind of handler that returns (important!)
for student in exam.subject.students.all():
marks = int(request.POST.get(f"marks_student.username", None))
if marks:
# if that particular marks field exists in POST and is filled, let's update (if it exists) or create a new marks object
marks_object = Marks.objects.filter(exam=exam, student=student).first() or Marks(exam=exam, student=student)
marks_object.marks = marks
marks_object.save()
return self.get(request, exam_id)
<!--add_marks.html-->
<form method="POST">
<table>
% for student in students %
<tr>
<td> student.get_full_name </td>
<td><input type="number" name="marks_ student.username " /></td>
</tr>
% endfor %
% if students %
<tr><td colspan="2"><input type="submit" value="Save marks" /></td></tr>
% else %
<tr><td colspan="2">No student is taking this class</td></tr>
% endif %
</table>
</form>
% if current_marks %
<h3>Currently saved marks</h3>
<table>
% for marks in current_marks %
<tr>
<td> marks.student.get_full_name </td>
<td> marks.marks </td>
</tr>
% endfor %
</table>
% endfor %
我确实做了一些更改。最引人注目的是Student
模型,或者说缺少它。我已将User
标记为学生或教师,允许您的学生登录并查看他们的成绩或注册课程。
其次,正如代码中提到的,Marks
模型中不需要subject
字段,因为可以从Exam
本身提取数据。
最后关于它的作用。它将创建一个包含表格的表单,其中每一行将包含一个名为marks_<username>
的字段。然后可以在post
方法处理程序中检索该字段。如果该字段存在并且具有值,则视图将更新现有的,或创建一个新的Marks
模型。如果已经保存了任何标记,它们将显示在下面的单独表格中。
我已经完全删除了表格,因为在这种情况下这是多余的。如果您真的想这样做,也许在其他地方,可以通过使用 Django 的 FormSet API 来实现这一页上的多个表单。关于它的文档是[这里][1]。这使您可以一个接一个地堆叠许多相同类型的表格,以便一次编辑多行。但由于我们实际上只有一个字段,我发现自己处理一个字段更容易。
最后一件事,我没有写任何错误检查和处理。我会留给你的。需要处理的潜在地方是两个 except 块,它们需要从方法返回,以便不执行下面的代码。一些不错的 404 页面就足够了。另一个地方是获取POST
内容的int()
调用。如果发送了非整数值,这可能会引发异常。您应该能够使用简单的 try-except
块来处理它。
【讨论】:
嘿伙计,我真的想通了。友情提示,你最好这样! ? 感谢您的详细解答。 看起来你有时开发了一些符合这个的东西?? 不,我有很多 Django。主要是娱乐节目。今天我想在 *** 上写一个太长的答案。简而言之我的生活。 这一行是什么意思?marks_object = Marks.objects.filter(exam=exam, student=student).first() or Marks(exam=exam, student=student)以上是关于如何将 django forms.py 选择项转换为 html 中的列表?的主要内容,如果未能解决你的问题,请参考以下文章