Django - ForeignKey过滤器选项



我想过滤用户可以在我的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)

最新更新