Django throwing ValueError: too many values to unpack (expected 2) with no change to the code

Viewed 75

I have written a new function in a subfolder and my django project that was running fine is now throwing the following error:

 File "C:\Users\me\PycharmProjects\IndicatorAnalyserWebapp\Analyser\Indicators\urls.py", line 4, in <module>
    from .views import (
  File "C:\Users\me\PycharmProjects\IndicatorAnalyserWebapp\Analyser\Indicators\views.py", line 15, in <module>
    from .forms import IndicatorForm, SearchForIndicatorMetaData
  File "C:\Users\me\PycharmProjects\IndicatorAnalyserWebapp\Analyser\Indicators\forms.py", line 24, in <module>
    class IndicatorForm(forms.ModelForm):
  File "C:\Users\me\AppData\Local\Continuum\anaconda37\envs\py34\lib\site-packages\django\forms\models.py", line 252, in __new__
    opts.field_classes)
  File "C:\Users\me\AppData\Local\Continuum\anaconda37\envs\py34\lib\site-packages\django\forms\models.py", line 166, in fields_for_model
    formfield = f.formfield(**kwargs)
  File "C:\Users\me\AppData\Local\Continuum\anaconda37\envs\py34\lib\site-packages\django\db\models\fields\__init__.py", line 1873, in formfield
    return super(IntegerField, self).formfield(**defaults)
  File "C:\Users\me\AppData\Local\Continuum\anaconda37\envs\py34\lib\site-packages\django\db\models\fields\__init__.py", line 872, in formfield
    defaults['choices'] = self.get_choices(include_blank=include_blank)
  File "C:\Users\me\AppData\Local\Continuum\anaconda37\envs\py34\lib\site-packages\django\db\models\fields\__init__.py", line 802, in get_choices
    for choice, __ in choices:
ValueError: too many values to unpack (expected 2)

Similar questions have been asked in the past and it has always been that someone has used a dictionary rather than an iterable to define choices. I have not done this, but I am getting the same error. The traceback seems to think the issue is somewhere in my forms.py. My forms.py is below:

from django import forms
from .models import Indicator


def get_indicator_ids():
    ids = []
    indicator_objects = Indicator.objects.all()
    for indicator in indicator_objects:
        ids.append(indicator.id)
    return ids


class IndicatorDropDown(forms.Form):
    def __init__(self, *args, **kwargs):
        super(IndicatorDropDown, self).__init__(*args, **kwargs)
        self.fields['indicators'] = forms.ChoiceField(choices=get_indicator_ids())


class IndicatorForm(forms.ModelForm):

    class Meta:
        model = Indicator
        fields = '__all__'
        exclude = ['creator']


class SearchForIndicatorMetaData(forms.Form):
    search_for_indicator_metadata = forms.IntegerField(label='Search for metadata by ID', max_value=999999999)

forms.py calls the model Indicator, however this has not changed from the last commit where it was working. All of my choice fields are tuples, and so should not throw this error. Any advice would be appreciated.

Edit - adding the model as well

