В настоящее время в моем поле request_number модели ServiceRequest по умолчанию используется число шесть di git, сгенерированное функцией "number" (YY + 4 di git порядковый номер). Учитывая ожидаемое количество пользователей, потенциально создающих запросы одновременно, велика вероятность возникновения ошибки из-за дублирования номеров запросов. В случае моего проекта сообщение об ошибке гласит: «Запрос на обслуживание с этим номером запроса уже существует».
Как мне обработать эту ошибку, чтобы автоматически увеличить номер запроса на 1 до следующего уникального запроса номер найден, затем сохранить?
models.py
from django.db import models
from django.utils.timezone import now
from django.urls import reverse
import datetime
def number():
y2 = now().strftime('%y')
last_request = ServiceRequest.objects.filter(
request_number__startswith=y2
).order_by('-request_number').values_list('request_number', flat=True).first()
if last_request is None:
return f'{y2}0000'
else:
num = (int(last_request) + 1) % 10000
return f'{y2}{num:04d}'
class ServiceRequest(models.Model):
CATEGORY_CHOICES = (
(None, ''),
('aircraft_repair', 'Aircraft Repair'),
('backshop', 'Backshop'),
('documentation', 'Documentation'),
('other', 'Other')
)
PRIORITY_CHOICES = (
(None, ''),
('1', 'Level 1 - Critical'), # <24 hours
('2', 'Level 2 - Urgent'), # 1-2 days
('3', 'Level 3 - Standard'), # 3-4 days
('4', 'Level 4 - Low') # 5+ days
)
STATUS_CHOICES = (
('open_status', 'Open'),
('reopened_status', 'Reopened'),
('closed_status', 'Closed'),
('cancelled_status', 'Cancelled'),
('in_work_status', 'In Work')
)
timestamp = models.DateTimeField(
auto_now_add=True,
auto_now=False,
blank=True
)
updated = models.DateTimeField(auto_now=True)
request_number = models.CharField(
max_length=6,
db_index=True,
default=number,
unique=True,
blank=True
)
status = models.CharField(
max_length=20,
choices=STATUS_CHOICES,
default='open_status'
)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
email = models.EmailField()
contact = models.CharField(max_length=14)
category = models.CharField(
max_length=20,
choices=CATEGORY_CHOICES,
default=None
)
due_date = models.DateField()
aircraft = models.CharField(max_length=20)
NrcWorkOrder = models.CharField(
max_length=10,
verbose_name='Work Order',
blank=True
)
NrcZone = models.CharField(
max_length=10,
verbose_name='Zone',
blank=True
)
NrcItem = models.CharField(
max_length=10,
verbose_name='Item',
blank=True
)
EgWorkOrder = models.CharField(
max_length=10,
blank=True
)
EgZone = models.CharField(
max_length=10,
blank=True
)
EgItem = models.CharField(max_length=10, blank=True)
references = models.CharField(max_length=200)
description = models.TextField()
class File(models.Model):
files = models.FileField(
verbose_name="Attachments",
name="files",
upload_to="files/")
service_request = models.ForeignKey(
ServiceRequest,
on_delete=models.CASCADE
)
# TODO ASSOCIATE UPLOADED FILES TO THE REQUEST INSTANCE THAT IS BEING CREATED WHEN LOADING THE FILE
def __str__(self):
return str(self.files)
def get_absolute_url(self):
return reverse('file_list')
def delete(self, *args, **kwargs):
self.files.delete()
super().save(*args, **kwargs)
views.py
from django.shortcuts import render, redirect, reverse
from .forms import ServiceRequestForm, FileForm
from .models import ServiceRequest, File
import datetime
def esr_submit(request):
files = File.objects.all()
if request.user.is_authenticated:
initial_data = {'first_name': request.user.first_name,
'last_name': request.user.last_name,
'email': request.user.email,
'contact': request.user.phone,
}
request_form = ServiceRequestForm(initial=initial_data)
file_form = FileForm()
else:
request_form = ServiceRequestForm()
# request_form.save()
# request_form = ServiceRequestForm()
file_form = FileForm()
if request.method == 'POST':
if 'file_upload' in request.POST:
file_form = FileForm(request.POST, request.FILES)
if file_form.is_valid():
file_form.save()
if 'submit_request' in request.POST:
request_form = ServiceRequestForm(request.POST)
if request_form.is_valid():
request_form.save()
return render(
request,
'esr_submit/esr_submit.html',
{'request_form': request_form,
'file_form': file_form,
'files': files
}
)
forms.py
from django import forms
from .models import ServiceRequest, File
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Submit, Row, Column
class ServiceRequestForm(forms.ModelForm):
class Meta:
model = ServiceRequest
fields = [
'first_name',
'last_name',
'email',
'contact',
'category',
'due_date',
'aircraft',
'NrcWorkOrder',
'NrcZone',
'NrcItem',
'references',
'description',
'request_number', # TODO remove before switching to production mode - should be hidden
]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.layout = Layout(
Row(
Column('first_name', css_class='input-large'),
Column('last_name', css_class='input-large'),
),
Row(
Column('email', css_class='input-large'),
Column('contact', css_class='input-large'),
),
Row(
Column('category', css_class='input-large'),
Column('aircraft', css_class='input-large'),
Column('due_date', css_class='input-large'),
),
Row(
Column('NrcWorkOrder', css_class='input-large'),
Column('NrcZone', css_class='input-large'),
Column('NrcItem', css_class='input-large'),
),
Row(
Column('references', css_class='input-large'),
),
Row(
Column('description', css_class='input-large'),
),
Row(
Column('request_number', css_class='input-large'),
),
)
class FileForm(forms.ModelForm):
class Meta:
model = File
# widgets = {
# 'request_number': forms.HiddenInput(),
# }
fields = [
'files',
]
esr_submit.html
{% extends "main/base.html" %}
{% block title %}
Submit an ESR
{% endblock %}
{% load crispy_forms_tags %}
{% block content %}
<head>
</head>
<br>
<div class="container">
<div class="row justify-content-md-center mb-2">
<div class="col-sm-8 mb-4 shadow-lg p-3 bg-white rounded">
<div class="header mb-2">
<h3 class="header mb-0 text-center">New Engineering Service Request</h3>
{% if not request.user.is_authenticated %}
<div class="text-center">
<small class="text-muted"><strong>Want to speed things up? </strong><a href="/login/?next=/esr_submit/"> Log In |</a></small>
<small class="text-muted"><a href="/register/?next=/esr_submit/">Create an account </a></small>
</div>
{% endif %}
</div>
<form method="post" enctype="multipart/form-data" id="request_form">
<div class="col">
{% csrf_token %}
{% crispy request_form %}
<span class="helper-text"></span>
</div>
</form>
<form method="post" enctype="multipart/form-data" id="file_upload">
<div class="col">
{% csrf_token %}
{{ file_form|crispy }}
</div>
</form>
<table class="table table-borderless" style="margin-top: 10px;">
<tbody>
{% for file in files %}
{% if file.files %}
<tr>
<td class="w-50">
<a href="{{ file.files.url }}" target="_blank">{{ file.files }}</a>
</td>
<td>
<form method="post" action="{% url 'delete_file' file.pk %}">
{% csrf_token %}
<button type=submit class="btn btn-danger btn-sm">DELETE</button>
</form>
</td>
</tr>
{% else %}
{% endif %}
{% endfor %}
</tbody>
</table>
<div class="pl-2">
<button type="submit" name="file_upload" value="file_upload" form="file_upload" class="btn btn-primary">Upload File</button>
<button type="submit" name="submit_request" value="submit_request" class="btn btn-primary" form="request_form">Submit Request</button>
<button type="submit" name="save_draft" value="save_draft" id="save_draft" class="btn btn-primary" form="request_form">Save Draft</button>
</div>
</div>
</div>
</div>
{% endblock content%}