What is the purpose of Django to "deconstruct" the field function of the model?

To develop custom fields for the Django model, I read the documentation.

I already developed my custom field (which is almost equal to that in the example, HandField : a field mapped over a Python class ... The only difference being that I inherit from models.CharField , not models.Field ).

 from external_library import ExternalClass class ExternalClassField(models.CharField): description = "An ExternalClass field" def __init__(self, *args, **kwargs): kwargs['max_length'] = 14 super(ExternalClassField, self).__init__(*args, **kwargs) def from_db_value(self, value, expression, connection, context): if value is None: return value return ExternalClass(value) def to_python(self, value): if isinstance(value, ExternalClass): return value if value is None: return value return ExternalClass(value) def get_prep_value(self, value): if value is None: return value if isinstance(value, ExternalClass): return value.to_string() return value 

The field behaves as expected. However, I am stuck in this part of the documentation: deconstruct () .

In particular, I do not understand what it is:

  • What is the purpose of the deconstruct function?
  • Why does my field work fine even without it (and even if I change the init arguments)?
  • How and when does Django call the deconstruct function?

I do not want to blindly copy-paste code that I do not understand, but the documentation is not clear.

+5
source share
1 answer

The deconstruct() method is used to migrate a model that cannot be automatically processed by the system. Let me go through the scenario where deconstruction will be called.

Let's say we had some kind of model, and we added a custom field to it. We are trying to migrate using python manage.py makemigrations .

We encounter the following error:

 ValueError: Cannot serialize: Foo There are some values Django cannot serialize into migration files. 

It turned out that there already exists a linked ticket that was submitted to the Django project, and check it out.

ticket-issue

One of the main developers answered that this is the intended behavior, because our field contains the called.

ticket-resolution

So, we missed something in the documentation. The called value is stored there, and for some reason it cannot be automatically transferred. What we can do?

Well, in addition to telling us about ValueError , manage.py also gave us a useful documentation link:

docs-link

On this page, scroll down a bit until we get to the section on serializing values .

Django can serialize the following:

  • ...
  • All that the user-defined deconstruct () method has (see below)
  • ...

Ok, let see below :

You can let Django serialize its own instances of the class by providing the class method deconstruct (). It takes no arguments and should return a tuple of three things (path, args, kwargs):

  • the path must be the Python path for the class with the class name included as the last part (for example, myapp.custom_things.MyClass). If your class is not available at the top level of the module, this is not serialization.
  • args should have a list of positional arguments to jump to your init class. Everything on this list should be serializable.
  • kwargs must be a keyword argument to go to your init class. Each value must be serialized.

Note that the deconstruct () method works hand in hand with __eq__() , as stated in the documentation:

To prevent creating a new migration every time you run makemigrations, you must also add the __ eq __ () method to the decorated class. This feature will be called by the Djangos migration framework to detect changes between states.

In my case, the mistake was to add brackets after the value that should not have been called, but in many cases you will want to implement this method of deconstructing for migration. (Here is another useful link that has an example.)

+12
source

Source: https://habr.com/ru/post/1239630/


All Articles