Answer the question
In order to leave comments, you need to log in
Django IntegrityError on competing requests?
There is a model, it has a unique field
The model is presented in the admin panel
The problem is that if the database is loaded, then with a simultaneous request, the form passes validation and tries to save data in several streams, as a result, an IntegrityError is thrown into the console
This is clearly visible if at the moment put save points in sleep, or set break points in debug mode
Partially overcome the problem by wrapping the save block - super(ProductCardAdmin, self).save_model(request, obj, form, change) - into an atomic context manager, and wrapping it into try ... except and catch IntegrityError
Now, with requests, both work out and a redirect occurs to the page with the list of the model, but at the top in both cases it is written that the object was successfully saved, but it is necessary that in one case it was written that it was successful, and in others that it is impossible to save, because the object is already in the database
All this happens in the save_model(self, request, obj, form, change) method
In the handler I tried to do form.add_error('field_name', 'error_msg') and below del form.cleaned_data['field_name']
Doesn't help
How to win?
piece of code
def get_form(self, request, obj=None, **kwargs):
form = super(ProductCardAdmin, self)\
.get_form(request, obj, fields=forms.ALL_FIELDS, **kwargs)
if obj:
form.base_fields.update(obj.kind.get_preview_template_fields(obj))
try:
template = obj.kind.template
except Template.DoesNotExist:
return form
# TODO: Упростить как сделано в конфигураторе всю группу
# методов для получения этой формы
if template:
form.base_fields.update(template.get_fields(obj))
return form
def save_model(self, request, obj, form, change):
if obj:
obj.has_template_changed = False
if obj.author is None:
obj.author = request.user
is_checked = form.cleaned_data.get('is_checked', False)
if is_checked:
obj.date_checked = date.today()
obj.is_ready = True
if obj.is_ready:
try:
template = obj.kind.template
except Template.DoesNotExist:
obj.is_ready = False
super(ProductCardAdmin, self).save_model(request, obj, form, change)
obj.attributes.all().delete()
obj.preview_templates.clear()
for field_name, value in form.cleaned_data.iteritems():
# attributes save
if field_name.startswith('attrfield_'):
if value is None:
continue
attribute_pk = field_name.split('attrfield_')[1]
attribute = obj.attributes.create(options_id=attribute_pk)
attribute.value = value
attribute.save()
# preview template save
if field_name.startswith('preview_template_'):
if value is None:
continue
shopping_type = field_name.split('preview_template_')[1]
try:
preview_template = ProductCardPreviewTemplate.objects.get(
shopping_type=shopping_type,
pk=value
)
except ProductCardPreviewTemplate.DoesNotExist:
continue
obj.preview_templates.add(preview_template)
# проверка в обработчике сигнала есть, просто заботимся о клиенте
if obj.is_checked:
# не стоит обновлять "слепок"... только upload_preview
update_description_and_previews_signal.send(
sender=ProductCard,
codes=[obj.code],
do_update_description=False
)
if obj.kind and obj.kind.template:
productcard_change_signal.send(sender=ProductCard, instance=obj)
# Возвращаемся к списоку карточек
return HttpResponseRedirect(
reverse('admin:cards_productcard_changelist')
)
Answer the question
In order to leave comments, you need to log in
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question