--Django has a built-in migration feature since 1.7. -In order to automatically extract differences with ** makemigrations **, it is necessary to work on custom fields and custom validators of Model. --Field requires implementation of ** deconstruct ** method --Validator requires ** deconstructible ** decorator and ** \ _ \ _ eq \ _ \ _ ** method implementation ――Easy to summarize the correspondence contents.
--When I created a custom validator and ran ** makemigrations **, I ran into the following error:
python
There are some values Django cannot serialize into migration files.
For more, see https://docs.djangoproject.com/en/1.9/topics/migrations/#migration-serializing
--When I tried to solve this, I came to the story of ** deconstruct **.
--Class-based custom validators were written as follows before 1.6
# validators.py ----
from django.core.exceptions import ValidationError
class UploadSizeValidator:
def __init__(self, size=None):
if size:
self.size = size
def __call__(self, value):
if value.file.size > self.size:
raise ValidationError('Upload Size Error')
# models.py ----
class Question(models.Model):
question_image = models.ImageField(
upload_to='question_image',
validators=[UploadSizeValidator(size=200)],
default=None
)
--However, from 1.7, the above error is displayed unless Validator is implemented as follows.
from django.core.exceptions import ValidationError
from django.utils.deconstruct import deconstructible
@deconstructible # <-Add decorator
class UploadSizeValidator:
def __init__(self, size=None):
if size:
self.size = size
def __call__(self, value):
if value.file.size > self.size:
raise ValidationError('Upload Size Error')
def __eq__(self, other): # <- __eq__Implement method
return (
isinstance(other, self.__class__) and (self.size == other.size)
)
--This is the first time that ** make migrations ** passes. -The reason why ** \ _ \ _ eq \ _ \ _ ** is necessary is that it is used for difference comparison when generating a migration file. ――Specifically, the following things happen.
1. UploadSizeValidator(size=100)Suppose you created a migration file with
2.Change size to 200 and run makemigrations
3. __eq__Before change in method(other.size=100)And after the change(self.size=200)Compare size
4.AlterField migration files are generated because they do not match
――The content of the actually generated migration looks like this
operations = [
migrations.AlterField(
model_name='question',
name='question_image',
field=models.ImageField(
default=None, upload_to='question_image',
validators=[polls.validators.UploadSizeValidator(size=200)]
),
),
--By doing this, the contents of the validator can also be migrated or returned with backwards. ――By the way, function-based validators do not have anything that can be compared by difference, so it is the same as the writing method so far. --AlterField is only generated when specified as validators
def validate_even(value):
if value % 2 != 0:
raise ValidationError(
_('%(value)s is not an even number'),
params={'value': value},
)
--When creating a custom field, you need to implement the ** deconstruct ** method. -** deconstruct ** has a role similar to ** \ _ \ _ eq \ _ \ _ ** above --That is, it returns information to compare whether the Field has changed. --Information is field name (name), field path (path), Field argument to constructor (args), keyword argument (kwargs)
class HandField(models.Field):
def __init__(self, *args, **kwargs):
kwargs['max_length'] = 104
super(HandField, self).__init__(*args, **kwargs)
def deconstruct(self): # <- deconstruct
name, path, args, kwargs = super(HandField, self).deconstruct()
del kwargs["max_length"]
return name, path, args, kwargs
# refs https://docs.djangoproject.com/ja/1.9/howto/custom-model-fields/#field-deconstruction
--Custom validators and special work to create custom fields are required --** deconstructible ** is also required when creating a custom storage class
Recommended Posts