#django #django-models #django-views #django-forms
#django #django-модели #django-просмотры #django-forms
Вопрос:
Я хотел бы иметь уникальный id_order для каждой компании, и если он уже существует, я не могу сохранить заказ или форма недействительна. В моем примере каждая компания сохраняет заказы, компания A может сохранять id_order 1 id_order 2 id_order 3 … Компания B может сохранить id_order 10 id_order 20 id_order 30… теперь я хочу, чтобы компания A не могла сохранить два раза id_order 3 или компания B не может сохранить два раза id_order 20.
class Company(models.Model):
name = models.CharField(max_length=240)
last_order = models.DecimalField(max_digits=20, decimal_places=0)
class Order(models.Model):
company = models.ForeignKey('Company', on_delete=models.CASCADE)
id_order = models.DecimalField(max_digits=20, decimal_places=0)
def save(self, *args, **kwargs):
created = not self.pk
super().save(*args, **kwargs)
if created:
Company.objects
.filter(pk=self.company_id)
.update(last_order=self.id_order)
Формы:
class OrderForm(ModelForm):
class Meta:
model = Order
def __init__(self, company , *args, **kwargs):
super(OrderForm, self).__init__(*args, **kwargs)
self.fields['company'] = forms.ModelChoiceField(queryset=Company.objects.filter(name=company), initial = company)
try:
code = company.last_order 1
self.fields["id_order"].initial = code
except Exception as e:
print(e)
Ответ №1:
Вы можете добавить уникальное ограничение для пары company
и id_order
:
class Order(models.Model):
company = models.ForeignKey('Company', on_delete=models.CASCADE)
id_order = models.IntegerField(max_digits=20, decimal_places=0)
# …
class Meta:
constraints = [
models.UniqueConstraint(
fields=['company', 'id_order'],
name='unique_per_company'
)
]
Однако я бы не стал хранить модель last_order
at the company. Это может быть проблемой, поскольку идентификаторы заказов сами по себе не отправляются по порядку, например, возможно, что последний идентификатор заказа есть 4
, тогда как уже есть 5
.
Для компании вы можете просто вычислить максимальное значение и увеличить его на единицу:
from django.db.models import Max
class OrderForm(ModelForm):
class Meta:
model = Order
def __init__(self, company , *args, **kwargs):
super(OrderForm, self).__init__(*args, **kwargs)
self.fields['company'] = forms.ModelChoiceField(queryset=Company.objects.filter(pk=company.pk), initial=company)
code = (company.order_set.aggregate(
max_id=Max('id_order')
)['max_id'] or 0) 1
self.fields["id_order"].initial = code
Вы также можете рассмотреть DecimalField
возможность замены decimal_places=0
with на BigIntegerField
[Django-doc].
Комментарии:
1. отлично ! большое спасибо. пожалуйста, есть ли какое-либо решение в случае уже существующего сообщения об ошибке, чтобы показывать только уже существующее сообщение об ошибке или поле вместо желтой страницы ошибок со значением исключения: заказ не может быть создан, поскольку данные не были проверены.