У меня есть набор профилей:
Модель:
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, unique=True)
...
Вид:
Profile.objects.select_related('user')
Каждый пользователь/профиль может регистрироваться на несколько событий в день:
Модели:
class Event(models.Model):
title = models.CharField(max_length=120)
date = models.DateField(default=default_event_date)
...
class Registration(models.Model):
event = models.ForeignKey(Event)
student = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
block = models.ForeignKey(Block, on_delete=models.CASCADE)
....
Учитывая дату, как я могу аннотировать (? Я думаю, это то, что я хочу?) Один объект регистрации на блок (отфильтрованный по пользователю/профилю и Event__Date)
В конце концов, то, что я пытаюсь вывести в своем шаблоне, выглядит примерно так:
For Date: 19 Dec 2016
User/Profile Block A Block B ...
user1 None None
user2 Event1 Event2
user3 Event3 None
...
ИЗМЕНИТЬ
Попытка 1. Вот моя первая попытка сделать это. Я подозреваю, что это ужасно неэффективно и будет очень медленным в производстве, но, по крайней мере, это работает. Если кто-то может предоставить более эффективное и элегантное решение, мы будем признательны! (Обратите внимание, что это также включает фильтр модели профиля пользователя для homeroom_teacher, который не был включен в исходный вопрос, но я оставил здесь, потому что это рабочий код)
Менеджер модели регистрации
класс RegistrationManager(models.Manager):
def homeroom_registration_check(self, event_date, homeroom_teacher):
students = User.objects.all().filter(is_staff=False, profile__homeroom_teacher=homeroom_teacher)
students = students.values('id', 'username', 'first_name', 'last_name')
# convert to list of dicts so I can add 'annotate' dict elements
students = list(students)
# get queryset with events? optimization for less hits on db
registrations_qs = self.get_queryset().filter(event__date=event_date, student__profile__homeroom_teacher=homeroom_teacher)
# append each students' dict with registration data
for student in students:
user_regs_qs = registrations_qs.filter(student_id=student['id'])
for block in Block.objects.all():
# add a new key:value for each block
try:
reg = user_regs_qs.get(block=block)
student[block.constant_string()] = str(reg.event)
except ObjectDoesNotExist:
student[block.constant_string()] = None
return students
Шаблон Обратите внимание, что block.constant_string() --> "ABLOCK", "BBLOCK" и т. д., это жестко закодировано в методе block.constant_string(), и я не уверен, как обойти это либо.
{% for student in students %}
<tr >
<td>{{ student.username }}</td>
<td>{{ student.first_name }}</td>
<td>{{ student.last_name }}</td>
<td>{{ student.ABLOCK|default_if_none:'-' }}</td>
<td>{{ student.BBLOCK|default_if_none:'-' }}</td>
</tr>
{% endfor %}