Фильтрация поля related_name, в django - PullRequest
1 голос
/ 21 апреля 2020

Я пытаюсь отфильтровать поле related_name с запросом, если это возможно. Я сериализирую таблицы.

class ProjectsSerializers(serializers.ModelSerializer):
    class Meta:
        model = Projects
        fields = ["id", "project_id", "project_name", "tasks"]
        depth = 1

Выше в списке полей. tasks - это related_table, поэтому в таблице задач у меня есть поле task_created_at и когда я получаю таблицу проектов. Я хочу отфильтровать его по этому полю.

def get_projects(request):
  projects = Projects.objects.filter(task_created_at__startswith="2020-04")
  serializer = ProjectsSerializers(projects, many=True)
  return Response(serializer.data)

Конечно, это: task_created_at__startswith="2020-04" не работает. Потому что task_created_at нет в проектах. это в related_name, что tasks. Так есть ли способ фильтрации задач с получением проектов

и соответствующих моделей:

class Projects(models.Model):

    project_id = models.CharField(max_length=255)
    project_name = models.CharField(max_length=255)  

    def __str__(self):
        return self.project_name

    class Meta:
        db_table = "projects"

class Tasks(models.Model):

    projects = models.ForeignKey(Projects, on_delete=models.CASCADE, related_name='tasks', blank=True, null=True)
    task_price = models.IntegerField(blank=True, null=True)
    task_total_price = models.IntegerField(blank=True, null=True)
    task_created_at = models.CharField(max_length=255, blank=True, null=True)

    def __str__(self):
        return self.ad_kind

    class Meta:
        db_table = "tasks"

пример данных:

[
    {
        "id": 6,
        "order_id": null,
        "project_id": "23123",
        "project_name": "プレサンス グラン 茨木駅前",
        "company_name": null,
        "analytics_id": null,
        "advertisements": [],
        "tasks": [
            {
                "id": 1,
                "task_total_price": null,
                "task_created_at": "2020-04-02",
                "task_due_date": "2020-04-07",
                "task_modified_at": "2020-04-07T06:42:41.447Z",
                "projects": 6
            },
            {
                "id": 2,
                "task_total_price": null,
                "task_created_at": "2020-02-02",
                "task_due_date": "2020-03-07",
                "task_modified_at": "2020-04-07T06:42:41.447Z",
                "projects": 6
            },
        ]
    }
]

Ответы [ 3 ]

2 голосов
/ 21 апреля 2020

Вы можете присоединиться к двум таблицам / моделям по __ (двойное подчеркивание).

<b>from django.db.models import Prefetch</b>


def get_projects(request):
    <b>projects = Projects.objects.prefetch_related(
        Prefetch('tasks', queryset=Tasks.objects.filter(task_created_at__istartswith='2020-04'))
    ).filter(tasks__task_created_at__istartswith='2020-04')</b>

    serializer = ProjectsSerializers(projects, many=True)
    return Response(serializer.data))

Ссылка

1 голос
/ 21 апреля 2020

Вам нужно будет использовать подзапрос :

def get_projects(request):

    project_ids = Task.objects.filter(
      task_created_at__startswith='2020-04').values('project_id')
    projects = Project.objects.filter(id__in=project_ids)

    serializer = ProjectsSerializers(projects, many=True)
    return Response(serializer.data)

Также, пожалуйста, не используйте имена множественных таблиц ; -)

Наконец, я бы рекомендовал использовать DateTimeField для хранения дат вместо использования CharField.

0 голосов
/ 21 апреля 2020

Чтобы иметь возможность динамически изменять представление объекта, вы можете изменить сериализатор. Одним из способов фильтрации задач является предоставление serializers.SerializerMethodField, который фильтрует задачи динамически.

class TaskSerializer(serializers.ModelSerializer):
    class Meta:
        model  = Task
        fields = [ ... your fields ... ]


class ProjectSerializer(serializers.ModelSerializer):
    filtered_tasks = serializers.SerializerMethodField()

    class Meta:
        model  = Project
        fields = ["id", "project_id", "project_name", "filtered_tasks"]
        depth  = 1

    def get_filtered_tasks(self, obj):
        tasks = Task.objects.filter(created_at__startswith="2020-04")
        return TaskSerializer(tasks, many=True).data

Однако мне не нравится этот подход. Я думаю, что вы должны пересмотреть, как вы представляете данные. Такое ощущение, что вы слишком сильно связываете данные. Хотя я не знаю ваш вариант использования, поэтому не могу прийти с конкретными предложениями.

Кроме того, я изменил здесь названия, чтобы модели были единственными , так как это условность.

...