Django integrity error

Short answer: don’t 😉

Published 4 March, 2019;
last updated on 23 April, 2021.

As part of a project I’m working on, I’m refactoring two nearly identical models (create.Event and delete.Event) into one (generic.Event).

Doing this requites a handful of migrations to:

  1. create the table for generic.Event;
  2. move the data from create.Event into generic.Event and delete the create.Event table; and
  3. move the data from delete.Event into generic.Event and delete the delete.Event table.

Migrations two and three call this function to move data between models:

from django.forms.models import model_to_dict

def move_events(source_model, dest_model):
    for source in source_model.objects.all():
        source_fields = model_to_dict(source)
        del source_fields['id']

        dest = dest_model()
        for attr, value in source_fields.items():
            setattr(dest, attr, value)

        dest.save()

This works perfectly well … until I introduce real-world data and a unique event_id field into my models. 😢

django.db.utils.IntegrityError: duplicate key value violates unique constraint "generic_event_id_key"
DETAIL: Key (event_id)=(the-duplicate-key) already exists.

Taking a pythonic “easier to ask for forgiveness than permission” approach, my first attempt at this was to wrap the call to save in a try … except block:

from django.db.utils import IntegrityError

try:
    dest.save()
except IntegrityError as err:
    print("Ignoring unhandled integrity error:")
    print(err)

I naively deployed this fix expecting my problems to vanish, but the exceptions persisted. 😭

I was now getting TransactionManagementErrors.

django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.

After some digging, reading, and thinking, I realised that the cause of the IntegrityError isn’t Python—it’s Postgres. Handling the error in Python is suppressing an error about a failed transaction, but the transaction is still failed.

The Django docs give a clue about what’s happening here:

Inside a transaction, when a call to a PostgreSQL cursor raises an exception (typically IntegrityError), all subsequent SQL in the same transaction will fail with the error “current transaction is aborted, queries ignored until end of transaction block”. While simple use of save() is unlikely to raise an exception in PostgreSQL, there are more advanced usage patterns which might, such as saving objects with unique fields, saving using the force_insert/force_update flag, or invoking custom SQL.

In order to stop IntegrityErrors in your migrations, you need to “look before you leap” to stop the cause of them in the first place. For me, that meant something like the following:

def move_events(source_model, dest_model):
    for source in source_model.objects.all():
        source_fields = model_to_dict(source)
        del source_fields['id']

        # Ignore records with pre-existing event IDs.
        event_id = source_fields['event_id']
        if dest_model.objects.filter(event_id=event_id).exists():
            print("Discarding record with duplicate event ID.")
            pprint(source_fields)
            continue

        dest = dest_model()
        for attr, value in source_fields.items():
            setattr(dest, attr, value)

        dest.save()

Cover image for How to Fix IntegrityError or Not Null Constraint Failed in Django

Shahriar Shakil 👨‍💻

Learn how to fix integrity errors or not null constraint failed in Django. You can easily fix this error just avoid 2 simple mistakes.

I’m a full-time freelance contractor and available for hire.

My Expertise:

— Web Design,
— Web Development
— WordPress
— Python
— Graphic Design

For business queries:
wpcodersclub@gmail.com

Please subscribe to my channel for more amazing tuts.

Thanks for watching

Top comments (0)

For further actions, you may consider blocking this person and/or reporting abuse

Why You Need to Study Javascript Fundamentals

The harsh reality for JS Developers: If you don’t study the fundamentals, you’ll be just another “Coder”. Top learnings on how to get to the mid/senior level faster as a JavaScript developer by Dragos Nedelcu.

Read next


viniciusenari profile image

Automating Content Creation with Python: Obtaining Clips from Twitch

Vinicius Koji Enari — Jan 25


scofieldidehen profile image

Build Your First Port Scanner using Python

Scofield Idehen — Feb 4


ycrydev profile image

How to get Wallet Addresses from Comment section of a Tweet

Ycrypto-3 — Jan 2


polterguy profile image

