WedX - журнал о программировании и компьютерных науках

Резервное копирование пустого поля Django

У меня есть модель, которая содержит адрес пользователя. Эта модель должна иметь поля first_name и last_name, так как нужно указать адрес получателя (например, его компанию и т. д.). Чего я пытаюсь достичь, так это:

  • Если поле first_name/last_name в адресе заполнено - вернуть просто это поле
  • Если поле first_name/last_name в адресе пусто - получить соответствующие данные поля из внешнего ключа, указывающего на правильный django.auth.models.User
  • Я бы хотел, чтобы это рассматривалось как обычное поле Django, которое будет присутствовать при поиске полей.
  • Я не хочу создавать метод, так как это рефакторинг и Address.first_name/last_name используются в разных местах приложения (также в формах модели и т. д.), поэтому мне нужно, чтобы это было как можно более гладко, иначе, Придется повозиться во многих местах.

Ответы:


1

Здесь есть два варианта. Во-первых, создать метод для динамического поиска, но использовать декоратор property, чтобы другой код по-прежнему мог использовать прямой доступ к атрибутам.

class MyModel(models.Model):
    _first_name = models.CharField(max_length=100, db_column='first_name')

    @property
    def first_name(self):
        return self._first_name or self.user.first_name

    @first_name.setter
    def first_name(self, value):
       self._first_name = value

Это всегда будет ссылаться на самое последнее значение first_name, даже если связанный пользователь изменен. Вы можете получить/установить свойство точно так же, как атрибут: myinstance.first_name = 'daniel'

Другой вариант — переопределить метод save() модели, чтобы он выполнял поиск при сохранении:

def save(self, *args, **kwargs):
    if not self.first_name:
        self.first_name = self.user.first_name
    # now call the default save() method
    super(MyModel, self).save(*args, **kwargs)

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

27.08.2009
  • вы можете указать db_column='first_name', чтобы предотвратить изменение схемы: docs.djangoproject.com/en/dev/ref/models/fields/#db-column 27.08.2009
  • так что после @first_name.setter просто добавьте first_name.db_column=first_name ? Смогу ли я сделать: address = Address.objects.get(first_name=blah)? 27.08.2009
  • Я обновил код и объяснение в ответ на комментарий piquadrat. 27.08.2009
  • Спасибо за помощь :) работает без нареканий (метод свойств), единственное, что меня беспокоит - у меня есть типовая форма, и она не заполняет пустые поля с помощью self.user.first_name. Установка атрибута и получение работает без нареканий. 27.08.2009
  • Есть еще одна небольшая проблема - при поиске django orm не может разрешить поле информации о свойствах, для этого требуется исходное поле _first_name. 27.08.2009

  • 2

    Хотя это не соответствует всем требованиям OP, в некоторых случаях использования, когда требуется запасной вариант в фильтрах набора запросов (на уровне базы данных), можно использовать класс Coalesce() Django (docs).

    Простейшим решением в таком случае может быть аннотация набора запросов (на примере ответа @daniel-roseman):

    queryset = MyModel.objects.annotate(first_name=Coalesce('_first_name', 'user__first_name'))

    Каждый элемент, полученный из набора запросов, получит атрибут first_name, который имеет значение _first_name с запасным вариантом (в случае, если значение равно null) до user.first_name.

    То есть, если предположить, что ваша модель имеет отношение user.

    Это может быть реализовано, например. в пользовательском менеджере, а также может использоваться в сочетании с подходом property.

    Подробный пример для аналогичного случая (переопределение вместо отката) приведен в этом ответе SO.

    08.12.2018
    Новые материалы

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

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


    Для любых предложений по сайту: [email protected]