Обновление модели Django или создание объекта с уникальным ограничением - PullRequest
0 голосов
/ 06 июля 2018

Есть модель:

class Proxy(models.Model):
        host = models.CharField(max_length=100,)
        port = models.CharField(max_length=10,)
        login = models.CharField(max_length=100,)
        password = models.CharField(max_length=100,)
    class Meta:
        unique_together = ("host", "port")

Я добавил партию прокси в интерфейс администратора, и один из них - 0.0.0.0:0000, логин = 123, пароль = 123. Затем я добавляю еще одну партию прокси, и один из них такой же 0.0.0.0:0000, но с новым логином = 234 и паролем = 234. Любая возможность переопределить метод сохранения модели, чтобы получить поведение типа «вставить ... при конфликте (хост, порт), сделать обновление set login = login, password = password». Джанго 2, дб - Постгрес.

1 Ответ

0 голосов
/ 12 июля 2018

Наконец я нашел ответ сам. Если кому-то это нужно, вот оно:

(1) Отключить validate_unique для уникальных полей в модели:

def validate_unique(self, exclude=None):
    super().validate_unique(exclude='host')

Эта проверка вызывается перед действиями save_model () или save (). Так что любые другие изменения будут бесполезны.

(2) Метод сохранения с переопределением:

def save(self, *args, **kwargs):
    proxy = Proxy.objects.get(host=self.host, port=self.port)
    if proxy:
        self.id = proxy.id
        super().save(*args, **kwargs, update_fields=["login", "password"])
    else:
        super().save(*args, **kwargs)

Нет update_or_create () или что-то подобное, здесь не работает, потому что они приводят к бесконечной рекурсии. Просто обновить или сохранить метод (даже с параметром force_update) тоже не работает, потому что у текущего объекта еще нет идентификатора. Поэтому нам нужно получить этот идентификатор, если такой объект существует, и обновить его или просто создать новый объект.

...