fix issue "TypeError: 'int' object is not iterable" during update (pre_save), add tests (#100)

This commit is contained in:
Serj S 2019-11-01 09:03:57 +03:00 committed by tomasgarzon
parent 66266dd30b
commit c4579138dd
5 changed files with 41 additions and 8 deletions

View file

@ -6,7 +6,8 @@
"title": "My book 1",
"tags": "sex,work,happy",
"categories": "1,3,5",
"published_in": "BC,AL,AK"
"published_in": "BC,AL,AK",
"chapters": "1"
}
},
{

View file

@ -1,6 +1,4 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9 on 2016-09-22 20:34
from __future__ import unicode_literals
# Generated by Django 2.2.6 on 2019-10-31 08:31
from django.db import migrations, models
import multiselectfield.db.fields
@ -22,6 +20,7 @@ class Migration(migrations.Migration):
('categories', multiselectfield.db.fields.MultiSelectField(choices=[(1, 'Handbooks and manuals by discipline'), (2, 'Business books'), (3, 'Books of literary criticism'), (4, 'Books about literary theory'), (5, 'Books about literature')], default=1, max_length=9)),
('tags', multiselectfield.db.fields.MultiSelectField(blank=True, choices=[('sex', 'Sex'), ('work', 'Work'), ('happy', 'Happy'), ('food', 'Food'), ('field', 'Field'), ('boring', 'Boring'), ('interesting', 'Interesting'), ('huge', 'Huge'), ('nice', 'Nice')], max_length=54, null=True)),
('published_in', multiselectfield.db.fields.MultiSelectField(choices=[('Canada - Provinces', (('AB', 'Alberta'), ('BC', 'British Columbia'))), ('USA - States', (('AK', 'Alaska'), ('AL', 'Alabama'), ('AZ', 'Arizona')))], max_length=2, verbose_name='Province or State')),
('chapters', multiselectfield.db.fields.MultiSelectField(choices=[(1, 'Chapter I'), (2, 'Chapter II')], default=1, max_length=3)),
],
),
]

View file

@ -27,6 +27,13 @@ CATEGORY_CHOICES = (
(5, _('Books about literature')),
)
ONE = 1
TWO = 2
CHAPTER_CHOICES = (
(ONE, 'Chapter I'),
(TWO, 'Chapter II')
)
TAGS_CHOICES = (
('sex', _('Sex')), # noqa: E241
('work', _('Work')), # noqa: E241
@ -67,6 +74,7 @@ class Book(models.Model):
published_in = MultiSelectField(_("Province or State"),
choices=PROVINCES_AND_STATES,
max_choices=2)
chapters = MultiSelectField(choices=CHAPTER_CHOICES, default=ONE)
def __str__(self):
return self.title

View file

@ -23,8 +23,7 @@ from django.test import TestCase
from multiselectfield.utils import get_max_length
from .models import Book, PROVINCES, STATES, PROVINCES_AND_STATES
from .models import Book, PROVINCES, STATES, PROVINCES_AND_STATES, ONE, TWO
if sys.version_info < (3,):
u = unicode # noqa: F821
@ -92,6 +91,27 @@ class MultiSelectTestCase(TestCase):
if form.is_valid():
form.save()
def test_empty_update(self):
book = Book.objects.get(id=1)
self.assertEqual(book.get_chapters_list(), ["Chapter I"])
book.chapters = {}
book.save(update_fields=['chapters'])
self.assertTrue(len(book.chapters) == 0)
def test_single_update(self):
book = Book.objects.get(id=1)
self.assertEqual(book.get_chapters_list(), ["Chapter I"])
book.chapters = {ONE}
book.save(update_fields=['chapters'])
self.assertEqual(book.get_chapters_list(), ["Chapter I"])
def test_multiple_update(self):
book = Book.objects.get(id=1)
self.assertEqual(book.get_chapters_list(), ["Chapter I"])
book.chapters = {ONE, TWO}
book.save(update_fields=['chapters'])
self.assertEqual(book.get_chapters_list(), ["Chapter I", "Chapter II"])
def test_object(self):
book = Book.objects.get(id=1)
self.assertEqual(book.get_tags_display(), 'Sex, Work, Happy')

View file

@ -138,7 +138,7 @@ class MultiSelectField(models.CharField):
return MultiSelectFormField(**defaults)
def get_prep_value(self, value):
return '' if value is None else ",".join(value)
return '' if value is None else ",".join(map(str, value))
def get_db_prep_value(self, value, connection, prepared=False):
if not prepared and not isinstance(value, string_type):
@ -149,7 +149,12 @@ class MultiSelectField(models.CharField):
choices = dict(self.flatchoices)
if value:
return value if isinstance(value, list) else MSFList(choices, value.split(','))
if isinstance(value, list):
return value
elif isinstance(value, string_type):
return MSFList(choices, value.split(','))
elif isinstance(value, (set, dict)):
return MSFList(choices, list(value))
return MSFList(choices, [])
if VERSION < (2, ):