Got it - thank you! This community is great :) On Tuesday, January 13, 2015 at 11:31:19 PM UTC-8, Jani Tiainen wrote: > > Because sequence number was running number per "tenant" (in my case it > was invoice type) that started from zero (0) at the beginning of the > every year. > > You could use max+1 as well but you should be aware that there is a > slim chance that there is race condition and you may end up having two > entities with the same max number - that though would raise error when > trying to save into database. > > By having explicitly pessimistic locking (select_for_update) for a row > with tenant + sequence value you can guarantee that no other request > can change the value while you're reading it. > > To make that easier you can create custom manager that can retrieve > updated sequence values automagically, so your call would look like > something like: > > Tenant.sequence.get_value(tenant, sequence) > > > On Tue, 13 Jan 2015 06:37:21 -0800 (PST) > Matt Cooper <[email protected] <javascript:>> wrote: > > > Thanks Jani, good to hear someone has gone down this road before. > > Since you did it in code, is there a reason you kept a sequence value > > on Tenant rather than using > > Widget.objects.aggregate(Max(Widget.sequence_value)) ? I ask because > > for my app, Widget is actually just one of several cases where I need > > this pattern. If I could keep all the book-keeping on the model with > > the constraint, that seems cleaner to me. But, of course, I'm not > > willing to pay a huge performance or corruption penalty just for > > vague ideological purity :) > > > > Thanks again! > > ~matt > > > > On Tuesday, January 13, 2015 at 5:07:21 AM UTC-8, Jani Tiainen wrote: > > > > > > I've done something similiar. > > > > > > Only way to do that is that you need to upkeep that tenant > > > sequence_id manually, > > > > > > So doing something like: > > > > > > class Tenant(models.Model): > > > name = models.CharField(max_length=50) > > > sequence_value = models.IntegerField() > > > > > > and in a code: > > > > > > tenant = Tenant.object.get(id=tenant_id).select_for_update() # > > > Pessimistic locking > > > tenant.sequence_value = tenant.sequence_value + 1 > > > tenant.save() > > > > > > widget = Widget(owner=tenant,sequence_value=tenant.sequence_value) > > > widget.save() > > > > > > That should do the trick. Another option could be using table > > > triggers to automate > > > that within a database table trigger(s). > > > > > > On Mon, 12 Jan 2015 21:26:54 -0800 (PST) > > > Matt Cooper <[email protected] <javascript:>> wrote: > > > > > > > I'm building a multi-tenant application with a data model that > > > simplifies > > > > to: > > > > > > > > class Tenant(models.Model): > > > > name = models.CharField(max_length=50) > > > > > > > > class Widget(models.Model): > > > > owner = models.ForeignKey(Tenant) > > > > sequence_id = <question here> > > > > > > > > > > > > I want Widget.sequence_id to work like an AutoField (that is, > > > automatically > > > > give me something unique and generally incrementing by 1) but > > > > scoped to > > > a > > > > single Widget.owner. So for instance, when Tenant A creates 3 > > > > widgets, > > > they > > > > would get sequence_ids 1, 2, and 3. Then Tenant B comes along and > > > creates 2 > > > > widgets; those widgets get sequence_ids 1 and 2. The tenant/user > > > > gets no control over the number, but it's something she'll see in > > > > the UI. AutoNumber is out because from the perspective of a > > > > single tenant, they should have sequential widget IDs. > > > > GUIDs/UUIDs are out because it needs > > > to > > > > be human-readable. > > > > > > > > I looked through docs on AutoField and unique_together. I turned > > > > StackOverflow upside down and only found this > > > > < > http://stackoverflow.com/questions/18072586/django-autofield-increment>, > > > > > > > which isn't quite what I want. I didn't see anything on > > > djangopackages.com > > > > that would solve my problem, though I could have missed it. > > > > > > > > Basically, has anyone done something like this before and have a > > > suggested > > > > pattern? > > > > > > > > Thanks! > > > > ~matt > > > > > > > > -- > > > > You received this message because you are subscribed to the > > > > Google > > > Groups "Django users" group. > > > > To unsubscribe from this group and stop receiving emails from it, > > > > send > > > an email to [email protected] <javascript:>. > > > > To post to this group, send email to [email protected] > > > <javascript:>. > > > > Visit this group at http://groups.google.com/group/django-users. > > > > To view this discussion on the web visit > > > > https://groups.google.com/d/msgid/django-users/37fd32e7-28dd-4c10-8451-b0d705a3e52e%40googlegroups.com. > > > > > > > > > For more options, visit https://groups.google.com/d/optout. > > > > > > > -- > > You received this message because you are subscribed to the Google > > Groups "Django users" group. To unsubscribe from this group and stop > > receiving emails from it, send an email to > > [email protected] <javascript:>. To post to this group, > > send email to [email protected] <javascript:>. Visit this > group at > > http://groups.google.com/group/django-users. To view this discussion > > on the web visit > > > https://groups.google.com/d/msgid/django-users/1ab4b16d-df97-4412-9622-22cf3b344f80%40googlegroups.com. > > > > For more options, visit https://groups.google.com/d/optout. >
-- You received this message because you are subscribed to the Google Groups "Django users" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/django-users. To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/ae68cc49-147e-45d3-887c-071351416586%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.

