Django исключить поле из всех запросов - PullRequest
0 голосов
/ 17 октября 2019

Я использую Django на Heroku с функцией без простоев. Это означает, что во время развертывания в одной базе данных работают две версии кода (старая и новая). Вот почему мы должны избегать любых обратных несовместимых миграций.

Есть ли возможность исключить поле из запроса Django для данной модели?

Допустим, у нас есть модель (версия 1):

class Person(models.Model):
    name = models.CharField()
    address = models.TextField()

В некоторыхВ будущем мы хотим перенести адрес в отдельную таблицу. Мы знаем, что не следует удалять поле для более старого кода для работы, поэтому модель Person может выглядеть так (версия 2):

class Person(models.Model):
    name = models.CharField()
    address = models.ForeignKey(Address)
    _address = models.TextField(db_name='address')

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

Как теперь я могу безопасно удалить поле _address? Если мы развернем версию 3 с удаленным полем _address, то код для версии 2 все равно будет пытаться получить _address при выборе, даже если он нигде не используется и завершится с ошибкой «Нет такого столбца».

Есть ли способ предотвратить это и пометить какое-либо поле как "не подлежащее извлечению" в коде для версии 2? Таким образом, версия 2 не удалит поле, но больше не будет его извлекать, а версия 3 удалит поле.

Ответы [ 2 ]

1 голос
/ 18 октября 2019

Вы можете использовать менеджер пользовательских объектов для defer вашего конкретного поля / полей для всего набора запросов.

class CustomManager(models.Manager):
    def get_queryset(self):
        return super(CustomManager, self).get_queryset().defer('_address',)
class Person(models.Model):
    name = models.CharField()
    address = models.ForeignKey(Address)
    _address = models.TextField(db_name='address')

    objects = CustomManager()

, после этого в любом вашем наборе запросов для Person модель не будет включать _address поле в запросе по умолчанию.

0 голосов
/ 17 октября 2019

Да, вы можете сделать это:

QuerySet.defer ():

"В некоторых сложных ситуациях моделирования данных ваши модели могут содержать много полей, некоторыеиз которых могут содержать много данных (например, текстовые поля) или требовать дорогостоящей обработки для преобразования их в объекты Python.Если вы используете результаты набора запросов в какой-то ситуации, когда вы не знаете, нужны ли вам эти конкретныеполей при первоначальном извлечении данных, вы можете указать Django не извлекать их из базы данных. " - документы

Entry.objects.defer("headline", "body")

ИЛИ

С django 1.8 и выше: используйте values_list. Вы можете включать только те поля, которые вы хотите. Вы также можете использовать Queryset.only() и Queryset.defer() для уточнения запросов набора запросов. Вы также можете связывать defer() звонков

Entry.objects.values_list('id', 'headline')

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