[Django]-Django sequence:item 4 expected string or unicode int found

7👍

✅

Short answer: make from max_length an explicitly named argument.

Based on the source code, max_length is not an explicit parameter of CharField, it thus performs a call to the __init__ of Field, and this has as arguments:

def __init__(self, verbose_name=None, name=None, primary_key=False,
             max_length=None, unique=False, blank=False, null=False,
             db_index=False, rel=None, default=NOT_PROVIDED, editable=True,
             serialize=True, unique_for_date=None, unique_for_month=None,
             unique_for_year=None, choices=None, help_text='', db_column=None,
             db_tablespace=None, auto_created=False, validators=(),
             error_messages=None):

So as you can see, your first unnamed parameter, actually will match with verbose_name, and this should be a string. Of course providing the number as a string will not solve the problem since then you pass the max_length to the verbose_name, instead, and furthermore max_length is, as far as I know a required parameter for CharField.

The solution is to explicitly use max_length such that it is clear that you want to assign 4 to that parameter. The same holds for the DecimalField by the way:

class Publisher(models.Model):
    publisherCode = models.CharField(max_length=3,primary_key=True)
    publisherName = models.CharField(max_length=25)
    city = models.CharField(max_length=20)

class Book(models.Model):
    bookCode = models.CharField(max_length=4,primary_key=True)
    title = models.CharField(max_length=40)
    publisherCode = models.ForeignKey(Publisher)
    type = models.CharField(max_length=3)
    paperback = models.CharField(max_length=1)

class Branch(models.Model):
    branchNum = models.DecimalField(max_digits=2, decimal_places=0, primary_key=True)
    branchName = models.CharField(max_length=50)
    branchLocation = models.CharField(max_length=50)

class Copy(models.Model):
    bookCode = models.ForeignKey(Book)
    branchNum = models.ForeignKey(Branch)
    copyNum = models.DecimalField(max_digits=2, decimal_places=0, primary_key=True)
    quality = models.CharField(max_length=20)
    price = models.DecimalField(max_digits=8, decimal_places=2)

This is more “self-explaining” as well: a user with not much Django experience, can usually guess that max_length=3 means that the string can contain at most three characters, whereas without explicit naming, he/she should have to look up what exactly this parameter means.

I find it rather weird that you use a DecimalField with decimal_places=0, since this is basically an IntegerField, usually it is better to use an IntegerField in that case since it maps more directly to what it is conceptually, the database can store it in a more compact way, and arithmetic operations are usually correct in integer land, whereas in floating point land, there can be rounding errors.

Leave a comment