class Indicator(models.Model):
    time_periods = (
        get_time_periods()
    )

    months = (
        get_months()
    )

    calculations = (
        get_calculations()
    )

    sex_ids = (
        get_all_sexes()
    )

    age_ids = (
        get_all_ages()
    )

    operands = (
       ('+', '+'),
       ('-', '-'),
       ('*', '*'),
       ('/', '/')
    )

    salt_options = get_salt_options_as_tuple()

    qof_data_choices = (
        ('qof-{}-prev-ach-exc-ms-prac.xlsx', 'Musculoskeletal group'),
        ('qof-{}-prev-ach-exc-neu-prac.xlsx', 'Mental health and neurology group'),
        ('qof-{}-prev-ach-exc-fer-obs-gyn-prac.xlsx', 'Fertility, obstetrics and gynaecology group'),
        ('qof-{}-prev-ach-exc-hd-prac.xlsx', 'High dependency and other long term conditions group'),
        ('qof-{}-prev-ach-exc-ls-prac.xlsx', 'Lifestyle group'),
        ('qof-{}-prev-ach-exc-resp-prac.xlsx', 'Respiratory group'),
        ('qof-{}-prev-ach-exc-cv-prac.xlsx', 'Cardiovascular group'),
        ('qof-{}-prac-dom-ach.xlsx', 'Achievement group'),
        ('qof-{}-prac-dom-exc.xlsx', 'Exclusion group'),
    )

    id = models.IntegerField(unique=True, primary_key=True)
    source_data_family = models.ForeignKey(IndicatorFamily, on_delete=models.CASCADE, blank=True)
    qof_source_data = models.CharField(max_length=100, choices=qof_data_choices, blank=True)
    source_sheet = models.CharField(max_length=200, blank=True)
    year_range = models.CharField(max_length=2, blank=True)
    time_period = models.CharField(max_length=30, choices=time_periods, blank=True)
    ageId = models.IntegerField(choices=age_ids, blank=True)
    sexId = models.IntegerField(choices=sex_ids)
    calculation = models.CharField(max_length=30, choices=calculations, blank=True)
    rate = models.IntegerField(blank=True, null=True)
    value_declared_independently = models.BooleanField(default=False)
    value_column_name = models.CharField(max_length=200, blank=True)
    numerator_starts_with_financial_year = models.BooleanField(default=False)
    numerator = models.CharField(max_length=200, blank=True)
    salt_numerator = models.CharField(max_length=200, blank=True, choices=salt_options)
    salt_numerator_operand = models.CharField(max_length=2, choices=operands, blank=True)
    salt_numerator_2 = models.CharField(max_length=200, blank=True, choices=salt_options)
    numerator_minus_not_caseness = models.BooleanField(default=False)
    iapt_q_m_variable_type = models.CharField(max_length=200, blank=True)
    iapt_q_m_variable_a = models.CharField(max_length=200, blank=True)
    iapt_q_m_variable_b = models.CharField(max_length=200, blank=True)
    iapt_q_m_variable_type_denominator = models.CharField(max_length=200, blank=True)
    iapt_q_m_variable_a_denominator = models.CharField(max_length=200, blank=True)
    iapt_q_m_variable_b_denominator = models.CharField(max_length=200, blank=True)
    denominator_starts_with_financial_year = models.BooleanField(default=False)
    denominator = models.CharField(max_length=200, blank=True)
    denominator_minus_not_caseness = models.BooleanField(default=False)
    denominator_source_sheet = models.CharField(max_length=200, blank=True)
    salt_denominator = models.CharField(max_length=200, blank=True, choices=salt_options)
    salt_denominator_operand = models.CharField(max_length=2, choices=operands, blank=True)
    salt_denominator_2 = models.CharField(max_length=200, blank=True, choices=salt_options)
    add_denominator_column = models.CharField(max_length=200, blank=True)
    additional_denominator_column_starts_with_financial_year = models.BooleanField(default=False)
    adjust_denominator_for_person_years = models.BooleanField(default=False)
    ccg_over_18_population_as_denominator = models.BooleanField(default=False)
    ccg_total_population_as_denominator = models.BooleanField(default=False)
    is_count = models.BooleanField(default=False)
    is_percentage = models.BooleanField(default=False)
    ccg_to_stp = models.BooleanField(default=False)
    gp_to_upper_tier_la = models.BooleanField(default=False)
    ccg_lookup_required = models.BooleanField(default=False)
    drop_depression = models.BooleanField(default=False)
    count_non_nulls = models.BooleanField(default=False)
    non_null_columns = models.CharField(max_length=300, blank=True)
    drop_eng_row = models.BooleanField(default=False)
    months_to_quarter = models.BooleanField(default=False)
    snapshot = models.BooleanField(default=False)
    asterisk_as_two = models.BooleanField(default=False)
    creator = models.ForeignKey(settings.AUTH_USER_MODEL, default=1)
    denominator_2_equals_denominator = models.BooleanField(default=False)
    do_not_suppress_small_numbers = models.BooleanField(default=False)
    numerator_is_num_minus_denom = models.BooleanField(default=False)
    stp_is_average_not_sum = models.BooleanField(default=False)
    mental_health_trust_geographies = models.BooleanField(default=False)
    filter_by = models.CharField(max_length=200, blank=True)
