Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python

How to autofill a field in the database?

I'm new to django, but coming from php I think its the greatest thing ever.

I have a model for Invoices ...

from django.conf import settings
from django.db import models
from django.core.urlresolvers import reverse
#from django.contrib.auth.models import User

class Invoice(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    their_company = models.CharField(max_length=255)
    invoice_number = models.CharField(max_length=50, default='')
    bill_to = models.CharField(max_length=255, default='')
    created_by = models.ForeignKey(settings.AUTH_USER_MODEL)

    class Meta:
        ordering = ['invoice_number', ]

    def __str__(self):
        return self.invoice_number

    def get_absolute_url(self):
        return reverse("accounting:invoices:detail", kwargs={"pk": self.pk})

right now the user has to put in the invoice number themselves. I want to not give the user that option though - I'd like to autofill that field in the database with a concatenation of the 2 digit year (17) plus 2 digit month (07) plus 2 digit day (24) and then a 2 digit auto increment for every invoice created on that specific date so the first invoice created today would be 17072401 and the second would be 17072402, etc. I'm guessing I need a field just for the date and another for the iteration of each invoice.

Can anyone give me some direction on this? First I'm not sure how to autofill a field in the database without getting the input from the user, and I'm also not sure how I would do the concatenation with the right numbers. Thanks for your help

James J. McCombie
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
James J. McCombie
Python Web Development Techdegree Graduate 21,199 Points

Hello,

I had this challenge recently. I believe that there can only be one auto increment field on a django model, and that is the pk/id field. The work around I found was to either use a model manager or override the save method. I went with the manager approach.

So you would write a manager and have a method in it that has logic to figure out the current day, and query the database for other entries on that day and add the increment if needed, that can be returned to use to populate a field in an instance your are saving.

Overriding the save method can also work I think, again logic needed to work out the day and increment then save the field, and call the save() method of the parent class.

1 Answer

Thanks! I dont think I've come across model managers and overriding the save function in the videos on treehouse. How did you learn about this? Thanks again

James J. McCombie
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
James J. McCombie
Python Web Development Techdegree Graduate 21,199 Points

Hello,

Managers are mentioned at some point in the courses on Django, I really can't remember where, not in the context of doing what you want to do though. Overriding the save method I think I came across that googling how to auto increment fields, but I think again it's mentioned in the courses at some point in a different context, I might be wrong...

There are better ways to do it, but as part of the custom manager I was using i defined a method to generate the next contract number. Inside a custom manager class, you can get at the model which is being managed with self. So the function performed a database query and looked up the last contract number, and returned the next one. You could search the database on the current date basis, find all entries and then work out what to return, the method returns the correct* number. you would call it like model.custom_,manager_name.method_name() ( just like model.objects.method() ). You can make the call somewhere in the business logic for you views where model instances are being saved, or use it to populate the invoice number field on a Model Form, etc etc.

I am not a teacher, so apologies if that does not make any sense, is rambling etc. I would recommend having a read of the docs for Model Managers and Save method, to make that clearer.

*In my own work, I am concerned about concurrency issues, depending on usage, there may be an occasion where the method is called, an number returned and before save the database is hit again, the same number is generated, then one is saved and then the next is saved. Since the field should be unique this is gonna cause an issue. I think a work around would be to include some logic for dealing with a Database Integrity error, perhaps actually in the save method!