Reputation: 11691
I have a very basic class that looks something like the following:
class Car(Model):
name = CharField(max_length=255, unique=True)
@classmethod
def create_simple_examples(cls):
for c in ['Sedan', 'Coupe', 'Van', 'SUV']:
cls.objects.get_or_create(name=c)
@classmethod
def get_default(cls):
c, _ = cls.objects.get_or_create(name='Sedan')
return c
def __unicode__(self):
return self.name
I am trying to add it to a django app. I have the two class methods to 1. a function to populate the table quickly, and 2. to grab a default one which will be used often.
When I run
python manage.py makemigrations myapp
I get the following error
ValueError: Cannot serialize: <bound method ModelBase.get_default of <class 'crunch.django.myapp.models.Car'>>
I am not quite sure why it's trying to serialize my get_default
function as that's not really part of the migration of the table itself. Any help would be greatly appreciated
UPDATE I think I may have found the source of the problem (still not sure how to fix it though...)
I have other classes that are FKing to my new class, and the default uses my default above...something like this
class OtherClass(Model):
car = ForeignKey(Car, default=Car.get_default)
It looks like the migration is trying to serialize the function because of this. Any tips on how to get around this?
Upvotes: 4
Views: 4239
Reputation: 99620
Add the @deconstructible
decorator to the classes which have a classmethod
from django.utils.deconstruct import deconstructible
@deconstructible
class Car(Model):
...
More documentation on deconstructible
can be found here
Upvotes: 3
Reputation: 58352
As explained in Django's migrations docs, Django can serialize function and method references, (in Python 3) unbound methods used from within the class body, and a bunch of other stuff, but it can't serialize everything.
In this case, because you've made get_default
a @classmethod
, Car.get_default
is a bound method (i.e., it takes an implicit reference to Car
as its first parameter), rather than a plain function or method reference, and Django doesn't know what to do with that.
Try making get_default
a @staticmethod
instead, or make a free function (top-level function) that calls Car.get_default
.
Upvotes: 3