Reputation: 145
I would like to have a unique id_order per company, and if already exist, i cannot save the order or form is not valid. In my example, each company save orders, Company A can save id_order 1 id_order 2 id_order 3 ... Company B can save id_order 10 id_order 20 id_order 30... what i want now is that company A cannot save two times id_order 3 or company B cannot save two times 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)
Forms:
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)
Upvotes: 1
Views: 193
Reputation: 477190
You can add a unique constraint on the couple company
and 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'
)
]
I would however not store the last_order
at the company model. This might be a problem since the order ids are not per se dispatched in order, for example it is possible that the last order id is 4
, whereas there is already a 5
.
For a company you can simply calculate the maximum value and increment this with one:
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
You also might want to consider replacing the DecimalField
with decimal_places=0
with a BigIntegerField
[Django-doc].
Upvotes: 1