Я разрабатываю программу обучения словарного запаса с Джанго (немецкий-шведский).
Словарные данные приложения состоят из большого количества "словарных карточек", каждая из которых содержит одно или несколько немецких слов или терминов, соответствующих одному или нескольким шведским терминам.
Обучение доступно только для зарегистрированных пользователей, поскольку приложение отслеживает производительность пользователя, сохраняя score
для каждой словарной карты.
Словарные карточки имеют уровень (базовый, продвинутый, экспертный) и любое количество тегов, присвоенных им.
Когда зарегистрированный пользователь начинает обучение, приложение должно рассчитать средние оценки пользователя для каждого из уровней и тегов, чтобы он мог сделать свой выбор.
Я решил эту проблему, введя модель с именем CardByUser
, которая имеет score
и поле и ForeignKey
отношения с моделями User
и Card
. Теперь я могу использовать функцию агрегирования Джанго для вычисления средних баллов.
Большой недостаток: это работает, только если есть экземпляр CardByUser
для каждого экземпляра Карты, который в настоящее время существует в БД, даже если пользователь обучил только 100 карт. Мое текущее решение заключается в создании всех этих CardByUser
экземпляров при создании Card
и при регистрации пользователя. Это, конечно, довольно неэффективно как с точки зрения памяти базы данных, так и с точки зрения вычислительного времени (регистрация пользователя занимает довольно много времени).
И это выглядит довольно не элегантно, что меня больше всего беспокоит.
Есть ли лучший способ сделать это?
Возможно, можно подсказать Джанго следующее при расчете среднего балла для Card
:
- Если
CardByUser
для данного Card
и пользователя существует, используйте его счет.
- Если
CardByUser
не существует, используйте значение по умолчанию -> оценка 0.
Можно ли это сделать? Если да, то как?
Редактировать: Уточнение
Спасибо S.Lott's за первый ответ, но я думаю, что моя проблема немного сложнее. Плохо, я пытаюсь уточнить, используя какой-то реальный код из моих моделей.
class Card(models.Model):
entry_sv = models.CharField(max_length=200)
entry_de = models.CharField(max_length=200)
... more fields ...
class CardByUser(models.Model):
user = models.ForeignKey(User)
card = models.ForeignKey(Card, related_name="user_cards")
score = models.IntegerField(default=0)
... more fields ...
Это означает, что многие CardByUser
объекты связаны с одним Card
.
Теперь в моем коде представления мне нужно создать набор запросов из CardByUser
объектов, которые удовлетворяют следующим критериям:
- поле
tag
связанного Card
объекта содержит определенную строку (я сейчас тоже не оптимален, но не в фокусе моего вопроса ...)
- пользователь является текущим пользователем
Тогда я могу агрегировать по баллам. Мой текущий код выглядит так (сокращенно):
user_cards = CardByUser.objects.filter(user=current_user)
.filter(card__tags__contains=tag.name)
avg = user_cards_agg.aggregate(Avg('score'))['score__avg']
Если CardByUser
для текущего пользователя и Card
не существует, оно просто не будет включено в агрегацию. Вот почему я создаю все эти CardByUser
с счетом 0.
Так, как я мог избавиться от них? Любые идеи будут оценены!