У меня есть две модели, одна связана с другой 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

Я пытался с 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
            }
          ]
}
....
]
1
sankycse 12 Апр 2019 в 10:57

2 ответа

Лучший ответ

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

from django.db.models import Prefetch

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

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

3
Endre Both 12 Апр 2019 в 08:16

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

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)

Что-то вроде этого было бы моим первым взглядом на это

0
Bloodmallet 12 Апр 2019 в 08:14