2011-02-07 4 views
2

Я делаю переход от sqlite к backend. База данных оракула уже существует и поддерживается другими людьми. Его версия - Oracle9i Enterprise Edition Release 9.2.0.1.0.Ошибка целостности Django Oracle при сохранении любого экземпляра базы данных

У меня есть простая модель:

class AliasType(models.Model): 
    id = models.AutoField(primary_key=True, db_column="F_ALIAS_ID") 
    name = models.CharField(u"Type name", max_length=255, unique=True, db_column="F_ALIAS_NAME") 

    class Meta: 
     db_table = "ALIAS" 

./manage.py syncdb не возвращает никаких ошибок. Но когда я пытаюсь создать новый экземпляр и сохранить его в базу данных, я получаю следующее сообщение об ошибке:

>>> AliasType.objects.create(name="test") 
Traceback (most recent call last): 
    File "<console>", line 1, in <module> 
    File "/mnt/Data/private/projects/envs/termary-oracle/src/django/django/db/models/manager.py", line 138, in create 
    return self.get_query_set().create(**kwargs) 
    File "/mnt/Data/private/projects/envs/termary-oracle/src/django/django/db/models/query.py", line 360, in create 
    obj.save(force_insert=True, using=self.db) 
    File "/mnt/Data/private/projects/envs/termary-oracle/src/django/django/db/models/base.py", line 460, in save 
    self.save_base(using=using, force_insert=force_insert, force_update=force_update) 
    File "/mnt/Data/private/projects/envs/termary-oracle/src/django/django/db/models/base.py", line 553, in save_base 
    result = manager._insert(values, return_id=update_pk, using=using) 
    File "/mnt/Data/private/projects/envs/termary-oracle/src/django/django/db/models/manager.py", line 195, in _insert 
    return insert_query(self.model, values, **kwargs) 
    File "/mnt/Data/private/projects/envs/termary-oracle/src/django/django/db/models/query.py", line 1435, in insert_query 
    return query.get_compiler(using=using).execute_sql(return_id) 
    File "/mnt/Data/private/projects/envs/termary-oracle/src/django/django/db/models/sql/compiler.py", line 791, in execute_sql 
    cursor = super(SQLInsertCompiler, self).execute_sql(None) 
    File "/mnt/Data/private/projects/envs/termary-oracle/src/django/django/db/models/sql/compiler.py", line 735, in execute_sql 
    cursor.execute(sql, params) 
    File "/mnt/Data/private/projects/envs/termary-oracle/src/django/django/db/backends/util.py", line 18, in execute 
    return self.cursor.execute(sql, params) 
    File "/mnt/Data/private/projects/envs/termary-oracle/src/django/django/db/backends/oracle/base.py", line 630, in execute 
    return self.cursor.execute(query, self._param_generator(params)) 
IntegrityError: ORA-01400: cannot insert NULL into ("SINCE"."ALIAS"."F_ALIAS_ID") 

Если я указать идентификатор, например, AliasType.objects.create(id=5, name="test"), он работает. Я думал, что django должен иметь возможность автоматически извлекать значение id. Я узнал, что Oracle не поддерживает автоинкремент, и я должен использовать триггеры и последовательности. Мне сказали, что в базе данных есть существующая последовательность, которая возвращает идентификаторы для всех новых строк, и я знаю ее имя, скажем SEQ_GET_NEW_ID.

Итак, вопрос заключается в том, как реализовать это самым элегантным способом, то есть как рассказать Django о get id values for all new objects from the sequence named SEQ_GET_NEW_ID, не слишком сильно взломав его (например, переопределяя методы save() для всех моделей)?

ответ

1

Существует открытый билет (#1946), позволяющий именно это, переопределяя имя последовательности по умолчанию. Но поскольку он еще не закрыт, я не думаю, что есть способ без взлома.

Я раньше не использовал Oracle, но быстрый поиск предполагает, что можно создавать псевдонимы/синонимы для последовательностей. manage.py sqlall <app> должен показать вам имя последовательности, которое ожидает Django. Таким образом, вы, вероятно, могли бы сделать это псевдонимом для SEQ_GET_NEW_ID.

+0

Благодарим за ответ. Это помогло мне найти решение. Я попросил человека, который поддерживает базу данных, создавать триггеры для всех таблиц. Триггеры получают следующий id перед вставкой из той же последовательности 'SEQ_GET_NEW_ID'. Поэтому здесь не нужны псевдонимы для последовательности. –

+2

Просто, чтобы уточнить, как django получает идентификатор только что вставленной строки. Если указан параметр 'use_returning_into', django получает идентификатор непосредственно из предложения' INSERT'. В этом случае django не требуется. Если 'use_returning_into' является ложным, django сначала получает новый идентификатор из последовательности, которая имеет имя' APP_MODEL_SQ', а затем вставляет строку с этим идентификатором. В этом случае вам нужно создать псевдонимы для существующих последовательностей (это может быть одна и та же последовательность для всей базы данных), чтобы django мог их использовать. –

Смежные вопросы