Django 3.1 Makemigrations fails with FilePathField but succeeds with CharField

103 views
Skip to first unread message

Olivier

unread,
Mar 18, 2021, 10:28:21 AM3/18/21
to Django users
Hello,

I've got a Django app which has over 200 migration steps.
To shorten its test loading time, I'm trying to erase all current migrations and restart from scratch.

I deteted and re-created my app Postgres database.
I deleted all files (but __init__.py) in migrations directory.
I typed "python manage.py makemigrations --verbosity 3".

1. Latest makemigrations failed with:
  File "/home/perenip/venv-flexcore/lib/python3.7/site-packages/django/db/migrations/serializer.py", line 339, in serializer_factory
    "topics/migrations/#migration-serializing" % (value, get_docs_version())
ValueError: Cannot serialize: PosixPath('/var/www/vhosts/foo/vendorstatic')
There are some values Django cannot serialize into migration files.
For more, see https://docs.djangoproject.com/en/3.1/topics/migrations/#migration-serializing

If I'm not mistaken, I couldn't read any reference to the Model/Field that triggered the error.
Should we expect an explicit mention of the faulty statement/line ?

2. I edited a Model within models.py with:
class Firmware(models.Model):
    #filepath = models.FilePathField(path=settings.VENDOR_STATIC_ROOT, match=settings.FIRMWARE_REGEX, recursive=True)
    filepath = models.CharField(max_length=64)
    display_name = models.CharField(default='foobar', max_length=32, help_text='Value as shown in HTTP User-Agent string')

    def __str__(self):
        return self.relative_path()

    def relative_path(self):
        return str(pathlib.Path(self.filepath).relative_to(settings.VENDOR_STATIC_ROOT))

After changing from a PathFileField to a CharFiled as shown above, I could successfully run makemigrations.

Doc [1] mentions Django can serialize "any Django field". Should it serialize FilePathField ?

3. How to work around this with rewriting my app (and its tests) ?


Best regards

Olivier

unread,
Mar 18, 2021, 11:51:13 AM3/18/21
to Django users
PS: In case the errors comes from the  '/var/www/vhosts/foo/vendorstatic' value itself , may I add that VENDOR_STATIC_ROOT is defined in settings.py, with:

from pathlib import Path
BASE_DIR = Path(__file__).resolve(strict=True).parent.parent
VENDOR_STATIC_ROOT = BASE_DIR / 'vendorstatic'

and that /var/www/vhosts/foo/vendorstatic directory exists.

Python version 3.7.3 and Django 3.1.7.

Olivier

unread,
Mar 18, 2021, 12:01:07 PM3/18/21
to Django users
Converting path from Pathlib to str, allowed makemigrations to pass, at the cost of having a single test to rewrite

class Firmware(models.Model):
    filepath = models.FilePathField(path=str(settings.VENDOR_STATIC_ROOT), match=settings.FIRMWARE_REGEX, recursive=True)

    display_name = models.CharField(default='foobar', max_length=32, help_text='Value as shown in HTTP User-Agent string')

    def __str__(self):
        return self.relative_path()

    def relative_path(self):
        return str(pathlib.Path(self.filepath).relative_to(settings.VENDOR_STATIC_ROOT))


I would be very curious to get a deeper understanding of what is happening here.
Thanks in advance.

Peter of the Norse

unread,
Jun 22, 2021, 11:50:21 PM6/22/21
to django...@googlegroups.com
I think you might be better off using https://docs.djangoproject.com/en/3.2/topics/migrations/#squashing-migrations than having it recreate all of them.  

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/739e8a51-ed79-476c-9945-1076a0491b75n%40googlegroups.com.

David Nugent

unread,
Jun 27, 2021, 10:20:40 PM6/27/21
to django...@googlegroups.com
Hi Peter, I hope I can help.

On Wed, Jun 23, 2021 at 1:50 PM Peter of the Norse <rahm...@gmail.com> wrote:
I think you might be better off using https://docs.djangoproject.com/en/3.2/topics/migrations/#squashing-migrations than having it recreate all of them.  

On Mar 18, 2021, at 8:28 AM, Olivier <oza....@gmail.com> wrote:

Hello,

I've got a Django app which has over 200 migration steps.
To shorten its test loading time, I'm trying to erase all current migrations and restart from scratch.

Yep, pretty reasonably if you have the luxury of re-creating/reloading your db.  If you don't, you can squash your migrations, even if it leaves the original migration files intact until you manually remove them (when it is safe to do so).

Experience suggests that it isn't migrations that accounts for a big share of test startup time - it's the test discovery which takes so long...
 
I deteted and re-created my app Postgres database.
I deleted all files (but __init__.py) in migrations directory.
I typed "python manage.py makemigrations --verbosity 3".

1. Latest makemigrations failed with:
  File "/home/perenip/venv-flexcore/lib/python3.7/site-packages/django/db/migrations/serializer.py", line 339, in serializer_factory
    "topics/migrations/#migration-serializing" % (value, get_docs_version())
ValueError: Cannot serialize: PosixPath('/var/www/vhosts/foo/vendorstatic')
There are some values Django cannot serialize into migration files.
For more, see https://docs.djangoproject.com/en/3.1/topics/migrations/#migration-serializing

If I'm not mistaken, I couldn't read any reference to the Model/Field that triggered the error.
Should we expect an explicit mention of the faulty statement/line ?

2. I edited a Model within models.py with:
class Firmware(models.Model):
    #filepath = models.FilePathField(path=settings.VENDOR_STATIC_ROOT, match=settings.FIRMWARE_REGEX, recursive=True)

This is the issue. Your settings for VENDOR_STATIC_ROOT is a Path, not a string.

So in your settings use VENDOR_STATIC_ROOT = str(whatever expression you initialise it with)

Should fix this immediately.
 
    filepath = models.CharField(max_length=64)
    display_name = models.CharField(default='foobar', max_length=32, help_text='Value as shown in HTTP User-Agent string')

    def __str__(self):
        return self.relative_path()

    def relative_path(self):
        return str(pathlib.Path(self.filepath).relative_to(settings.VENDOR_STATIC_ROOT))

After changing from a PathFileField to a CharFiled as shown above, I could successfully run makemigrations.

Doc [1] mentions Django can serialize "any Django field". Should it serialize FilePathField ?


Yeah it's not the field at fault, it is the path= initialiser :-)
 
3. How to work around this with rewriting my app (and its tests) ?


HTH,
David 
Reply all
Reply to author
Forward
0 new messages