Django在form.save()之前引发IntegrityError异常



我有一个模型;代码";字段和同一模型的形式;代码";字段被隐藏。我需要设置";代码";值,但是我得到IntegrityError异常。

型号

class Ticket(models.Model):
codice = models.CharField(unique=True, max_length = 13, default = '')

表单

class NewTicketForm(forms.ModelForm):
codice = forms.CharField(widget = forms.HiddenInput(), required=False)

视图

if request.method == 'POST':
form = NewTicketForm(request.POST)
form.codice = 'MC-PR' + get_random_string(length=8, allowed_chars='0123456789')
if form.is_valid():
while True:
try:
codice = 'MC-PR' + get_random_string(length=8, allowed_chars='0123456789')
form.codice = codice
form.save() 
except:
break
form.save()
return redirect('ticket-homepage')
else:
form = NewTicketForm()
context = {
'form': form
}
return render(request, 'ticket/new_ticket_form.html', context)

我还尝试将form.code设置在form.is_valid((之前,但无论如何都会引发异常。从技术上讲,应该不会有任何问题,因为我使用getrandom_string生成值,并且只要值不是唯一的,就可以尝试except允许我再次执行。

回溯

Traceback (most recent call last):
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/django/db/backends/mysql/base.py", line 73, in execute
return self.cursor.execute(query, args)
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/pymysql/cursors.py", line 148, in execute
result = self._query(query)
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/pymysql/cursors.py", line 310, in _query
conn.query(q)
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/pymysql/connections.py", line 548, in query
self._affected_rows = self._read_query_result(unbuffered=unbuffered)
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/pymysql/connections.py", line 775, in _read_query_result
result.read()
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/pymysql/connections.py", line 1156, in read
first_packet = self.connection._read_packet()
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/pymysql/connections.py", line 725, in _read_packet
packet.raise_for_error()
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/pymysql/protocol.py", line 221, in raise_for_error
err.raise_mysql_exception(self._data)
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/pymysql/err.py", line 143, in raise_mysql_exception
raise errorclass(errno, errval)
The above exception ((1062, "Duplicate entry '' for key 'ticket_ticket.ticket_ticket_codice_f619a2bb_uniq'")) was the direct cause of the following exception:
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/var/www/framework_mc/ticket/views.py", line 34, in createNewTicket
form.save()
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/django/forms/models.py", line 460, in save
self.instance.save()
File "/var/www/framework_mc/ticket/models.py", line 72, in save
return super(Ticket, self).save(*args, **kwargs)
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/django/db/models/base.py", line 753, in save
self.save_base(using=using, force_insert=force_insert,
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/django/db/models/base.py", line 790, in save_base
updated = self._save_table(
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/django/db/models/base.py", line 895, in _save_table
results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/django/db/models/base.py", line 933, in _do_insert
return manager._insert(
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/django/db/models/query.py", line 1254, in _insert
return query.get_compiler(using=using).execute_sql(returning_fields)
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1397, in execute_sql
cursor.execute(sql, params)
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/django/db/backends/utils.py", line 98, in execute
return super().execute(sql, params)
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/django/db/backends/utils.py", line 66, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/django/db/utils.py", line 90, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/django/db/backends/mysql/base.py", line 73, in execute
return self.cursor.execute(query, args)
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/pymysql/cursors.py", line 148, in execute
result = self._query(query)
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/pymysql/cursors.py", line 310, in _query
conn.query(q)
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/pymysql/connections.py", line 548, in query
self._affected_rows = self._read_query_result(unbuffered=unbuffered)
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/pymysql/connections.py", line 775, in _read_query_result
result.read()
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/pymysql/connections.py", line 1156, in read
first_packet = self.connection._read_packet()
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/pymysql/connections.py", line 725, in _read_packet
packet.raise_for_error()
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/pymysql/protocol.py", line 221, in raise_for_error
err.raise_mysql_exception(self._data)
File "/var/www/framework_mc/framework_mc/lib/python3.8/site-packages/pymysql/err.py", line 143, in raise_mysql_exception
raise errorclass(errno, errval)
Exception Type: IntegrityError at /ticket/new-ticket/
Exception Value: (1062, "Duplicate entry '' for key 'ticket_ticket.ticket_ticket_codice_f619a2bb_uniq'")

您可以进行

while True:
try:
codice = 'MC-PR' + get_random_string(length=8, allowed_chars='0123456789')
form.codice = codice
form.save() 
break  # <- it breaks while loop only if there is no Integrity error
except IntegrityError:
pass  # <- in case of Integrity error it will generate a new code and try again

使用django pre_save信号进行设置编码:

from django.db.models.signals import pre_save
from django.dispatch import receiver
@receiver(pre_save)
def my_callback(sender, instance, *args, **kwargs):
instance.codice = 'MC-PR' + get_random_string(length=8, allowed_chars='0123456789')

最新更新