如何将 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_&lt;username&gt; 的字段。然后可以在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 中的列表?的主要内容,如果未能解决你的问题,请参考以下文章

Django在forms.py中使用视图或url中的变量

django中的日期时间选择器不使用forms.py

Django模型中的下拉列表

如何将 Django 日期格式更改为 dd/mm/yy?

Django 形式的懒惰选择

在 Django 中使用 AJAX 更新数据库