-
-
Save vdboor/e3754e19551f2fbbcc31b01eec99ee8e to your computer and use it in GitHub Desktop.
""" | |
Patch the creation of database migrations in Django | |
Import this early from `__init__.py``. | |
- Don't want verbose_name changes in the migrations file. | |
- Don't want help_text in the migrations file. | |
""" | |
from functools import wraps | |
from django.db.models import Field | |
def patch_deconstruct(old_func, condition): | |
""" | |
Patch the ``Field.deconstruct`` to remove useless information. | |
This only happens on internal apps, not third party apps. | |
""" | |
@wraps(old_func) | |
def new_deconstruct(self): | |
name, path, args, kwargs = old_func(self) | |
# AutoField has no model on creation, but can be skipped | |
if hasattr(self, 'model') and condition(self): | |
kwargs.pop('verbose_name', None) | |
kwargs.pop('help_text', None) | |
return name, path, args, kwargs | |
return new_deconstruct | |
Field.deconstruct = patch_deconstruct(Field.deconstruct, lambda self: self.model.__module__.startswith('apps.')) |
from django.core.management.commands.makemigrations import Command
Why import Command if it is not used?
The unused import is a bit of a hack – Django needs a Command
subclass to be present in the file to know what to do. If we simply import Command
, Django will find it and try to run it (which means that nothing happens, as Command
doesn't take any action).
It's a bit hacky to just import Command
– you could also do something more explicit, which I do in my code, and I've updated the snippet above to reflect that: Import Command as SomeOtherName
, and define your class Command(SomeOtherName): pass
, so that it's clear from reading the code that you need to have this class present.
Now I understand.
Will this option still work correctly for django 4.1 version? Because I didn't find another solution to exclude some data from the migration. I use the dynamic field verbose_name_plural in the admin panel, after the model name I display the amount of some filtered data
I have not used the command with Django 4.1 yet. You'll have to look at the changelog to see if there's anything to suggest that the API changed.
Just to note that the solution provided by @rixx is better because importing from
__init__.py
will cause django test to fail due to infinite recursion problem.