Django Model Field initialization issue

Hi!

I have a model called MyOrder.

class MyOrder(models.Model):
	"""Lorem ipsum"""

	created_at = models.DateField(auto_now_add=True)
	user = models.ForeignKey(User, ...)
	...
	order_number = models.IntegerField()

	class Meta:
		unique_together = [('created_at', 'order_number')]


	@property
	def global_order_number(self):
		return str(self.created_at) + str(self.order_number)

The point here is that global_order_number which must be unique.
And order_number should start from 1 every day.
I think initializing order_number can get what I need but I am not sure how I can make it start from 1 at the beginning of every day.
So the global_order_numbers should look like this

20210417-000001
20210417-000002
20210417-000003
...
20210417-000123
20210417-000124
...
(new day starts, order number starts from 1)
20210418-000001
20210418-000002
20210418-000003
...
20210418-000211
20210418-000212
...
(new day starts, order number starts from 1)
20210419-000001
20210419-000002

Do you have any idea?

First, keep in mind that in a production environment, you’re likely to have multiple instances of your application running in the course of each day. That means you’ll want to store your current counter somewhere external to your app (database, memcache, redis, etc). That also means that whichever storage you choose to use needs to provide a lock and an atomic “increment and return value” operation.

(You also need to identify the degree to which you want to ensure that there are no gaps in the numbers, if it’s truly required that there be none. Power-outages, system failures, network errors all introduce boundary conditions making it much more difficult to truly ensure a contiguous series of numbers are being applied.)

In this specific case, I’d approach it one of two ways, depending upon how many of these I expected to generate each day.

  1. Store the current date in a field associated with the value. On each request, check the current date to the stored date, and if the date has changed, change the date and reset the field value.

  2. Set up a periodic task to run at midnight, checking the date, and if necessary, resetting the date and counter. (The if is intended to prevent resetting it twice on the same date in case of a system failure / outage.)

What do you mean by associated with the value?
Could you please explain further on #1?
I think the date is fine with models.DateField and auto_now_add=True
Then we do not need to manipulate the date.
My concern is how to initialize the number and where to store it

You want to store today’s date somewhere you know is related to the counter’s value. For example, if you’re storing the counter in the database, you could store the date as another column in the database. If you’re using redis, you could store the date and counter as two keys within a redis hash. You want to store the date so you know when you need to reset the counter.

Yes, correct.
I am thinking of using redis for this.
so I can store both date and number and based on that compose the order_number field which I would like to use models.CharField.
And everytime, the order request comes in, we can get the last value, compose the order_number and update the date and number of cache.
If outage happens or timeout(24 hours), then we can get last created object from db and get date there.
If date is changed, this means new day has begun, if not, it means outage.
We can either continue the number from the one we get from db or start from 1 if the date is changed.
How does it sound? :slightly_smiling_face:

Yea, that ought to about cover it. Just make sure you properly use WATCH, MULTI, and EXEC when you’re updating the date and resetting the counter in redis.

Here the challenge is to handle simultaneous requests

Can you explain a bit more about how to use them in django?

It’s no different than in any other Python code using redis. That you’re likely running this in a view doesn’t change any of the fundamentals of working with redis.

MULTI
SET value
EXEC

I think this will work.
Should I use WATCH as well?

I see.
I should use WATCH to watch for changes of the value during transaction