我想过滤用户可以在我的ForeignKey字段中选择的选项。我基本上有一个外键的测试主题和测试的实际主题。这些主题来自不同的模型,并链接到一个主题。现在我想过滤选项,只包括链接到当前选定主题的主题。这可能吗?如果可能,怎么做?
models.py
class Test(models.Model):
student = models.ForeignKey(Person, on_delete=models.CASCADE, blank=True, null=True)
subject = models.ForeignKey(Subject, on_delete=models.CASCADE, blank=True, null=True)
thema = models.ForeignKey(Thema, on_delete=models.CASCADE, blank=True, null=True)
school_class = models.ForeignKey(SchoolClass, on_delete=models.CASCADE, blank=True, null=True)
grade = models.FloatField(validators=[MinValueValidator(0), MaxValueValidator(6)], blank=True, null=True)
date = models.DateField(default=datetime.date.today)
def save(self, *args, **kwargs):
if not self.school_class and self.student:
self.school_class = self.student.klasse
return super().save(*args, **kwargs)
class Thema(models.Model):
subject = models.ForeignKey(Subject, on_delete=models.CASCADE, blank=True, null=True)
thema = models.CharField(max_length=50)
class Subject(models.Model):
teacher = models.ForeignKey(Person, on_delete=models.CASCADE, blank=True, null=True)
name = models.CharField(max_length=20)
如果我使用这个问题:
# thema model @staticmethod
def return_thema(subject):
themen = Thema.objects.filter(subject=subject)
return {'thema': themen}
#test model
thema = models.ForeignKey(Thema, on_delete=models.CASCADE, blank=True, null=True,limit_choices_to=Thema.return_thema(subject))
是我得到错误:django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet.
这意味着当模型正在加载时我无法获得主题模型的对象
EDIT (for Swift):这似乎解决了尝试迁移时的错误,但我现在得到这个错误,当访问管理门户创建一个新的Test:
File "/Users/di/Code/Schule/GymnasiumApp/venv/lib/python3.10/site-packages/django/db/models/sql/query.py", line 1404, in build_filter
arg, value = filter_expr
ValueError: too many values to unpack (expected 2)
我想你理想的选择是ForeignKey.limit_choices_to
请参阅文档:
https://docs.djangoproject.com/en/dev/ref/models/fields/django.db.models.ForeignKey.limit_choices_to
你可以在模型级别限制可用的选项,这在django应用程序中强制执行,包括自动执行表单。
编辑,因为OP提供了更多信息
好的,所以我相信如果你像这样在测试模型上声明thema字段,它将解决问题,我将在后面解释为什么:
class Test(models.Model):
student = models.ForeignKey(Person, on_delete=models.CASCADE, blank=True, null=True)
subject = models.ForeignKey(Subject, on_delete=models.CASCADE, blank=True, null=True)
thema = models.ForeignKey(Thema, on_delete=models.CASCADE, blank=True, null=True, limit_choices_to=Q('thema_set__subject_set'))
school_class = models.ForeignKey(SchoolClass, on_delete=models.CASCADE, blank=True, null=True)
grade = models.FloatField(validators=[MinValueValidator(0), MaxValueValidator(6)], blank=True, null=True)
date = models.DateField(default=datetime.date.today)
def save(self, *args, **kwargs):
if not self.school_class and self.student:
self.school_class = self.student.klasse
return super().save(*args, **kwargs)
我们实际上是在告诉Django评估有限选项之间的关系" lazy "也就是说,表单是动态加载的。Django表单会查看limit_choices_to
字段参数,并将其应用到可用的选项中。
我不是100%了解你的模型之间的关系,所以我添加的Q(...)
可能实际上需要Q('subject_set')
如果你使用django表单,你可以使用model choice字段。在您的视图中,您可以设置此选择字段的查询集。所以你可以过滤。
fields['your model field'].queryset = yourmodel.objects.filter(your filter parameters)
我认为保存方法也有问题。难道你不需要在里面写上模型的名字吗?
return super(<modelName>).save(*args, **kwargs)