使用Django REST框架,我想知道是否有可能将模型上的ManyToMany
字段的选择/选项限制为特定的QuerySet
?
使用下面的模型(向下滚动查看模型),我很好奇是否有可能在模型的定义中定义这个限制,以实现以下目标:
# Having the following Employee instance
emp = Employee(...)
# Should return only the instances with value 'case' in EmployeeSubstitute.type field
emp.substitute_case.all()
# Should return only the instances with value 'phone' in EmployeeSubstitute.type field
emp.substitute_phone.all()
模型:
class Employee(models.Model):
substitute_case = models.ManyToMany(through=EmployeeSubstitute, ...)
substitute_phone = models.ManyToMany(through=EmployeeSubstitute, ...)
class EmployeeSubstitute(models.Model):
from = models.ForeignKey(Employee, ...)
to = models.ForeignKey(Employee, ...)
type = models.CharField(choices=..., ...) # choose between type 'case' and 'phone'
我看到有limit_choices_to
参数,但这不是我要找的,因为它只影响使用ModelForm或admin时显示的选项。
那么,ManyToManyField
返回相关对象和文档状态
默认情况下,Django使用Model的一个实例。_base_manager经理类访问相关对象时(即choice.question),而不是相关对象上的_default_manager。这是因为Django需要能够检索相关的对象,即使它不能被默认管理器过滤掉(因此不可访问)。
如果正常的基管理器类(django.db.models.Manager)不是根据具体情况,你可以告诉Django哪个类应该使用它通过设置Meta.base_manager_name.
基础管理器在查询相关模型时不使用,或者当访问一对多或多对多关系。例如,如果教程中的Question模型有一个已删除的字段和一个基过滤带有deleted=True的实例的管理器,类似于查询集Choice.objects.filter(question__name__startswith='What')将包括与删除问题相关的选项。
如果我没看错的话,不,这是不可能的
当你在ManyToManyField
中有through
的查询时,Django抱怨你应该在through
模型上运行这些查询,而不是在"父模型"上运行。我在文档中找不到,但我记得见过几次。
substitute_case
和substitute_phone
是属于代换的东西,它是它的类型。所以就这样做,而不是在Employee
中创建这些列。
from django.db import models
class SubstituteTypes(models.TextChoices):
case = "case", "case"
phone = "phone", "phone"
class EmployeeSubstituteQueryset(models.QuerySet):
def from_employee(self, e):
return self.filter(_from=e)
def case(self):
return self.filter(type=SubstituteTypes.case)
def phone(self):
return self.filter(type=SubstituteTypes.phone)
class Employee(models.Model):
substitute = models.ManyToManyField(through='EmployeeSubstitute', to='self')
class EmployeeSubstitute(models.Model):
_from = models.ForeignKey(Employee, on_delete=models.CASCADE, related_name='a')
to = models.ForeignKey(Employee, on_delete=models.PROTECT, related_name='b')
type = models.CharField(choices=SubstituteTypes.choices, max_length=5, db_index=True)
objects = EmployeeSubstituteQueryset.as_manager()
然后,一旦你得到你的emp
对象(或只有它的id),你可以做
EmployeeSubstitute.objects.from_employee(emp).case().all()