【问题标题】:How to make a drop down menu and connect the choice to a CBGV如何制作下拉菜单并将选择连接到 CBGV
【发布时间】:2016-08-11 05:32:11
【问题描述】:

我是 Django 新手,正在努力理解如何在两个模型之间建立用户可访问的连接。

models.py:

class StudyGroup(models.Model):
  start_date = models.DateTimeField()
  end_date = models.DateTimeField()
  ex_1_trial = models.IntegerField(blank=True, null=True, default=None)
  ex_2_trial = models.IntegerField(blank=True, null=True, default=None)
  ...
  def __str__(self):
    return self.studygroup_name

class Patient(models.Model):
  type = models.CharField('Type', max_length=20, db_index=True, help_text='s', primary_key=True)
  patient_name = models.CharField('Name', max_length=200, db_index=True, help_text='n')
  studygroup = models.ForeignKey(StudyGroup, verbose_name='StudyGroup')
  ...
  def __str__(self):
    return self.patient_name

views.py:

class SidebarList(object):
  def get_context_data(self, **kwargs):
    context = super(SidebarList, self).get_context_data(**kwargs)
    context['my_patient_list'] = Patient.objects.order_by('company_name')
    return context

class PatientStatsView(SidebarList, DetailView):
  model = Patient
  template_name = 'screener/patient_stats.html'

  def get_context_data(self, **kwargs):
    context = super(CompanyStatsView, self).get_context_data(**kwargs)
    ... some sorting and stuff here ...
    context['blah'] = some_values
    return context

现在我想创建一个下拉菜单,其中包含可用研究组的列表,并允许用户在与 PatientStatsView 关联的模板中选择一个与特定患者相关联。如果研究组已与患者实例相关联,则需要在下拉菜单中默认选择该研究组。

我不清楚实现这一点以及验证选择并将其保存在患者模型中的最佳方法。

最好在 form.py 中完成吗?

【问题讨论】:

    标签: python django django-templates django-views


    【解决方案1】:

    确实,我认为最好的方法是通过forms.py。特别是,您将更改数据库中的数据。因此,您可能希望将POST 方法与CSRF 一起使用。

    所以你首先需要创建forms.py ModelChoiceField(我觉得最适合你的任务),哪个

    允许选择单个模型对象,适合表示外键。

    并在上面设置queryset参数。

    模型对象的QuerySet,将从中派生出字段的选择,并将用于验证用户的选择。

    例如,您可以这样做:

    # forms.py
    ...
    class PatientForm(forms.Form):
        studygroups = forms.ModelChoiceField(queryset=StudyGroup.objects.all(),
                                             label='Study groups')
        ...
    

    如果页面是通过POSTGET 方法请求的,那么您将检查您的视图。如果用户第一次查看表单 - 通过GET 方法,那么如果用户被分配给一个,则您需要设置用户StudyGroup 的默认值,否则返回None。例如:

    CBV:

    class HomeView(View):
        form_class = PatientForm
        template_name = 'home.html'
    
        def get(self, request, *args, **kwargs):
            initial = {'studygroups': request.user.patient.studygroup.pk}
            form = self.form_class(initial=initial)
            return render(request, self.template_name, {'form': form})
    
        def post(self, request, *args, **kwargs):
            form = self.form_class(request.POST)
            if form.is_valid():
                ...
                return HttpResponseRedirect('/success/')
            return render(request, self.template_name, {'form': form})
    

    CBGV:

    class HomeView(FormView):
        form_class = PatientForm
        template_name = 'home.html'
        success_url = '/success/'
    
        def get_initial(self):
            initial = super(HomeView, self).get_initial()
            initial['studygroups'] = self.request.user.patient.studygroup.pk
            return initial
    
        def form_valid(self, form, *args, **kwargs):
            return super(HomeView, self).form_valid(form)
    

    FBV:

    ...
    if request.method == 'POST':
        form = PatientForm(data=request.POST)
        if form.is_valid():
            ...
            form.save()
    else:
        # some logic which would assign the patient studygroup's pk 
        # to default_group_pk variable.
        # or None if no default group should be selected
        # i.e. user is not logged in or is not assigned to any studygroup.
        # You could get logged in Patient's studygroup via:
        # default_group_pk = request.user.patient.studygroup.pk
        form = PatientForm(initial={'studygroups': default_group_pk})
    ...
    

    然后只需在您的 html 中呈现表单:

    <form action="." method="post">
            {{ form.as_p}}
            {% csrf_token %}
            <p><input type="submit" value="Save"></p>
    </form>
    

    【讨论】:

    • 感谢您的回答。鉴于我正在尝试使用 CBV(用于继承 SideBarList 等),我是否应该重写 form_valid()、get() 和 post() 方法来实现您建议的代码?我不清楚如何做到这一点,但该课程似乎有一些逻辑。
    • 太棒了。我想我开始看到这些联系了。不过,我不明白为什么要使用 form.is_valid() 方法而不是覆盖 form_valid() 方法。这是一个“最佳实践”的问题,还是这些方法的功能不同,以至于我提出的技术不起作用?
    • @PhotonWrangler 我用 CBGV 更新了代码,你使用 form_valid() 方法。确实有很多方法可以做到这一点。你选择哪一个取决于你。有很好的article,您可以在其中阅读更多内容。
    猜你喜欢
    • 2020-08-15
    • 2011-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多