django - 如何在没有重复字段的情况下注释字段 django
问题描述
所以我基本上有这个简单的模型:
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()
与shows_users中的User模型存在多对多关系
我想根据多对多表注释 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 个课程,这意味着我要获取所有 50000 个字段然后过滤其中的 50 个 :(
有没有更清洁的方法来做到这一点?
2.区别:
我之前尝试过 distinct 并没有解决问题,而不是显示三遍课程,它将显示:
- 一次(is_shown = True),
- 还有一次(is_shown = False)
解决方案
我设法解决了这个问题,如果发现我的多对多查询方式是问题所在,而不是shown_users__id == user.id
我使用id__in==user.lessons.values('id')
的完整代码:
class BaseLessonManager(InheritanceManager, CachingManager):
def with_is_shown(self, user):
user_shown_lessons = user.lessons.values('id')
shown_user_case = django_models.Case(
django_models.When(id__in=user_shown_lessons,
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)
推荐阅读
- javascript - 为什么在监视模式下运行时 Terser 最小化器不会删除空格和换行符?
- enums - 在传递带有向量的文件时,如何在测试台中使用枚举?
- ios - 无法归档 SwiftUI 项目,入口点 (_main) 未定义。用于架构 arm64
- css - 盒子应该是垂直薄的,没有足够的内容,但是当内容太多时会有滚动条
- nginx - 为什么我的 nginx 即服务在 windows server 2016 中不起作用
- r - 如何使用 R 中的 fixst 删除一个固定效果?
- javascript - 从子元素设置父样式
- javascript - 在 Slate.js 编辑器中启用自动链接
- javascript - 为什么 useCallback 是同一个实例
- rest - 从 Snapchat 自定义镜头调用 rest API