Как добавить дополнительный аргумент ключевого слова во все поля Django? - PullRequest
0 голосов
/ 31 мая 2019

Приложение, над которым я работаю, требует объединения моделей Django идентичного типа.Эти модели содержат состояние, которое может быть изменено хронологическими событиями, поэтому это не так просто, как глубокое копирование одного объекта в другой, так как не всегда корректно принимать последнее значение или всегда копировать истинные значения, например.

Я написал класс слияния моделей для обработки этой операции, однако мне нужно иметь возможность описать для каждого поля, должно ли оно быть включено в это слияние и, если оно должно быть включено, как обрабатывать это слияние.

Я уже пытался создать словарь, чтобы описать это поведение и передать его в слияние.Однако это становится громоздким на больших уровнях вложенности и очень хрупким для изменения кодовой базы.

Я также пытался добавить метод слияния к каждой отдельной модели, что решило проблему, но очень чувствительно к сбоям, если чужойключевые отношения, которые существуют в другой модели, пропущены или кодовая база изменилась.

Я начал писать собственную версию каждого поля в Django, так как эти поля кажутся правильным местом для логики, чтобы жить, ноон также чувствует себя громоздким и хрупким, чтобы поддерживать собственные версии каждого поля.

Есть ли способ в Django добавить дополнительный аргумент ключевого слова в базовый класс Field или, возможно, украсить каждое поле без необходимости их подкласса?

Спасибо

1 Ответ

0 голосов
/ 04 июня 2019

На всякий случай, если это кому-нибудь еще поможет, я закончил тем, что создал миксин и подклассифицировал каждое отдельное поле. Ниже приведен сокращенный пример.

from django.db import models

class MappableFieldMixin():
    def __init__(self, should_map=True, map_mode=None, *args, **kwargs):
        self.should_map = should_map
        if should_map and not map_mode:
            raise TypeError('Mappable field requires map_mode if should_map set to True')
        self.map_mode = map_mode
        super().__init__(*args, **kwargs)

    def deconstruct(self):
        name, path, args, kwargs = super().deconstruct()
        kwargs['should_map'] = self.should_map
        kwargs['map_mode'] = self.map_mode
        return name, path, args, kwargs

class MappableBooleanField(MappableFieldMixin, models.BooleanField):
    pass

Использование:

class Membership(models.Model):
    is_active = MappableBooleanField(map_mode=MapMode.MAP_ALWAYS, default=True)

Дополнительную информацию о создании пользовательских полей можно найти в документации Django .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...