views:

272

answers:

2

I have an app that lets people create tickets, and each Account owner using my app can create tickets.

Firstly, should it be unique per account do you think? Or, should it be completely unique?

Like this:

class Ticket(models.Model):
    """
    An ticket created by an Account holder.
    """
    account = models.OneToOneField('Account')
    number = models.CharField(max_length=20, verbose_name='Ticket Number')

    class Meta:
        unique_together = (('account', 'number'),)

or this, respectively:

class Ticket(models.Model):
    """
    An ticket created by an Account holder.
    """
    account = models.OneToOneField('Account')
    number = models.CharField(unique=True, max_length=20, verbose_name='Ticket Number')

Then, of course I want the order numbers to represent the account, so possibly a sample order number for an account that has the id: "chris" could be "chris-41984" or something like that. Would you create a model method for this, or...?

+5  A: 

If users can create more than one ticket, then a one-to-one field is not appropriate. Secondly, the ticket number is purely arbitrary, right? In other words, it only needs to be unique (I don't see any reason why it should be unique per user from what you have said so far), so you might as well just use the primary key, unless you're planning on integrating with some other data store.

So you can simply say:

class Ticket(models.Model):
    account = models.ForiegnKey(Account)

    # "ticket number" is just ticket.id.
    # if you don't like that, then say:
    #number = models.CharField(primary_key=True)

Note that if you uncomment the number definition, you'll need to specify it when you create the model instance - primary keys cannot be None. Alternately, override the save method to auto-generate the ticket number field based on your requirements.

Daniel
Daniel is absolutely correct: unless you have a really compelling reason to do it some other way, just use the Ticket.id and let it auto increment. This is one of those situations where getting clever just gets you into trouble.
Peter Rowell
I suppose completely unique would be ok. If you were a client using my system though, would you expect to have your own series of ticket numbers starting with like "FOOACCOUNT_0001", or would you be ok if your first ticket came through as "5168481". I hope it is OK for the latter because I don't want some tricky system.
orokusaki
A: 

Here is my solution (it works perfectly minus IntegrityError handling which will take place in the view (in the case of two tickets in one account at the exact same time)):

class Ticket(models.Model):
    account = models.ForeignKey(Account)
    number = models.PositiveIntegerField(blank=True)

    class Meta:
        unique_together = (('account', 'number'),)  # Just in case

    # Rather than use a CharField for number and include the account identifier 
    # (letters) and deal with incrementing the number through regex (which would be 
    # verbose and inefficient), I've decided to just format the __unicode__ to display 
    # ticket numbers as "fooaccount-12345". I can use regex to parse the ticket number
    # when somebody looks up a ticket by that "fooaccount-12345" style, and it'll be
    # much less costly than each one going in that way.

    def __unicode__(self):
        return 'Order: {0}-{1}'.format(self.account.identifier, self.number)

    def save(self, force_insert=False, force_update=False):
        if len(Order.objects.filter(account=self.account)):
            top = Order.objects.filter(account=self.account).order_by('-number')[0]
            self.number = top.number + 1
        else:
            self.number = 1
        super(Order, self).save(force_insert, force_update)
orokusaki
Your save() function is going to increment the `number` field every time the instance is re-saved.
Daniel