Opened 5 years ago

Closed 4 years ago

#30095 closed Bug (fixed)

System check error for tuples or lists in model field choices.

Reported by: Pedro Marcondes Owned by: Hasan Ramezani
Component: Database layer (models, ORM) Version: dev
Severity: Normal Keywords: choices tuple
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Since version 2.1 django stopped to accept tuples as value in choices.

I'll give you an example using the User model so you can reproduce. The error occurs when I do manage.py runserver.

I tried to find in the release notes from django 2.1.* versions but couldn't find something adressing this change. This model works with django version 2.0.10 and below.

from __future__ import unicode_literals
from django.db import models
from django.contrib.postgres.fields import IntegerRangeField


class Article(models.Model):

    LTE_50 = (1, 50)
    LTE_100 = (51, 100)

    SIZE_CHOICES = (
        (LTE_50, "1-50"),
        (LTE_100, "51-100"),
    )
  
    article_size = IntegerRangeField(choices=SIZE_CHOICES)
   """
   django.core.management.base.SystemCheckError: SystemCheckError: System check identified some issues:

   ERRORS:
   article.Article.article_size: (fields.E005) 'choices' must be an iterable containing (actual value, human readable name) tuples.
   """

    published = models.BooleanField("Is published", default=False)

    class Meta:
        verbose_name = "Article"
        verbose_name_plural = "Articles"

    def __str__(self):
        return "test"

Attachments (1)

regression_30095.py (492 bytes ) - added by Carlton Gibson 5 years ago.
Test cased used for bisecting change. (Saved in postgres_tests

Download all attachments as: .zip

Change History (18)

comment:1 by Tim Graham, 5 years ago

Component: UncategorizedDatabase layer (models, ORM)
Summary: Choices do not accept tuples is actual valueSystem check error for tuples in model field choices

I think you could solve your issue and improve your code by using NumericRange in your choices instead of tuples. Now there may be other custom fields that want to use tuples for choice values, but perhaps we should address that if/when someone presents a use case.

in reply to:  1 comment:2 by Pedro Marcondes, 5 years ago

Replying to Tim Graham:

I think you could solve your issue and improve your code by using NumericRange in your choices instead of tuples. Now there may be other custom fields that want to use tuples for choice values, but perhaps we should address that if/when someone presents a use case.

We tried to use 'NumericRange' but we got an error in serialization when trying to migrate. With further investigation we found that choices wasn't working(1.11.15~) with tuples even though it seemed to accept it as an option. Maybe django should support NumericRange serialization by default? Otherwise it's not possible to use the choices parameter out of the box.

comment:3 by Carlton Gibson, 5 years ago

Bisected to f9844f484186fa13399bf8b96f58616687fe158a: "Fixed #28748 -- Made model field choices check more strict for named groups."

comment:4 by Carlton Gibson, 5 years ago

Severity: NormalRelease blocker
Triage Stage: UnreviewedAccepted

OK, so the underlying issue here is that a tuple is not accepted as valid in the `is_value()` helper used during the checks.

I’m not at all sure that’s a universally valid restriction on choices. (???)

As such I’m inclined to Accept this as a Release Blocker on v2.1. (“Behaviour change from previous version”)

Happy for input to the contrary. (!!!)

comment:5 by Tim Graham, 5 years ago

While it might require a lot of code duplication, a custom field that uses tuples as valid values could override Field._check_choices(). I'm not immediately convinced the issue is severe enough to require a patch for Django 2.1 but we could simply remove the new validation as it's not critical.

For this ticket's use case, NumericRange serialization is added in Django 2.2 (#29738).

If we decide to take no action for Django 2.1, we could leave this ticket open for someone to improve the validation. Actually, #20749 is already open for that.

comment:6 by Carlton Gibson, 5 years ago

Severity: Release blockerNormal

OK, lets downgrade this to Normal: the change in behaviour of the system check isn't quite a change in behaviour of the code itself. (The system check can always be silenced.)

  • Implementing RangeField._check_choices() would be feasible.
  • Maybe raising the is_value() helper to class level would allow avoiding too much duplication.
    • We may need to separate the is_value() logic from the is_human_readable_label() test — currently the is_value() helper is used for both tasks.
  • Maybe a fix to #20749 addresses this too, but they don't seem quite the same. (I could see a fix for this without the more general problem being solved.)

by Carlton Gibson, 5 years ago

Attachment: regression_30095.py added

Test cased used for bisecting change. (Saved in postgres_tests

comment:7 by CHANDAN PRAKASH, 5 years ago

Owner: changed from nobody to CHANDAN PRAKASH
Status: newassigned

comment:8 by CHANDAN PRAKASH, 5 years ago

I am new to this open source.
Help me in this issue.

comment:9 by Carlton Gibson, 5 years ago

Hi Chandan.

First step is to read the contributing guide: https://docs.djangoproject.com/en/dev/internals/contributing/

Then your best bet, I think, is to take the test case I used and add it to the existing postgres test cases (you’ll need to have a look around as to where is best).

You’ll need to run against PostgreSQL to test. See https://docs.djangoproject.com/en/2.0/topics/testing/overview/#the-test-database

Then if you run the test suite you’ll see a failure. The test doesn’t currently pass. The task is to make it pass.

As per the discussion, implementing RangeField._check_choices() to override Field._check_choices() is the likely way forward.

Once you have something, even if not perfect, open a PR on GitHub and we can provide feedback.

Welcome aboard!

comment:10 by Hasan Ramezani, 5 years ago

Has patch: set
Owner: changed from CHANDAN PRAKASH to Hasan Ramezani

comment:11 by Mariusz Felisiak, 4 years ago

Needs tests: set
Patch needs improvement: set
Version: 2.1master

comment:12 by GitHub <noreply@…>, 4 years ago

In a9bd01d3:

Refs #30095 -- Simplified Field._check_choices() a bit.

Using an internal is_value() hook to check whether Field.choices
is iterable is misleading.

comment:13 by Hasan Ramezani, 4 years ago

Needs tests: unset
Patch needs improvement: unset

comment:14 by Mariusz Felisiak, 4 years ago

Patch needs improvement: set
Summary: System check error for tuples in model field choicesSystem check error for tuples or lists in model field choices.

ArrayField with lists in choices are also affected.

comment:15 by Hasan Ramezani, 4 years ago

Patch needs improvement: unset

Fix for ArrayField with lists in choices added.

comment:16 by Mariusz Felisiak <felisiak.mariusz@…>, 4 years ago

In dc60597:

Refs #30095 -- Added Field._choices_is_value().

This allows fields classes to override the validation of choices'
values.

comment:17 by Mariusz Felisiak <felisiak.mariusz@…>, 4 years ago

Resolution: fixed
Status: assignedclosed

In 47379d02:

Fixed #30095 -- Fixed system check for RangeField/ArrayField.choices with lists and tuples.

Note: See TracTickets for help on using tickets.
Back to Top