Получение дополнительного поля через аннотацию в отношении "многие ко многим" в Django
У меня есть m2m связь между моделью Feature
и моделью User
через промежуточную таблицу. Модель функций представляет все доступные функции, и пользователь может включить или отключить ноль, одну или несколько из них через web или api. Когда пользователь включает функцию, в промежуточной таблице создается соответствующая запись, когда пользователь отключает функцию, запись удаляется.
from django.contrib.auth.models import User
class Feature(models.Model):
name = models.CharField(max_length=50)
user = models.ManyToManyField(User, through='FeatureUserM2M')
...other fields...
class FeatureUserM2M(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
feature = models.ForeignKey(Feature, on_delete=models.CASCADE)
...other fields...
Предлагаем данные таким образом
Feature User Intermediary
|id|name | |id|name | |id|user_id|feature_id|
+--+------------+ +--+-------+ +--+-------+----------+
|1 |feature foo | |1 |user A | |1 |2 |1 |
|2 |feature bar | |2 |user B | | | | |
|3 |feature baz | | | | | | | |
Мне нужен результат со всеми доступными функциями, а для данного пользователя еще одно поле, указывающее, включена ли у пользователя эта функция или нет (может быть булево значение). В идеале, для "пользователя A" результат должен быть следующим:
|user_id|feature_id|enabled |
+-------+----------+--------+
|2 |1 | true |
|2 |2 | false |
|2 |3 | false |
Я пытался
Feature.objects.annotate(enabled=Subquery(
FeatureUserM2M.objects.filter(
feature=OuterRef('pk'),
user=request.user,
)
))
*** django.core.exceptions.FieldError: Cannot resolve expression type, unknown output_field
Я не думаю, что запрос, который я сделал, правильный, но даже указав тип вывода как BooleanField
я не получаю того, что хочу.
*** TypeError: QuerySet.annotate() received non-expression(s): <class 'django.db.models.fields.BooleanField'>.
Похоже, что вы можете просто использовать подзапрос Exists()
. Пример и описание этого есть в документации здесь:
https://docs.djangoproject.com/en/4.1/ref/models/expressions/#exists-subqueries
Feature.objects.annotate(enabled=Exists(
FeatureUserM2M.objects.filter(
feature=OuterRef('pk'),
user=request.user,
)
))