Django Models - Table and Table status - how to model?

I need some advice...

In my django app, I've got models: Order and Order status:

class OrderStatus(models.Model): 
    status = models.CharField(max_length=20, verbose_name="Status")
  
class Order(models.Model): 
    orderNo = models.CharField(max_length=20, verbose_name="Order", unique=True)
    orderStatus = models.ForeignKey(OrderStatus, on_delete=models.PROTECT, verbose_name="Status"  ) 

There are 3 statuses..: New, In progress, Finished...

In my views, I frequently use a code like: (for example to create Order)

orderx = Order() 
orderStatus1 = OrderStatus.objects.get(pk=1)   # <- the problem is here...
orderx.orderStatus=orderStatus1
orderx.orderNo=i
orderx.save()

The problem, I've got is the one:

  1. I should't get Status object by char content (eg. "New" - because it can change, be in different language etc, so I should't filter it like:
    orderStatus1 = OrderStatus.objects.get(status="New")
  2. I also shouldn't get it by id like now: orderStatus1 = OrderStatus.objects.get(pk=1) because there is no warranty, that it will be the same ID while placing in other database, etc..

So how should it be modelled, so I can take STATUS_NEW somehow?

You can add a "flag" is_initial to the OrderStatus that is guaranteed to only be applicable to one record by using a UniqueConstraint [Django-doc]:

from django.db.models import Q


class OrderStatus(models.Model):
    status = models.CharField(max_length=20, unique=True, verbose_name='Status')
    is_initial = models.BooleanField(db_index=True)

    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=('is_initial',),
                condition=Q(is_initial=True),
                name='one_initial_status',
            )
        ]

then you create an order with:

orderx = Order.objects.create(
    orderStatus=OrderStatus.objects.get(is_initial=True), orderNo=i
)

We can not guarantee that there is at least one such record. In the case we can not find one, we could use NULL/None instead.

Back to Top