Как фильтровать объекты внешнего ключа в запросах django? - PullRequest
1 голос
/ 12 апреля 2019

У меня есть две модели, одна связана с другой foreign key вот так

class CapturedPrescriptionModel(ColModel):
    p_id = models.IntegerField()
    p_age = models.IntegerField()
    p_gender = models.CharField(max_length=10)
    p_care_type = models.CharField(max_length=100)
    bacteria_id = models.ForeignKey(BacteriaListModel, 
              on_delete=models.CASCADE, null=True)

class SuggestedAntibioticsModel(ColModel):
    prescription_id = models.ForeignKey(CapturedPrescriptionModel, 
                  related_name='antibiotics', 
                   on_delete=models.CASCADE)
    cat_ids = models.TextField()
    flag = models.IntegerField(default=0)

Теперь я хочу все prescriptions с suggested antibiotics где flag=1

IЯ пытался использовать CapturedPrescriptionModel.objects.filter(antibiotics__flag=1), но это позволяет отфильтровать рецепты, а не список антибиотиков в наборе запросов.

 [
    {
    "id": 7,
    "p_id": 0,
    "p_age": 19,
    "p_gender": "Male",
    "p_care_type": "ICU",
    "bacteria_id": null,
    "antibiotics": [
        {
            "id": 188,
            "cat_ids": "[]",
            "flag": 0,
            "antibiotic_id_id": 87,
            "prescription_id_id": 7
        },
        {
            "id": 187,
            "cat_ids": "[]",
            "flag": 1,
            "antibiotic_id_id": 112,
            "prescription_id_id": 7
        },
      ......
      ]
}
....
]

Мой ожидаемый результат будет таким:

    [
        {
        "id": 7,
        "p_id": 0,
        "p_age": 19,
        "p_gender": "Male",
        "p_care_type": "ICU",
        "bacteria_id": null,
        "antibiotics": [
            {
                "id": 187,
                "cat_ids": "[]",
                "flag": 1,
                "antibiotic_id_id": 112,
                "prescription_id_id": 7
            }
          ]
}
....
]

Ответы [ 2 ]

3 голосов
/ 12 апреля 2019

Вам нужен отфильтрованный Prefetch, если вы хотите фильтровать только связанные объекты, а не главные объекты:

from django.db.models import Prefetch

CapturedPrescriptionModel.objects.prefetch_related(Prefetch(
    'antibiotics',
    queryset=SuggestedAntibioticsModel.objects.filter(flag=1)
)

Затем вам нужно убедиться, что antibiotics для отдельных объектов предписанияДоступ осуществляется только с помощью prescription.antibiotics.all(), иначе предварительная выборка не используется, и вы снова получите все антибиотики.

0 голосов
/ 12 апреля 2019

Соберите все рецепты:

prescriptions = CapturedPrescriptionModel.objects.all()

for prescription in prescriptions:
    prescription.antibiotics = prescription.antibiotics.filter(flag=1)

# at this time presciptions should be prepared, just make sure to not save them...

Вы также можете расширить свою модель, чтобы иметь свойство для этого списка.

class CapturedPrescriptionModel(ColModel):
    p_id = models.IntegerField()
    p_age = models.IntegerField()
    p_gender = models.CharField(max_length=10)
    p_care_type = models.CharField(max_length=100)
    bacteria_id = models.ForeignKey(BacteriaListModel, 
              on_delete=models.CASCADE, null=True)

    @property
    def flagged_antibiotics(self):
        try:
            return self.antibiotics.filter(flag=1)
        except Exception:
            return []

class SuggestedAntibioticsModel(ColModel):
    prescription_id = models.ForeignKey(CapturedPrescriptionModel, 
                  related_name='antibiotics', 
                   on_delete=models.CASCADE)
    cat_ids = models.TextField()
    flag = models.IntegerField(default=0)

Примерно так будет мой первый взгляд на это

...