简体   繁体   中英

How to make a drop down menu and connect the choice to a CBGV

I am new to Django and am struggling to understand how to make a user accessible connection between two models.

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

Now I want to make a drop down menu with the list of available studygroups in it and allow the user to select one to associate with a particular patient in the template associated with PatientStatsView. If a studygroup is already associated with a the patient instance, then that studygroup needs to be selected by default in the drop down.

I am unclear about the best ways to achieve this and to have the selection verified and saved in the patient model.

Is this best done in the form.py?

The best way I see it can be done is via the forms.py , indeeed. Especially, that you will be altering the data in your database. You would want to use POST method together with CSRF , because of that.

So you first of all you need to create forms.py with a ModelChoiceField (I find it most suitable for your task), which

Allows the selection of a single model object, suitable for representing a foreign key.

and set queryset parameter on it.

A QuerySet of model objects from which the choices for the field will be derived, and which will be used to validate the user's selection.

You could do it for example like this:

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

Then you would check in your view if the page was requested via POST or GET method. If user views the form for the first time - via GET method, then you would want to set the default value of user's StudyGroup if user is assigned to one, else return None . For example:

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})
...

Then simply render the form in your html:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM