Джанго пустое поле запасной - PullRequest
4 голосов
/ 27 августа 2009

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

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

Спасибо за помощь:)

Ответы [ 2 ]

6 голосов
/ 27 августа 2009

Здесь есть два варианта. Первый - создать метод для динамического поиска, но использовать декоратор 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)

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

0 голосов
/ 08 декабря 2018

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

Самым простым решением в таком случае может быть аннотация набора запросов (на примере @ 1006 * answer ответа @ 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-ответе .

...