Django (DRF) ManyToMany field choices / limit



使用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_casesubstitute_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()

最新更新