Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ValueError: Cannot serialize function: lambda while using makemigrations

When I do python manage.py makemigrations, i get above error and I am unsure where the error is happening. I saw some post regarding this issue but i find mainly in DateTimeField() where the function was passed but in my case I have used auto_now attribute instead of some datetime related function.

However, I have used lambda function in the class method as follow.

@classmethod
    def get_content_models(cls):
        """
        Return all Package subclasses.
        """
        is_content_model = lambda m: m is not Package and issubclass(m, Package)


def set_helpers(self, context):
    current_package_id = getattr(current_package, "id", None)
    current_parent_id = getattr(current_package, "parent_id", None)
    self.is_current_child = self.parent_id == current_package_id
    self.is_child = self.is_current_child

    def is_c_or_a(package_id):
        parent_id = context.get("_parent_package_ids", {}).get(package_id)
        return self.id == package_id or (parent_id and is_c_or_a(parent_id))
    self.is_current_or_ascendant = lambda: bool(is_c_or_a(current_package_id))

I am not clear on this issue, So i have posted for understanding the cause. Is above code creating that issue? If it is the cause, what should be done instead?

I don't know where exactly this issue lies in the models so here is the detail of models.py of package app in gist because the code is a bit huge . It is not reached to booking models so I am only putting the code of package app and here it is

https://gist.github.com/SanskarSans/51d2f287309a97163e680cc38abd3e06

UPDATE

In my Package models, I have used the custom field and in that field there was the use of lambda instead of callable function and that was creating an issue. Due to the long file of models, I did not paste it here, I apologize for that.

Here what I had done

in_menus = MenusField(_("Show in menus"), blank=True, null=True)

class MenusField(MultiChoiceField):
    """
    ``MultiChoiceField`` for specifying which menus a package should
    appear in.
    """

    def __init__(self, *args, **kwargs):
        choices = [t[:2] for t in getattr(settings, "PAGE_MENU_TEMPLATES", [])]
        default = getattr(settings, "PAGE_MENU_TEMPLATES_DEFAULT", None)
        if default is None:
            default = [t[0] for t in choices]
        elif not default:
            default = None
        if isinstance(default, (tuple, list)):
            d = tuple(default)
            # this lambda should be avoided
            # default = lambda:d 
            default = default_value(d)
        defaults = {"max_length": 100, "choices": choices, "default": default}
        defaults.update(kwargs)
        super(MenusField, self).__init__(*args, **defaults)
like image 649
Serenity Avatar asked Apr 04 '18 04:04

Serenity


1 Answers

An example replacing the lambda with a function.

Borken version:

class SomeModel(ParentModel):
    thing_to_export = ArrayField(models.CharField(max_length=50), 
                                 default=lambda: ['Default thing'])

Working version:

def default_thing():
    return ['THIS IS A DEFAULT']

class SomeModel(ParentModel):
    thing_to_export = ArrayField(models.CharField(max_length=50), 
                                 default=default_thing)
like image 99
jmunsch Avatar answered Sep 21 '22 13:09

jmunsch