簡體   English   中英

Django (DRF) ManyToMany 字段選擇/限制

[英]Django (DRF) ManyToMany field choices / limit

使用 Django REST 框架 我想知道是否可以將 model 上ManyToMany字段的選擇/選項限制為特定的QuerySet

使用下面的模型(向下滾動查看模型),我很好奇是否可以在 model 的定義中定義此限制,以實現以下目標:

# 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 或管理員時顯示的選項。

好吧, ManyToManyField返回相關對象和文檔state

默認情況下,Django在訪問相關對象(即choice.question)時使用Model._base_manager manager class的一個實例,而不是相關object上的_default_manager。這是因為Django需要882828即使檢索到相關的29否則會被默認管理器過濾掉(因此無法訪問)。

如果正常的基礎管理器 class (django.db.models.Manager) 不適合您的情況,您可以通過設置 Meta.base_manager_name 告訴 Django 使用哪個 class。

在查詢相關模型或訪問一對多或多對多關系時,不使用基礎管理器。 例如,如果教程中的問題 model 有一個 deleted 字段和一個過濾掉 deleted=True 實例的基本管理器,則像 Choice.objects.filter(question__name__startswith='What') 這樣的查詢集將包括與已刪除問題相關的選項。

所以如果我沒看錯的話,不,這是不可能的。

當您在ManyToManyField中進行查詢並through時,Django 抱怨您應該through model 而不是“父級”運行這些查詢。 我在文檔中找不到它,但我記得看過幾次。

substitute_casesubstitute_phone是屬於 substitute 的東西,是它的類型。 因此,只需這樣做而不是在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 object (或只有它的 id),你就可以做

EmployeeSubstitute.objects.from_employee(emp).case().all()

這是在 Django 哲學中設計的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM