Форум сайта python.su
Как заставить Django не делать тот бред ( т е каскадные удаления апдейты и прочее ) который django пытается сделать считая себя умнее чем связи в БД при удалении записи ?
Офлайн
А вы хотите данные неконсистентными сделать?
Офлайн
Я хочу чтобы целостностью данных занималась БД. Т е когда хочу удалить свойство чтобы не удалялось каскадом полбазы в то время как в базе там стоит on delete restrict, а django мне пытается подсунуть on cascade delete. Кстати конечно хорошо написать столько кода который этот процесс эмулировал но нафига было это делать ? Уж лучше бы добавили много других полезных фич.
Отредактировано (Апрель 26, 2010 09:19:50)
Офлайн
Очень вероятно у вас какой-то косяк в проектировании моделей)
Но можно проставить значение ключа в None перед удалением, например.
Или еще что-то тут:
http://docs.djangoproject.com/en/dev/ref/models/relations/
QuerySet.remove
QuerySet.clear
Офлайн
Очень вероятно у вас какой-то косяк в проектировании моделей)Вы о чем ? Представьте 3 сущности - свойсва + модель+типы свойста. Соотв в интерфейсе на джанго 3 таблицы. В базе стоит соотв чтобы при попытке удалить тип свойства “отсылалось лесом”. В интерфейсе можно конечно проверять при попытке удаления но извините зачем это делать когда в базе все это учтены. И тут вмешивается великий ORM от Django который пытается этот “недостаток” устранить. В результате полбазы нет т к была попытка удалить тип свойства. В чем косяк то ?
Отредактировано (Апрель 26, 2010 10:39:38)
Офлайн
Это еще спорный вопрос кто за целостностью должен следить бд или орм, если вы используете орм)
а какой смысл от свойств у которых нет типа?) по моему логично удаляет)
Офлайн
Bdfy1В ДНК.
В чем косяк то ?
Bdfy1Где здесь хак?
А решение хакообразное:
technology = models.ForeignKey(Technology,null=True, blank=True)
Офлайн
де здесь хак?В том что связи предполагаются null что в общем-то не так. Если уж django ORM захотело копировать ON CASCADE DELETE то зачем это делать по умолчанию а не сделать опцией ? Причем если посмотреть генерируемые sql запросы при таком удалении - много интересного там можно найти :).
В ДНК.ДНК не ДНК но если с БД работает не только один интерфейс а что-то еще написанное на чем угодно - куда же еще такую логику не засунуть как в БД.
Такая логика в БД – зло.
Если не хотите чтобы типы свойств удалялись, то не удаляете. Перегрузите методы и сделайте чтобы они не удаляли объект.Я хочу чтобы типы свойств удалялись только те которые можно удалить - т е например типы которые не используются в моделях. Вот и все.
Отредактировано (Апрель 26, 2010 14:22:49)
Офлайн
Bdfy1, если вашу БД используют другие программы кроме django, причем во всякой извращенной форме (имеются в виду особенности, которые вы описали в предыдущем посте), то вам лучше смотреть в сторону SQLAlchemy, и отказаться от django в пользу, например, TG, или Pylons, которые с алхимией работают по умолчанию и рекомендациям. Все-таки django-ORM разрабатывался как часть django, а не как отдельный ORM, он удовлетворяет тем требованиям, которые на него возложены, и никаким другим.
Отредактировано (Апрель 26, 2010 15:00:23)
Офлайн
Ответы местных гуру просто впечатляют. Такое ощущение что никто ни разу не использовал ON DELETE RESTRICT:
* Evg: Очень вероятно у вас какой-то косяк в проектировании моделей)
* Daevaorn: Косяк в … ДНК
* Daevaorn: Такая логика в БД – зло.
* regall: вашу БД используют другие программы кроме django, причем во всякой извращенной форме
Тут хочется заметить что если ON DELETE RESTRICT явно ( mysql, postgresql ) или неявно ( oracle, mssql ) присутствует в большинстве нормальных баз, то наверное он злом или ошибкой в днк являться не может. Это так же глупо, как утверждать что крестовых отверток не существует, есть только плоские, только потому что вы не хотите пользоваться крестовой ( ужос ) :) А касательно кривости структуры и применимости этого поведения - ну вот хочу я чтобы запись можно было удалить только если на неё нет ссылок, мне удавиться или использовать другой фрейворк?
Отдельно порадовал ответ regall - “Все-таки django-ORM разрабатывался как часть django, а не как отдельный ORM, он удовлетворяет тем требованиям, которые на него возложены, и никаким другим.” Фраза ни о чем и полностью отражает подпись под этим постом. Кстати, было бы неплохо посмотреть на ссылочку, где расписана цель и задачи джанго орм.
Ответ lorien вообще является образцом “дружелюбия”. Новичкам не рады?
Да, собственно о чем я… Я не ругаться и не высказывать свое фи пришел. Просто каждый раз когда искал решение по эмуляции рестрикта наталкивался именно на эту страничку, потому решил на фоне прочих “фи” запечатлеть таки действенное решение - мало ли кто еще набредет. Впрочем, решений тонна.
Исходная задача - эмуляция ON DELETE RESTRICT, что в переводе на русский - запретить удаление объектов, на которые есть ссылки.
1. Перегрузить метод delete у models.Manager
Реализуемо, но меньше всего хотелось бы этим заниматься, поскольку model.Manager это практически полностью прокси к QuerySet, и фактически прийдется переписывать соответствующий метод именно у queryset, а там все не так тривиально, хоть и возможно. Вобщем отмел как геморный.
2. Перегрузить метод delete у models.Model
А вот тут как раз ничего сложного. Оригинальный код:
def delete(self, using=None):
using = using or router.db_for_write(self.__class__, instance=self)
assert self._get_pk_val() is not None, "%s object can't be deleted because its %s attribute is set to None." % (self._meta.object_name, self._meta.pk.attname)
# Find all the objects than need to be deleted.
seen_objs = CollectedObjects()
self._collect_sub_objects(seen_objs)
# Actually delete the objects.
delete_objects(seen_objs, using)
from django.db.models.signals import pre_delete
from django.db.models.query_utils import CollectedObjects
from django.db.utils import IntegrityError
def on_delete_restrict( sender, **kwargs ):
# Find all the objects than need to be deleted.
seen_objs = CollectedObjects()
kwargs['instance']._collect_sub_objects(seen_objs)
if len(seen_objs.data) > 1:
raise IntegrityError('Some objects are still depends on %s(pk=%s)' % ( str(kwargs['instance'].__class__.__name__), str(kwargs['instance'].pk) ) )
pre_delete.connect(on_delete_restrict, sender = Model1)
pre_delete.connect(on_delete_restrict, sender = Model2)
pre_delete.connect(on_delete_restrict, sender = Model3)
Отредактировано (Июнь 1, 2010 04:24:23)
Офлайн