问题
There is a model:
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")
I added batch of proxies in admin interface, and one of them is 0.0.0.0:0000, login=123, password=123. Then I add another batch of proxy, and one of them is the same 0.0.0.0:0000, but with new login=234 and password=234. Is any possibility to override save method of model to get behaviour like "insert ... on conflict (host, port) do update set login=login, password=password". Django 2, db - Postgres.
回答1:
Finally I found answer by myself. If anyone need it here is it:
(1) Deactivate validate_unique on unique fields in model:
def validate_unique(self, exclude=None):
super().validate_unique(exclude='host')
This check is called before save_model() or save() actions. So any other changes will be useless.
(2) Override save method:
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)
No update_or_create() or something similar approaches does not work here because they lead to infinite recursion. Just update or save method (even with force_update option) does not work too, because current object have no id yet. So we need to get that id if such object exists and update it or just create new object.
来源:https://stackoverflow.com/questions/51205137/django-model-update-or-create-object-with-unique-constraint