title: How do I construct a Django form that has a ModelChoiceField?
body: <p>I'm trying to write a test for my form which uses a custom ModelChoiceField:</p>
  
  <pre><code>from django.forms import ModelChoiceField
  class CycleModelChoiceField(ModelChoiceField):
      def label_from_instance(self, cycle):
          return str(cycle.begin_date)
  </code></pre>
  
  <p>Whatever the user selects in this field needs to be passed into 2 other fields (DateField and radio ChoiceField) by overriding the <code>clean()</code> method. That's complicated logic that I need to test.</p>
  
  <p>So here's what I've tried in my test so far:</p>
  
  <pre><code>self.client.login(username='user', password='1234')
  response = self.client.get(reverse('my_form'), follow=True)
  cyc = list(CycleDate.objects.all())[0]
  form_data = {'type_of_input': '0', 'cycle': cyc,'usage_type': 'E',}
  form = EnergyUsageForm(data=form_data, user=response.context['user'])
  </code></pre>
  
  <p>But the <code>form.is_valid()</code> returns false and <code>form.errors</code> says:</p>
  
  <pre><code>{'cycle': [u'Select a valid choice. That choice is not one of the available choices.']}
  </code></pre>
  
  <p>There must be something wrong with my form construction. <code>'cycle': cyc</code> clearly isn't working as intended. I've also tried <code>'cycle': '0'</code> and <code>'cycle': '1'</code>.</p>
  
  <p>What is the correct way to construct a form like this?</p>
  
  <p><strong>EDIT:</strong>
  I should explain what the available choices are. There's only one CycleDate in the database and only one choice. After running the lines of my test in the shell, I typed <code>form.fields['cycle'].choices.choice(cyc)</code> which returns <code>(1, '2015-05-01')</code>. The strange thing is that <code>form.fields['cycle'].queryset</code> returns <code>[]</code>. Maybe the issue is related to that?</p>
  
  <p><strong>EDIT2:</strong>
  Here's my form with that complicated (read: messy and terrible and shameful) clean method:</p>
  
  <pre><code>class EnergyUsageForm(forms.Form):
      # Override init so that we can pass the user as a parameter.
      # Then put the cycle form inside init so that it can access the current user variable
      def __init__(self, *args, **kwargs):
          user = kwargs.pop('user', None)
          super(EnergyUsageForm, self).__init__(*args, **kwargs)
  
          # Get the last 12 cycle dates for the current user
          td = datetime.date.today
          cycle_dates = CycleDate.objects.filter(cycle_ref=Account.objects.get(holder__user=user).cycle,
                                                 begin_date__lte=td).order_by('begin_date')
          self.fields['cycle'] = CycleModelChoiceField(queryset = cycle_dates,
                                                        required = False,
                                                        widget = forms.Select(attrs={"onChange":'changeCalendar()'}),
                                                        label = "Choose a billing cycle")
  
  
      type_of_input = forms.ChoiceField(required=False,
                                      widget=forms.Select(attrs={"onChange": "switchInput()"}),
                                      choices=INPUT,
                                      initial='0',
                                      label="Choose a way to display usage", )
  
      end_date = forms.DateField(widget=forms.TextInput(attrs=
                                  {
                                      'class':'datepicker'
                                  }), 
                                  label="Choose start date",
                                  help_text='Choose a beginning date for displaying usage',
                                  required=True,
                                  initial=datetime.date.today,)
  
      period = forms.ChoiceField(required=True,
                                  widget=forms.RadioSelect, 
                                  choices=DISPLAY_PERIOD, 
                                  initial='01',
                                  label="Choose period to display",)
  
      usage_type = forms.ChoiceField(required=True,
                                  widget=forms.RadioSelect,
                                  choices=USAGE_TYPE,
                                  initial='E',
                                  label="Choose type of usage to display",)
  
      def clean_end_date(self):
          data = self.cleaned_data['end_date']
  
          if datetime.date.today() &lt; data:
              raise forms.ValidationError("Don't choose a future date")
          # Always return the cleaned data, whether you have changed it or
          # not.
          return data
  
      def clean(self):
          cleaned_data = super(EnergyUsageForm, self).clean()
          selection = cleaned_data['type_of_input']
          # Check if the user wants to use cycle_dates instead
          if selection == '0':
              # Set the end_date and period
              cleaned_data['end_date'] = cleaned_data['cycle'].begin_date #MUST BE CHANGED TO END_DATE LATER
              cleaned_data['period'] = cleaned_data['cycle'].duration
          return cleaned_data
  </code></pre>
  
  <p><strong>EDIT3</strong>
  Fixed a typo in my test, and also here's my test's setUp method:</p>
  
  <pre><code>client = Client()
      def setUp(self):
          user = User.objects.create_user(username = 'user', password = '1234')
          user.save()
          profile = UserProfile.objects.create(user = user)
          profile.save()
          account = Account(number=1, first_name='test',
                            last_name='User',
                            active=True,
                            holder=profile,
                            holder_verification_key=1)
  
          account.save()
  
          the_cycle = Cycle.objects.create(name = 'test cycle')
          the_cycle.save()
          cd = CycleDate.objects.create(begin_date = datetime.date(2015, 5, 1),
                                   end_date = datetime.date.today(),
                                   cycle_ref = the_cycle)
          cd.save()
  </code></pre>
  
  <p><strong>EDIT4:</strong>
  In addition to all this mess, I'm now getting <code>KeyError: 'cycle'</code> whenever I call <code>form.is_valid()</code>. Probably due to the clean() method trying to access cleaned_data['cycle'] when the cycle field has an invalid selection.</p>