I'm running python manage.py migrate with my models,the database was already made i'm just making the models for it now, but getting this error when running the command
TypeError: Error when calling the metaclass bases
sequence item 4: expected string or Unicode, int found
my models
class Publisher(models.Model):
publisherCode = models.CharField(3,primary_key=True)
publisherName = models.CharField(25)
city = models.CharField(20)
class Book(models.Model):
bookCode = models.CharField(4,primary_key=True)
title = models.CharField(40)
publisherCode = models.ForeignKey(Publisher)
type = models.CharField(3)
paperback = models.CharField(1)
class Branch(models.Model):
branchNum = models.DecimalField(2,0,primary_key=True)
branchName = models.CharField(50)
branchLocation = models.CharField(50)
class Copy(models.Model):
bookCode = models.ForeignKey(Book)
branchNum = models.ForeignKey(Branch)
copyNum = models.DecimalField(2,0,primary_key=True)
quality = models.CharField(20)
price = models.DecimalField(8,2)
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.