having used cakephp in the past, one thing (perhaps the only thing?) i liked about it was that it had a "create" and "update" timestamp capability that was lovely - simply put, when you first added an item, the "create" date was set (assuming you named it right - create_date, i think)
Anytime thereafter, if an update was performed, the "update" field was set to the current time.
Does django have this as well? If so, what/how do i name the fields to get it to pick them up?
It is not added to your model built-in in every table. You must add it as field to your model.
class Message(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
Message in this case your table's name.
Sure it has!
Check auto_now and auto_now_add in the doc
Related
Suppose I have a Django app backed by Postgres, and in that app I have model called Contact with a DateTimeField called last_updated. Suppose last_updated has auto_now set to True.
I know there are some circumstances in which last_updated will not get updated when a Contact record is updated:
Contact.objects.filter(xxx).update(yyy) will not update last_updated unless last_updated is included in yyy
Contact.objects.bulk_update(contacts_qs, [zzz]) will not update last_updated unless last_updated is in zzz
Are there other ways to update modify Contact objects (barring accessing the DB directly) where last_updated won't be updated?
From the docs auto_now:
DateField.auto_now
Automatically set the field to now every time the object is saved. Useful for “last-modified” timestamps. Note that the current date is always used; it’s not just a default value that you can override.
The field is only automatically updated when calling Model.save(). The field isn’t updated when making updates to other fields in other ways such as QuerySet.update(), though you can specify a custom value for the field in an update like that.
So unless you are doing an unmodified save directly from the model, it is possible the field will not be automatically saved. This is why I use a Postgres trigger/function combination that handles this in the database. Also to handle data updates coming from outside Django.
Not sure if this is a bug in Django, or it just doesn't support what I'm trying to do (or how i'm doing it).
A snippet of my model:
class UserProfile(models.Model):
user = models.OneToOneField(User, primary_key=True, related_name='profile'
login_hash = models.CharField(max_length=36, blank=True, null=True, default=uuid.uuid4())
...
As you see, i've set the default for login_hash to a call to uuid.uuid4()
works fine... however, multiple calls to the UserProfile (creating new users quickly, even seemingly a few minutes, but i've not an official time) will result in the same login_hash for multiple users.
It appears that django (i'm on 1.7.4) is caching the result of uuid4() for some period of time. not good for what i'm trying to do.
SOLUTION:
that i'm using. I've simply set an 'on insert' trigger on the database, so that when i insert a new record, the database generates the UUID, but only on inserts/new records.
Is there a way to do it within django so that i can keep it database agnostic?
works fine... however, multiple calls to the UserProfile (creating new users quickly, even seemingly a few minutes, but i've not an official time) will result in the same login_hash for multiple users.
As the code is currently written you're calling uuid.uuid4() at the point UserProfile is imported. It'll be called once and the resulting value will be the default for all new creations.
What you instead what to do is pass a callable as the default. Like so: default=uuid.uuid4.
Also, for CharField I'd strongly suggest not allowing NULL values as well as blank values. It's also not clear if you really do want to allow blank values for this field, but let's assume that you do. You should end up with this:
login_hash = models.CharField(max_length=36, blank=True, default=uuid.uuid4)
Is there a way to order result of a model queryset by update time of its instances? i.e. the instance that has been saved most recently comes first and so on.
You will need to add a timestamp field to your model. For example in my own code I add a date_updated field for this very purpose.
Your custom models don't have this by default so you have to add it.
last_edit = models.DateTimeField(auto_now_add=True)
You will have to update this in the save method (or another method) of your model.
import datetime
self.last_edit = datetime.datetime.now()
If you have a field on your model that tracks this update time (more information on this here), then yes, you can just use that in a normal ordering specification.
If you don't track updates on your model, no, that is not possible.
I have a Shops model and would like each shop to be able to login to my application. Following as best I can the guide at http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/ and various other googlings, I've got part of the way there, but I've run into a problem. When I try to login as a shop, I get the following error:
OperationalError at /login/
(1054, "Unknown column 'shops.user_ptr_id' in 'field list'")
Shops model:
class Shops(User):
shop_id = models.AutoField(primary_key=True)
shop_code = models.CharField(unique=True, max_length=5)
shop_type_fk = models.ForeignKey(ShopTypes,
null=True,
db_column='shop_type_id',
blank=True)
address_fk = models.ForeignKey(Addresses, db_column='address_id')
phone_number = models.CharField(max_length=30)
#email = models.EmailField(max_length=255, blank=True)
description = models.TextField(blank=True)
does_gift_aid = models.NullBooleanField(null=True, blank=True)
objects = UserManager()
class Meta:
db_table = u'shops'
I've sync'd the database, so surely it should have made the column user_ptr_id. Does anyone know where I'm going wrong?
"I've sync'd the database, so surely it should have made the column user_ptr_id."
What makes you think that? Especially in light of this clear statement in the docs for syncdb:
Syncdb will not alter existing tables
syncdb will only create tables for
models which have not yet been
installed. It will never issue ALTER
TABLE statements to match changes made
to a model class after installation.
Changes to model classes and database
schemas often involve some form of
ambiguity and, in those cases, Django
would have to guess at the correct
changes to make. There is a risk that
critical data would be lost in the
process.
If you have made changes to a model
and wish to alter the database tables
to match, use the sql command to
display the new SQL structure and
compare that to your existing table
schema to work out the changes.
It does sound like you had an existing shops table before changing it to inherit from User (as Daniel notes), and syncdb does not update the schema for existing tables.
You need to drop the table and then run syncdb, if possible. Otherwise you need to go into your database and add the user_ptr_id field manually, if you know how to do that. The definition should look something like this:
"user_ptr_id" integer NOT NULL UNIQUE REFERENCES "auth_user" ("id")
I have a model (and model form based on it) that has several time fields. I want these fields to be optional such that the user may leave some empty. My problem is that I continue to receive "Column 'mechreturn_tm' cannot be null" errors when I attempt to save an instance where one or more of these fields are blank. I've used the following approaches:
mechreturn_tm = models.TimeField(blank=True, null=False)
mechreturn_tm = models.TimeField(blank=True, null=True)
mechreturn_tm = models.TimeField()
none seem to work. what am I doing wrong?
Are you sure you still get the error using the second approach (both blank and null set to to True)?
Keep in mind that you'll need to recreate the DB table when you make this change since syncdb won't alter an existing table. That may be why you got the error even with the correct code.
Setting blank=True on a model field means that the field is allowed to be blank when validating a form with that field.
Setting null=True means that the model can be saved to the DB without any value at all for that field.
http://docs.djangoproject.com/en/dev/topics/db/models/#field-options