如何在 Django 中以 ModelMultipleChoiceField 的形式获取不同的月份和年份?

How can I get the distinct month and years in the form ModelMultipleChoiceField in django?

我有两个型号如下:

class Program(Model):
    name = CharField(...)
    teacher = CharField(...)

class ProgramIntake(Model):
    program = ForeignKey(Program, ...)
    intake = DateField(null=True, blank=True, )

我有一些项目的对象,比如数学和艺术 作为程序模型的实例:

math = Program.objects.create(name='math', teacher='teacher1')
art = Program.objects.create(name='art', teacher='teacher2')

每个项目都有几个摄入量:

math_intake1 = PorgramIntake.objects.create(program=math, intake='2019-01-01')
math_intake2 = PorgramIntake.objects.create(program=math, intake='2019-01-15')
math_intake3 = PorgramIntake.objects.create(program=math, intake='2020-01-01')
art_intake1 = PorgramIntake.objects.create(program=art, intake='2019-01-01')
art_intake2 = PorgramIntake.objects.create(program=art, intake='2019-02-18')
art_intake3 = PorgramIntake.objects.create(program=art, intake='2020-05-21')

为了构建我的表单,我构建了这个模型:

class ProgramIntakeEnroll(Model):
    available_intakes = ManyToManyField(ProgramIntake, 
    blank=True, ...)

下面的表格使用 ModelForm:

class ProgramIntakeEnrollForm(ModelForm):
    available_intakes = ModelMultipleChoiceField(queryset=ProgramIntakeEnroll.objects.values_list('intake', flat=True).distinct().order_by('intake'), required=False)

    class Meta:
        model = ProgramIntakeEnroll
        fields = '__all__'

我将此表单呈现如下:

def programs(request):
    template_name = 'programs/programs.html'
    context = {}

    if request.POST:
        program_intake_enroll_form = ProgramIntakeEnrollForm(request.POST)
        if study_intake_form.is_valid():
            pass

    else:
        program_intake_enroll_form = ProgramIntakeEnrollForm()

    context.update({'program_intake_enroll_form': program_intake_enroll_form,})
 return render(request, template_name, context)

在 html 我有:

<form method="post">
{% csrf_token %}
    {{ program_intake_enroll_form.as_p }}
<button type="submit">Filter</button>
</form>

我期望的是我只想在我的表单中看到以下选项:

2019 年 1 月

2019 年 2 月

2020 年 1 月

2020 年 5 月

我想我必须更改我的 ModelForm 中的查询集,但我不知道如何更改它。

我将模型更改如下,现在可以使用了:

class IntakeRound(Model):
    intake_year = PositiveSmallIntegerField(blank=True, null=True)
    intake_month = PositiveSmallIntegerField(blank=True, null=True)

    class Meta:
        unique_together = ('intake_year', 'intake_month',)

    def __str__(self):
        return str(self.intake_year) + '-' + str(self.intake_month)


class Program(Model):
    name = CharField(...)
    intake = ManyToManyField(IntakeRound, through='ProgramIntake', blank=True)


class ProgramIntake(Model):
    program = ForeignKey(Program, on_delete=CASCADE, related_name='program_intakes')
    program_intake_round = ForeignKey(IntakeRound, on_delete=CASCADE, related_name='program_intakes')
    program_start_date = DateField(null=True, blank=True, verbose_name='Program Start Date')
    program_submission_deadline = DateField(null=True, blank=True, verbose_name='Program Submission Deadline')

    class Meta:
        ordering = ('program_start_date',)

    def __str__(self):
        return str(self.program) + '-' + str(self.program_intake_round)

为了能够使用ModelForm,也为了把数据库中可用的程序和同学们的兴趣分开,这里叫Profile,我这里也有这个模型。请注意,我不想填充它。在这个阶段,我刚刚构建了它以从中创建一个 ModelForm:

class ProfileStudyInterest(Model):
    intake_rounds_of_interest = ManyToManyField(IntakeRound, blank=True, verbose_name='Intake Rounds')

这是我的表格:

class ProfileInterestFilterForm(ModelForm):
    intake_rounds_of_interest = ModelMultipleChoiceField(queryset=IntakeRound.objects.all(), required=False)

    class Meta:
        model = ProfileStudyInterest
        fields = '__all__'

但是,令我感到不舒服的是,我的模型中同时有 program_start_date 和 program_intake_round,而同一模式只是 start_date 的月份和年份。我认为从数据库设计的角度来看这是不正确的或最佳实践