Таким образом, у меня в основном есть эта простая модель:
class BaseLesson(models.Model):
YOUTUBE_VIDEO = '0'
MARKDOWN = '1'
TYPE_CHOICES = (
(YOUTUBE_VIDEO, 'youtube-video'),
(MARKDOWN, 'markdown'),
)
type = models.CharField(
max_length=10, choices=TYPE_CHOICES, default=MARKDOWN, verbose_name=_('type'))
shown_users = models.ManyToManyField(
User, related_name='lessons', verbose_name=_('shown users'), blank=True)
objects = managers.BaseLessonManager()
Существует много-много отношений с моделью User в selected_users
И я хочу аннотировать статус is_shown на основетаблица «многие ко многим», поэтому я сделал это:
class BaseLessonManager(InheritanceManager, CachingManager):
def get_lesson_with_is_shown(self, user):
shown_user_case = django_models.Case(
django_models.When(shown_users__id=user.id,
then=django_models.Value(True)),
default=django_models.Value(False),
output_field=django_models.BooleanField())
return self.get_queryset().annotate(
is_shown=shown_user_case)
Проблема в том, что если user1 и user2 видели один и тот же урок, он будет повторяться, например:
+-----------------+-----------+
| lesson_id | user_id |
+-----------------+-----------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
+-----------------+-----------+
В таком случае я получу следующие повторяющиеся уроки:
{
"id": 1
"type": "0",
"is_shown": true
},
{
"id": 1
"type": "0",
"is_shown": false
},
{
"id": 1
"type": "0",
"is_shown": false
}
Итак, он проверяет каждое связанное поле урока в таблице SHOWN_USERS ... пример фотографии: https://imgur.com/GJCPWjk
Что я пробовал до сих пор:
1.Исключить:
Я добавил выражение исключения, чтобы избавиться от лишних уроков:
return self.get_queryset().annotate(
is_shown=shown_user_case).exclude(
django_models.Q(is_shown=False) & django_models.Q(shown_users__id=user.id))
И я думаю, что это очень уродливо, потому что у меня 1000 пользователей и 50 уроков, это означает, что я 'm, взяв все 50000 полей, затем отфильтруйте 50 из них: (*
Есть ли какой-нибудь более чистый способ сделать это?
2. Отличительный:
Я пробовал разные ранее, и этоне решая проблему, вместо того, чтобы показать урок три раза, он покажет:
- один раз (is_shown = True),
- и другой раз (is_shown = False)
Вот репозиторий github, если вы хотите поэкспериментировать: https://github.com/coretabs-academy/website-v2