Include ChatGPT on your WordPress website

Thomas Hansen — Jan 25

Django вызывает некоторые собственные исключения, а также стандартные исключения Python.

Исключения ядра Django¶

Классы исключений ядра Django определены в django.core.exceptions.

AppRegistryNotReady

exception AppRegistryNotReady[исходный код]

Это исключение возникает при попытке использовать модели до завершения процедуры app loading process, которая инициализирует ORM.

EmptyResultSet

exception EmptyResultSet[исходный код]

EmptyResultSet может возникнуть во время генерации запроса, если запрос не вернет никаких результатов. Большинство проектов Django не столкнутся с этим исключением, но оно может быть полезно для реализации пользовательских поисков и выражений.

FieldDoesNotExist

exception FieldDoesNotExist[исходный код]

Исключение FieldDoesNotExist вызывается методом _meta.get_field() модели, когда запрашиваемое поле не существует ни в модели, ни в родителях модели.

SuspiciousOperation

exception SuspiciousOperation[исходный код]

Исключение SuspiciousOperation возникает, когда пользователь выполнил операцию, которую следует считать подозрительной с точки зрения безопасности, например, подделка куки сеанса. Подклассы SuspiciousOperation включают:

  • DisallowedHost
  • DisallowedModelAdminLookup
  • DisallowedModelAdminToField
  • DisallowedRedirect
  • InvalidSessionKey
  • RequestDataTooBig
  • SuspiciousFileOperation
  • SuspiciousMultipartForm
  • SuspiciousSession
  • TooManyFieldsSent

Если исключение SuspiciousOperation достигает уровня обработчика ASGI/WSGI, оно регистрируется на уровне Error и приводит к появлению HttpResponseBadRequest. Дополнительную информацию см. в logging documentation.

PermissionDenied

exception PermissionDenied[исходный код]

Исключение PermissionDenied возникает, когда у пользователя нет разрешения на выполнение запрашиваемого действия.

ViewDoesNotExist

exception ViewDoesNotExist[исходный код]

Исключение ViewDoesNotExist вызывается django.urls, когда запрашиваемое представление не существует.

MiddlewareNotUsed

exception MiddlewareNotUsed[исходный код]

Исключение MiddlewareNotUsed возникает, когда промежуточное ПО не используется в конфигурации сервера.

ImproperlyConfigured

exception ImproperlyConfigured[исходный код]

Исключение ImproperlyConfigured возникает, когда Django каким-то образом неправильно настроен — например, если значение в settings.py неверно или не поддается разбору.

FieldError

exception FieldError[исходный код]

Исключение FieldError возникает, когда возникает проблема с полем модели. Это может произойти по нескольким причинам:

  • Поле в модели конфликтует с одноименным полем из абстрактного базового класса
  • Бесконечный цикл возникает при заказе
  • Ключевое слово не может быть разобрано из параметров фильтра
  • Поле не может быть определено по ключевому слову в параметрах запроса
  • Объединение не разрешено для указанного поля
  • Имя поля является недопустимым
  • Запрос содержит недопустимые аргументы order_by

ValidationError

exception ValidationError[исходный код]

Исключение ValidationError возникает, когда данные не проходят валидацию полей формы или модели. Подробнее о валидации см. в Form and Field Validation, Model Field Validation и Validator Reference.

NON_FIELD_ERRORS

NON_FIELD_ERRORS

ValidationError, которые не принадлежат определенному полю в форме или модели, классифицируются как NON_FIELD_ERRORS. Эта константа используется в качестве ключа в словарях, которые иначе сопоставляют поля с соответствующим списком ошибок.

BadRequest

exception BadRequest[исходный код]

Исключение BadRequest возникает, когда запрос не может быть обработан из-за ошибки клиента. Если исключение BadRequest достигает уровня обработчика ASGI/WSGI, оно приводит к возникновению HttpResponseBadRequest.

RequestAborted

exception RequestAborted[исходный код]

