2

我有一个配置文件查询集:

模型:

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 %}
4

2 回答 2

1

为了解决硬编码名称的问题,我会稍微修改您的解决方案,使其看起来像这样:

def homeroom_registration_check(event_date, homeroom_teacher):
    students = User.objects.filter(
        is_staff=False,
        profile__homeroom_teacher=homeroom_teacher,
    )
    block_ids = Block.objects.values('id')
    for student in students:
        table_row = []
        for block_id in block_ids:
            try:
                reg = Registration.objects.get(
                    student=student,
                    block=block_id,
                    event__date=event_date,
                )
                table_row.append(reg.event)
            except ObjectDoesNotExist:
                table_row.append(None)
        yield (student, table_row)

我将从模型管理器中取出它并将其放入views.py或单独的文件(如table.py)中。对我来说似乎更干净,但这只是一种意见——你可以把这段代码放在模型管理器中,它无论如何都会运行。

然后在您的模板中:

{% for student, row in homeroom_reg_check %}
    <tr>
        <td>{{ student.username }}</td>
        <td>{{ student.other_data }}</td>
        {% for event in row %}
            <td>{{ event.name|default_if_none:'-' }}</td>
        {% endfor %}
    </tr>
{% endfor %}
于 2016-12-20T19:45:59.020 回答
1

可能您不需要使用注释,但可以在模板中使用重组标签。

从头到尾。您想在页面上显示的所有信息都可以从注册模型中检索到。

获取按事件日期过滤的所有注册:

registrations = Registration.objects.filter(event__date = date)

之后,您必须在模板中按用户重新组合。

但是我看到以下问题:

  1. 我不确定重组标记是否可以与查询集一起正常工作。因此,您可能必须将数据转换为列表。但是,我找到了使用查询集的这个答案
  2. 即使您将重新组合,您也需要模板中的一些逻辑来定义事件的块。
于 2016-12-20T09:19:18.713 回答