#    ld_denominator_source_file = models.CharField(max_length=100, choices=qof_data_choices, blank=True)

    def __str__(self):
        return str(self.id)

Edit 2 - updated traceback:

  File "C:\Users\me\PycharmProjects\IndicatorAnalyserWebapp\Analyser\Indicators\urls.py", line 4, in <module>
    from .views import (
  File "C:\Users\me\PycharmProjects\IndicatorAnalyserWebapp\Analyser\Indicators\views.py", line 15, in <module>
    from .forms import IndicatorForm, SearchForIndicatorMetaData
  File "C:\Users\me\PycharmProjects\IndicatorAnalyserWebapp\Analyser\Indicators\forms.py", line 19, in <module>
    class IndicatorForm(forms.ModelForm):
  File "C:\Users\me\AppData\Local\Continuum\anaconda37\envs\py34\lib\site-packages\django\forms\models.py", line 252, in __new__
    opts.field_classes)
  File "C:\Users\me\AppData\Local\Continuum\anaconda37\envs\py34\lib\site-packages\django\forms\models.py", line 166, in fields_for_model
    formfield = f.formfield(**kwargs)
  File "C:\Users\me\AppData\Local\Continuum\anaconda37\envs\py34\lib\site-packages\django\db\models\fields\__init__.py", line 1873, in formfield
    return super(IntegerField, self).formfield(**defaults)
  File "C:\Users\me\AppData\Local\Continuum\anaconda37\envs\py34\lib\site-packages\django\db\models\fields\__init__.py", line 872, in formfield
    defaults['choices'] = self.get_choices(include_blank=include_blank)
  File "C:\Users\me\AppData\Local\Continuum\anaconda37\envs\py34\lib\site-packages\django\db\models\fields\__init__.py", line 802, in get_choices
    for choice, __ in choices:
ValueError: too many values to unpack (expected 2)

Edit 3 - Added examples of functions being called from model

def get_months():
    months = (
        ('jan', 'January'),
        ('feb', 'February'),
        ('mar', 'March'),
        ('apr', 'April'),
        ('may', 'May'),
        ('jun', 'June'),
        ('jul', 'July'),
        ('aug', 'August'),
        ('sep', 'September'),
        ('oct', 'October'),
        ('nov', 'November'),
        ('dec', 'December')
    )
    return months


def get_time_periods():
    time_periods = (
        ('monthly', 'Monthly'),
        ('quarterly', 'Quarterly'),
        ('annual', 'Annual')
    )
    return time_periods


def get_calculations():
    calcs = (
        ('WILSON', 'Wilson'),
        ('BYAR', 'Byar')
    )
    return calcs
2 Answers

All of my choice fields are tuples, and so should not throw this error.

It throws an error, because you here added a field to your form with:

... = forms.ChoiceField(choices=get_indicator_ids())

and the get_indicator_ids() indeed does not return a list of 2-tuples. It simply is a flat list of integers.

You can change the implementation of get_indicator_ids, but in fact here you want to make it possible to select Indicator objects if I understand it correctly. Then it is bitter to use a ModelChoiceField [Django-doc], like:

class IndicatorDropDown(forms.Form):

    indicators = forms.ModelChoiceField(queryset=Indicator.objects.all())

choices should be in this format:

[
    (value_1, label_1),
    (value_2, label_2),
    ...
]

You'll need to modify your code to append items to the list in 2-tuple format:

ids.append((indicator.id, indicator.id))

Above, indicator.id is also the label for the choice. Label is what django displays to the user when selecting a choice. You should probably provide the name of the object instead of plain id.


Note: The other answer by Willem is a better solution for your case.

Related