Можно ли переопределить отношение внешнего ключа с помощью пользовательского метода / свойства - PullRequest
3 голосов
/ 25 апреля 2020

Контекст

Я работаю над рефакторингом приложения Django 2.X, особенно базовой модели, CoreModel. Существует одна база данных (Postgres), содержащая все связанные таблицы.

Экземпляры CoreModel больше не будут жить в Postgres после этого рефакторинга, они будут жить где-то еще, но вне области действия Django project, скажем, некоторая AWS No- SQL служба базы данных.

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

class CordeModel(models.Model):
    pass

class SatelliteModel(models.Model):
    core = models.ForeignKey(CoreModel)

    def some_instance_method(self):
       return self.core.calculate_stuff() # <- override self.core!

Проблема

Код заполнен упоминаниями об отношении CoreModel, и я не смог успешно решить эту проблему.

Моим первым наивным подходом было реализовать метод получения @property, чтобы у меня была достаточно гибкости, чтобы сделать что-то вроде:

@property
def core(self):
    try:
       # ORM
       return self.core
    except CoreNotFound:
       # External datastore
       return aws_client.fetch_core()

С этим фрагментом у меня есть круговая зависимость от core имя, так что идея отсутствует.

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

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

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

Любые идеи, которые вы можете дать, очень ценятся.

ОБНОВЛЕНИЕ

Я забыл добавить самую важную информацию.

Большая часть CoreModel будет удалена для Postgres ( историй (1066 *), но есть крошечная часть CoreModel с, которая останется и будет перемещена через некоторое время. По сути, в Postgres останутся только «активные» CoreModel s, но в конечном итоге все они будут удалены, в то время как будут созданы новые CoreModel.

Так что исключается возможность изменения поле ForeignKey для целого числа.

1 Ответ

0 голосов
/ 26 апреля 2020

Вы можете сохранить, но переименовать внешний ключ, а затем добавить свойство со старым именем

class SatelliteModel(models.Model):
    old_core = models.ForeignKey(CoreModel, null=True, blank=True, on_delete=models.SET_NULL)

    @property
    def core(self):
        try:
            return self.old_core
        except CoreModel.DoesNotExist:
            return aws_client.fetch_core()

Это изменит имя столбца в вашей схеме, хотя вы можете переопределить имя столбца, чтобы предотвратить это

old_core = models.ForeignKey(CoreModel, db_column='core_id', null=True, blank=True, on_delete=models.SET_NULL)

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

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