Django .objects, получение объединенных наборов запросов из разных моделей

У меня есть абстрактная базовая модель («База»), от которой наследуются две модели: «Кино» и «Мультфильм». Я вывожу пользователю список и фильмов, и мультфильмов (с помощью itertools.chain). Затем я хочу дать пользователю возможность удалить любой из этих элементов, не зная заранее, фильм это или мультфильм. Я пытаюсь сделать это так:

        ...

        movies = Movie.objects.filter(user_created=userlist).order_by('title')
        cartoons = Cartoon.objects.filter(user_created=userlist).order_by('title')

        all_items = list(chain(movies, cartoons))

        item = all_items.get(id=item_id)
        item.delete()

Но затем PyCharm заявляет:

Неразрешенная ссылка на атрибут "получить" для класса "список"

Я понимаю, почему это происходит, но я не знаю, как этого избежать. Есть ли способ объединить два набора запросов из разных моделей и применить получение или фильтрацию без удаления абстрактной базовой модели и создания физической родительской модели?


person Edmond    schedule 28.02.2020    source источник


Ответы (2)


Вы можете использовать ContentTypes framework для универсального и многоразового решения для это для произвольного количества различных моделей. Но мне также интересно, почему Cartoon и Movie должны быть разными типами для начала; возможно, стоит потратить немного времени на размышления о том, можно ли использовать единую модель для обоих типов медиа — удаление произвольного экземпляра — это лишь один из многих случаев, когда единая модель будет более простой, чем полагаться на что-то вроде ContentTypes.

РЕДАКТИРОВАТЬ: Для получения дополнительной информации о ContentTypes. Вы можете либо создать базовую модель с общим отношением (вы сказали, что не хотите этого делать), либо для удаления вы можете включить метку приложения и имя модели в данные запроса вместе с идентификатором элемента, что позволит выполнять поиск, например:

    media_type = ContentType.objects.get(app_label=app_label, model=model_name)
    instance = media_type.get_object_for_this_type(id=item_id)
    instance.delete()

что хорошо в этом подходе, так это то, что вам едва ли придется менять структуру модели.

person nthall    schedule 28.02.2020
comment
Меня особенно интересует работа с несколькими моделями. Например, объект Cartoon может иметь такие поля, как «paint_used» или «for_adults» и т. д., а объект Movie может иметь такие поля, как «movie_type», «age_restriction» и т. д. Мне не нравится использовать все поля для обеих моделей, заполняя эти специфичные для объекта поля значением None, так как это все испортит. Я видел документацию по фреймворку ContentTypes, но пока не знаю, как его можно применить здесь. Я постараюсь найти больше информации. - person Edmond; 28.02.2020
comment
Я обновил свой ответ, добавив дополнительную информацию о поиске ContentType. - person nthall; 28.02.2020
comment
Спасибо. это хороший ответ. Мой последний вопрос: было бы более эффективно использовать отдельную физическую модель вместо ContentTypes? Учтите, что у меня будет 60 различных типов объектов (Фильм, Мультфильм, Концерт, Роман и т. д.). Наличие отдельной физической модели означало бы использование множества объединений. С другой стороны, на данный момент он уже кажется мне более интуитивным и дружелюбным (в отличие от того, что я думал изначально). - person Edmond; 28.02.2020
comment
Стандартный совет, как правило, заключается в том, чтобы не беспокоиться о производительности до тех пор, пока в этом нет необходимости, а если у вас еще нет рабочего продукта или пользователей, то вам и не нужно. Без более подробного понимания это единственный совет, который я могу дать. 60 на самом деле не так много типов; с разумным индексированием, кэшированием и т. д. Я не думаю, что производительность будет большой проблемой, но только вы можете знать, что лучше в этом отношении. - person nthall; 28.02.2020

вы можете сначала найти индекс, используя метод index(), а затем получить элемент с помощью all_items[given_index].delete()

person NaSir HuSSaiN    schedule 28.02.2020