【问题标题】:Filtering the options of ModelChoiceField in forms in django as per the ForeignKey relations根据 ForeignKey 关系在 django 的表单中过滤 ModelChoiceField 的选项
【发布时间】:2017-05-28 17:36:07
【问题描述】:

在我的 django 项目中,我创建了三个模型类。 “Subtopic”类与“Chapter”类具有 ForeignKey 关系,“SAQ”类与“Chapter”类和“Subtopic”类具有 ForeignKey 关系。

#models.py

from django.db import models
class Chapter(models.Model):
    chapter_serial = models.IntegerField(null=False, help_text="Chapter No.")
    slug = models.SlugField(unique=True, blank=True)
    chapter_name = models.CharField(max_length=120)

    class Meta:
        ordering = ["chapter_serial"]

    def get_saq_list_url(self):
        return reverse("cms:saq_list", kwargs={"chap_slug":self.slug})

class Subtopic(models.Model):
    subtopic_serial = models.IntegerField(null=False)
    title = models.CharField(max_length=240)
    chapter = models.ForeignKey('Chapter', on_delete=models.CASCADE)

    class Meta:
        ordering = ["subtopic_serial"]

class SAQ(models.Model):
    question_serial = models.IntegerField(null=False)
    question = models.TextField()
    answer = models.TextField()
    chapter = models.ForeignKey('Chapter', on_delete=models.CASCADE)
    subtopic = models.ForeignKey('Subtopic', on_delete=models.CASCADE, null=True, blank=True)

    class Meta:
        ordering = ["question_serial"]

我尝试使用 django ModelForm 为“模型 SAQ”创建表单,这样对于与特定章节实例关联的每个“SAQ 表单”,模型“子主题”的选择字段将仅包含该特定章节实例的那些子主题。

#forms.py
from django import forms
from .models import SAQ

class SAQForm(forms.ModelForm):

    class Meta:
        model = SAQ
        fields = [
            'question_serial',
            'question',
            'answer',
            'important',
            'remarks',
            'subtopic',
        ]

创建表单的django视图函数如下。

from django.shortcuts import render, get_object_or_404, redirect
from .models import SAQ, Chapter, Subtopic
from .forms import SAQForm
from django.http import HttpResponseRedirect

def saq_create(request, chap_slug=None):
    chapter_instance = get_object_or_404(Chapter, slug=chap_slug)
    form = SAQForm(request.POST or None)
    if form.is_valid():
        instance = form.save(commit=False)
        instance.chapter = chapter_instance
        instance.save()
        return HttpResponseRedirect(chapter_instance.get_saq_list_url())
    context = {
        "form":form,
        "chapter_instance":chapter_instance,
    }
    return render(request, 'cms/saq_form.html', context)

使用此配置,表单中的选择字段“子主题”会显示所有章节实例的所有子主题。任何建议都会非常有帮助。

【问题讨论】:

    标签: python django django-models django-forms django-views


    【解决方案1】:

    我建议覆盖表单 init 并传递章节实例,以便您可以过滤子主题查询集。

    示例(未经测试,可能包含拼写错误):

    #forms.py
    from django import forms
    from .models import SAQ
    
    class SAQForm(forms.ModelForm):
    
        class Meta:
            model = SAQ
            fields = [
                'question_serial',
                'question',
                'answer',
                'important',
                'remarks',
                'subtopic',
            ]
    
        def __init__(self, chapter, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.fields['subtopic'].queryset = \
                self.fields['subtopic'].queryset.filter(chapter=chapter)
    

    然后你的视图应该将章节实例传递给表单:

    chapter_instance = get_object_or_404(Chapter, slug=chap_slug)
    form = SAQForm(chapter_instance, request.POST or None)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-07
      • 2021-05-26
      • 2010-10-11
      • 2020-10-17
      • 1970-01-01
      • 2022-11-12
      相关资源
      最近更新 更多