Может ли поле generic.GenericForeignKey () быть пустым?

Я создаю объект, который отслеживает изменения (обновления), касающиеся создания, обновления и удаления других так называемых UUIDSyncable объектов в базе данных.

Сюда входит любой объект, который расширяет методы save() и delete() классов UUIDSyncable, замещаемый таким образом, что он создает новый Update объект, записывающий действие (вставку, обновление или удаление), и первоначально поле models.CharField(max_length=64), определяющее pk UUID для из UUIDSyncable объектов.

На этом этапе я хотел обновить реализацию, чтобы использовать поле Django generic.GenericForeignKey() вместо моего односимвольного поля. Это позволит получить доступ к объекту, о котором записывается обновление, гораздо более простым способом.

Моя проблема возникает, когда вы хотите удалить объект и сохранить его как объект Update, поскольку вы знаете, что Django выполняет каскадное удаление удаляемого объекта UUIDSyncable, удаляя все предыдущие записи Update (что нежелательно).

Когда объект UUIDSyncable был удален в моей исходной реализации, каждый объект Update по-прежнему сохранял бы UUID, чтобы информировать внешние стороны о своем удалении. Моим первым решением для эмуляции этого было установить content_object = None непосредственно перед удалением объекта на всех Update объектах, что предотвратило каскад удаления.

Кажется, что generic.GenericForeignKey() не может быть разрешено NULL значения. Есть ли способ сделать это, а если нет, то как можно аналогичным образом использовать стандартный CharField, содержащий первичный ключ UUID, и Sperate CharField, содержащий название модели?


person Marcus Whybrow    schedule 01.03.2010    source источник


Ответы (3)


Возможно, вам нужно установить null = True в базовых полях content_type и object_id, составляющих общий внешний ключ.

person Daniel Roseman    schedule 01.03.2010
comment
Я попытался разрешить content_type иметь значение null, но не object_id, так как я всегда хочу сохранить значение, которое идентификатор объекта (в данном случае charField PK) имеет для справки позже (даже после того, как объект, который он указывает), был удален. Я помню, что это не шов, чтобы позволить мне установить мою цель. - person Marcus Whybrow; 03.03.2010

Для ленивых / прагматиков:

class MyModel(models.Model):
    ...other fields...
    content_type = models.ForeignKey(ContentType, blank=True, null=True, on_delete=models.SET_NULL)
    object_id = models.PositiveIntegerField(blank=True, null=True)
    content_object = generic.GenericForeignKey('content_type', 'object_id')
person Mark Chackerian    schedule 12.01.2015
comment
Мне нравится, когда я гугу и натыкаюсь на свой собственный ответ ... ооо - person Mark Chackerian; 30.01.2015
comment
content_type & object_id - имена по умолчанию, вам даже не нужно устанавливать их в качестве аргументов, content_object = generic.GenericForeignKey() было бы достаточно - person yamm; 29.05.2015
comment
@yamm вы должны указать, чтобы они явно имели blank = True / null = True в этих полях, чтобы content_object мог иметь значение null, о чем и идет речь. - person Mark Chackerian; 29.05.2015
comment
@MarkChackerian да, я знаю ;-) вот почему я сказал, что вам не нужно устанавливать content_type & object_id в качестве аргументов, потому что они по умолчанию. Вы определяете content_type & object_id, а затем просто делаете content_object = generic.GenericForeignKey() - person yamm; 01.06.2015
comment
Также рекомендуется установить ограничение on_delete=models.SET_NULL на content_type, поскольку по умолчанию это CASCADE. - person Antoine Pinsard; 28.04.2016
comment
@AntoinePinsard, спасибо - я обновил свой ответ, так как on_delete теперь требуется для Django 2.0 - person Mark Chackerian; 07.12.2017
comment
@yamm - так раздражает, когда люди полагаются на имена полей по умолчанию вместо того, чтобы делать это явным. Я рада, что твой совет проигнорировали. - person Greg Schmit; 15.12.2019

Вы пробовали установить null=True на GenericForeignKey? Общие внешние ключи не являются концепцией, которая распознается приложением низкоуровневой базы данных (например, MySQL, SQLite и т. Д.), Поэтому вы должны иметь возможность указать, что поле имеет значение NULL.

null=True в поле базы данных в Django означает, что поле базы данных, представляющее эти данные, разрешено быть пустым, тогда как blank=True сообщает формам / проверке модели Django, что поле в порядке, чтобы пользователь оставил его пустым ( или вы, через админку). Следовательно, вам может потребоваться использовать оба, чтобы добиться того, что вам нужно.

person Rob Golding    schedule 01.03.2010