开发者社区 问答 正文

Django:我的对象A的B上有FK。如何以A的形式在下拉列表中显示B中的列?

我收到错误“为会话指定了未知字段(主题,主题)”。我正在尝试在sessionForm中创建主题和主题的下拉列表。

我的模型如下:

class Subject(models.Model): name = models.CharField(max_length = 30, primary_key = True)

def __str__(self):
  return self.name

class Meta:
    db_table = 'subjects'  

class Module(models.Model): topic = models.CharField(max_length = 200)
subject = models.ForeignKey(Subject, on_delete=models.CASCADE)

def str(self): return self.topic + ' in ' + self.subject.name

class Meta: db_table = 'modules'

class Session(models.Model): grade_level = models.CharField(max_length = 30) num_students = models.IntegerField(default=0) session_dt = models.DateTimeField() module = models.ForeignKey(Module, on_delete=models.CASCADE)

@property def subject(self): return self.module.subject

def topic(self): return self.module.topic

def str(self): return self.module.topic + ' on ' + self.session_dt

class Meta: db_table = 'sessions' 我的forms.py是

class SessionForm(forms.ModelForm):

class Meta:
    model = Session      
    fields = ['subject', 'topic', 'session_dt', 'grade_level', 'num_students']

我是Django和Python的新手。我已经看过下拉列表中的Vitor Freitas文章。

展开
收起
被纵养的懒猫 2019-09-24 13:21:34 445 分享 版权
阿里云 AI 助理回答

你遇到的错误信息“为会话指定了未知字段(主题,主题)”表明Django在尝试处理SessionForm时,在Session模型中找不到直接名为subjecttopic的字段。这是因为你在Session模型中定义了这两个属性作为方法(通过使用@property装饰器和普通函数),而不是实际的数据库字段。

要创建基于Module模型中的subjecttopic字段的下拉列表,你需要在SessionForm中使用Django的ModelChoiceField来引用关联模型的字段。这里是如何修改你的forms.py以实现这一点:

from django import forms
from .models import Session, Module, Subject

class SessionForm(forms.ModelForm):
    # 使用ModelChoiceField来创建Subject的下拉选择
    subject = forms.ModelChoiceField(
        queryset=Subject.objects.all(),
        empty_label=None,  # 如果需要显示空选项,可以改为"请选择"
        to_field_name='name',  # 这里假设你想用Subject的name作为选项显示
    )

    # 对于topic,我们需要先获取与选定subject相关的modules
    def __init__(self, *args, **kwargs):
        super(SessionForm, self).__init__(*args, **kwargs)
        if 'instance' in kwargs and kwargs['instance'].module:
            self.fields['topic'] = forms.ModelChoiceField(
                queryset=Module.objects.filter(subject=kwargs['instance'].module.subject),
                empty_label=None,
                to_field_name='topic',
            )
        else:
            # 如果没有实例或者实例的module未设置,则提供所有topic或不提供选择
            self.fields['topic'] = forms.ModelChoiceField(
                queryset=Module.objects.none(),  # 或者提供一个默认的queryset
                empty_label="请选择一个主题",
                to_field_name='topic',
            )

    class Meta:
        model = Session
        fields = ['grade_level', 'num_students', 'session_dt']  # 移除'subject', 'topic',因为我们手动添加了它们

    # 注意:这样处理后,表单提交后的处理逻辑可能也需要相应调整,确保能正确保存关联的对象。

这段代码首先定义了一个subject字段,它是一个直接指向Subject模型的选择字段。然后,在__init__方法中动态地为topic字段设置了查询集,这个查询集仅包含与所选subject相关的Module对象。如果表单是用于编辑现有Session实例,那么我们根据实例的module.subject来过滤Module;如果是新建表单,则可能需要根据实际情况决定是否提供可选项或默认值。

请记住,这种形式的动态字段设置可能会使表单逻辑变得复杂,特别是当涉及到表单验证和数据保存时。务必确保在视图中正确处理这些表单,并且理解如何将用户的选择映射回模型实例进行保存。

有帮助
无帮助
AI 助理回答生成答案可能存在不准确,仅供参考
0 条回答
写回答
取消 提交回答
问答分类:
问答标签:
问答地址: