#django #postgresql #foreign-keys #django-3.1
#django #postgresql #внешние ключи #django-3.1
Вопрос:
У меня есть эти модели в моем коде
class Address(models.Model):
street = models.CharField(max_length=50)
city = models.CharField(max_length=10)
class User(models.Model):
name = models.CharField(max_length=20)
age = models.IntegerField()
address = models.OneToOneField(Address, on_delete=models.CASCADE)
Я понимаю, как models.CASCADE
работает в Django. Если я удалю Address
запись, соответствующая User
запись будет удалена, но это не то, что я хочу. Я хочу, чтобы Address
запись была удалена, если User
запись будет удалена.
Я знаю, что могу добиться этого, поместив OneToOneField
в Address
вместо User
, но для меня это не имеет смысла с точки зрения схемы базы данных, потому что User
имеет Address
. У Address
нет User
.
Я пытался найти информацию о том, как принудительно выполнить удаление обратным способом, но, по-видимому, это невозможно из всех опций, которые есть в Django (https://docs.djangoproject.com/en/3.1/ref/models/fields/#django.db.models .ForeignKey.on_delete).
Кто-нибудь знает альтернативу? Или правильный способ построения схемы базы данных в противном случае?
Спасибо!
Комментарии:
1. возможно,
pre_delete
сигнал?2. @ArakkalAbu — хорошо, спасибо. это кажется хорошей идеей, хотя я чувствую, что немного странно иметь
on_delete
функциональность, но не использовать ее в любом случае. Я также хотел знать, как я могу защититьUser
от удаления, еслиAddress
будет удален. Должен ли я просто использоватьon_delete=models.PROTECT
?
Ответ №1:
Я не знаю, как указать в вашем уровне запутывания (orm), но на уровне базы данных вы указываете что-то вроде
,constraint usr2adr_fk
foreign key (adr_id)
references address(id)
on delete set null --<<< instead of delete
К вашему сведению, всего пара комментариев:
- отношения 1: 1 всегда сомнительны. Иногда по соображениям безопасности или если вы проводите значительный анализ одного из столбцов. Но в противном случае просто переместите столбец из дочерней таблицы в родительскую. Кроме того, на уровне базы данных их очень сложно реализовать. Вам нужны двунаправленные FKS и ограничение уникальности столбца.
- Возраст — очень плохой атрибут. Оно меняется ежегодно, поэтому вам нужно обновление, чтобы поддерживать его в актуальном состоянии, но не все они меняются одновременно. Гораздо лучше хранить дату рождения, а затем вычислять возраст, когда это необходимо. Обновление не требуется.
Комментарии:
1. Спасибо. Я должен сказать, что модели — это просто глупые шаблоны, иллюстрирующие проблему, с которой я столкнулся с гораздо большими таблицами.
age
это просто то, что я ввел случайным образом, но я понял ваш первый пункт.
Ответ №2:
Согласно документам, on_delete=models.CASCADE
не будет удалять связанный объект ( OneToOneField
например.), и такие сигналы, как pre_delete
и post_delete
, должны использоваться для имитации поведения