Исключение RequestAborted возникает, когда HTTP-тело, считываемое обработчиком, обрывается на середине пути и клиентское соединение закрывается, или когда клиент не отправляет данные и достигает тайм-аута, при котором сервер закрывает соединение.

Он является внутренним для модулей обработчика HTTP, и вы вряд ли увидите его где-либо еще. Если вы модифицируете код обработки HTTP, вам следует вызывать это сообщение, когда вы столкнулись с прерванным запросом, чтобы убедиться, что сокет закрыт чисто.

SynchronousOnlyOperation

exception SynchronousOnlyOperation[исходный код]

Исключение SynchronousOnlyOperation возникает, когда код, допустимый только в синхронном коде Python, вызывается из асинхронного контекста (потока с запущенным асинхронным циклом событий). Эти части Django в целом сильно зависят от потокобезопасности для функционирования и не работают корректно в корутинах, разделяющих один и тот же поток.

Если вы пытаетесь вызвать код, который является только синхронным, из асинхронного потока, то создайте синхронный поток и вызывайте его в нем. Этого можно добиться с помощью asgiref.sync.sync_to_async().

Исключения из URL-резольвера¶

Исключения URL Resolver определены в django.urls.

NoReverseMatch

exception NoReverseMatch[исходный код]

Исключение NoReverseMatch вызывается django.urls, когда подходящий URL в вашей URLconf не может быть идентифицирован на основе предоставленных параметров.

Исключения из базы данных¶

Исключения из базы данных могут быть импортированы из django.db.

Django обертывает стандартные исключения баз данных так, чтобы ваш код Django имел гарантированную общую реализацию этих классов.

exception Error[исходный код]
exception InterfaceError[исходный код]
exception DatabaseError[исходный код]
exception DataError[исходный код]
exception OperationalError[исходный код]
exception IntegrityError[исходный код]
exception InternalError[исходный код]
exception ProgrammingError[исходный код]
exception NotSupportedError[исходный код]

Обертки Django для исключений баз данных ведут себя точно так же, как и базовые исключения баз данных. Более подробную информацию смотрите в PEP 249, спецификация Python Database API Specification v2.0.

Как и в случае PEP 3134, атрибут __cause__ устанавливается с исходным (базовым) исключением базы данных, позволяя получить доступ к любой дополнительной информации.

exception models.ProtectedError

Возникает для предотвращения удаления ссылающихся объектов при использовании django.db.models.PROTECT. models.ProtectedError является подклассом IntegrityError.

exception models.RestrictedError

Возникает для предотвращения удаления ссылающихся объектов при использовании django.db.models.RESTRICT. models.RestrictedError является подклассом IntegrityError.

Исключения HTTP¶

Исключения HTTP могут быть импортированы из django.http.

UnreadablePostError

exception UnreadablePostError[исходный код]

UnreadablePostError возникает, когда пользователь отменяет загрузку.

Исключения из сессий¶

Исключения сессий определены в django.contrib.sessions.exceptions.

SessionInterrupted

exception SessionInterrupted[исходный код]

SessionInterrupted возникает, когда сессия уничтожается в параллельном запросе. Он является подклассом BadRequest.

Исключения транзакций¶

Исключения транзакций определены в django.db.transaction.

TransactionManagementError

exception TransactionManagementError[исходный код]

TransactionManagementError поднимается для любых и всех проблем, связанных с транзакциями базы данных.

Исключения в системе тестирования¶

Исключения, предоставляемые пакетом django.test.

RedirectCycleError

exception client.RedirectCycleError

RedirectCycleError поднимается, когда тестовый клиент обнаруживает цикл или слишком длинную цепочку перенаправлений.

Исключения в Python¶

Django также поднимает встроенные исключения Python, когда это необходимо. Более подробную информацию о Built-in Exceptions смотрите в документации Python.

Понравилась статья? Поделить с друзьями:
  • Django forms error class
  • Django forms custom error
  • Django form save error
  • Django form raise validation error
  • Django form is valid get error