Is there any Django-supported way to define a starting value for business sequence fields (e.g. order numbers)?

Hi everyone :waving_hand:

I understand that Django intentionally does not provide a start option for AutoField / BigAutoField, since primary key generation is handled by the database.

My question is slightly different and related to business identifiers (for example order_number, invoice_number, etc.), not primary keys.

Is there any Django-supported or recommended pattern for defining an initial offset (e.g. starting from 9000) for such fields, while keeping things:

  • database-agnostic

  • concurrency-safe

  • migration-safe

I’m aware of database sequences and manual logic, but I wanted to check first if Django already has (or intentionally avoids) any abstraction or pattern for this use case.

Thanks in advance for any guidance or design insight :slightly_smiling_face:

There are a couple of different ways to handle this type of situation that satisfy your constraints, depending upon your precise requirements.

However, while Django can support these, Django itself most likely does not provide them - it’s code you will have to write.

If you provide more details about exactly what it is you’re looking to achieve, including some samples of the different variety of results you need to get, we may be able to provide you with some ideas.

Thank you for the response,

Actually i have faced such an issue of writing the logic manually with different ways, mainly while saving a modal . SO i write the logic inside the modal save function .

But in an application somany where we need this type of feature. So that time i think why don’t django not providing this as inbuilt feature.

So what you think about it .Having or building such feature is good or not . Or it vialate the django philosophy

As a third-party package, sure. But the requirements and mechanics for doing things like this is so varied that I doubt you could come up with one solution that will work for more than a minority of cases.

But it’s tough to address this in the abstract. This is one of those issues that really needs to be addressed in the context of a specific requirement.

If you’re using postgres, it’s possible to write a sql migration that does resets the identity’s start value. Based on this post from Adam Johnson, Migrate PostgreSQL IDs from serial to identity after upgrading to Django 4.1 - Adam Johnson, the sql should roughly be:

# Change column to identity
cursor.execute(
     f"""\
     ALTER TABLE {qn(table_name)}
       ALTER {qn(column_name)}
         ADD GENERATED BY DEFAULT AS IDENTITY (RESTART %s)
     """,
     (starting_value,),
)

Now you’d need to port it to a RunSQL and potentially handle the case of it having a value that’s greater than starting_value.

I’d be interested in a library that provides extra migration operations for me to use. The more tooling we can use to surface PostgeSQL and database goodness in Django the better.

Though I suspect this would need to start as a third party package and grow outwards. Treating it like django-extensions is probably best. We’ve pulled a few features in from there once we realized how helpful they are to everyone.

Thank you for the clarification. That makes sense.
I understand now why Django doesn’t include this in core, since business sequence requirements can vary a lot between applications and databases. Handling it via database features or a third-party package seems more appropriate than a one-size-fits-all solution.

I appreciate the insights shared here.

I’d suggest checking out Aymeric Augustin’s django-sequences:

It’s battle-tested and does the hard things here.

1 Like