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.
Related
I'm new with django rest framework and I have 4 fields in my database table (id, chip, creation date, deletion date), on the front-end there is a button to delete the chip, so far so good, but on the page I have, in addition to the abject (chip) to be deleted, it has 2 more fields (creation date and deletion date) when deleting the object, the deletion date field must have the time of deletion and not simply be empty. How to make this change when doing the deletion?`
at the moment I just created the model and migrated it to the database.
I haven't started yet, I just created a route to list (GET) all the data in the table.
I ask for help to do the Delete/Update or whatever it may be.
my model
class Gateway(models.Model):
id = models.AutoField( primary_key=True)
gateway_chip = models.CharField(max_length=20, unique=True)
creation_date = models.DateTimeField()
deletion_date = models.DateTimeField()
class Meta:
db_table = 'GATEWAY'
You wouldn't use both PUT and DELETE together, you can only specify one as the HTTP method. If you have a deletion_date field then presumably you don't want to actually delete the model object, otherwise why record the date? In that case, you can 'soft delete' the object - it still exists but you can filter it away so that users see it as having been deleted but system administrators can still access it.
You can still use the DELETE method despite this essentially just being an update as the process is still essentially a deletion. There is also no strict requirement that the DELETE protocol actually deletes anything.
So I have this as a base model:
class BaseModel(models.Model):
"""
base class for all models enforcing a UUID
"""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
class Meta:
abstract = True
Programmatically, from my Django classes, when I derive from this class and call .save() a new object it's created with a fresh UUID.
However, when I look at the database schema (latest Postgres) with a tool like DataGrip, I find that the column id has nothing in the default definition - Why hasn't the default=uuid.uuid4 translate over to the database schema somehow?
When I edit the database with DataGrip, I have to insert a new UUID manually for records I put in manually to be able to save correctly.
Is there a way around this? To have the UUID automatically generate when I add rows from a 3rd party database client?
According to django docs here
Universally unique identifiers are a good alternative to AutoField for
primary_key. The database will not generate the UUID for you, so it is
recommended to use default:
It means, unlike AutoField default for UUIDField is not implemented (or used if your databese implements this kind of functionality) on database level. It is handled on application level. That's why you have to pass default value (uuid.uuid4). whenever a record is inserted, uuid.uuid4 function is called to generate a uuid and this value is inserted in database. If you are doing direct insertions, you have to handle it yourself.
However if you set default value for id column by running a direct query on db like
ALTER TABLE <TABLE_NAME> ALTER COLUMN id SET DEFAULT uuid_generate_v4();
Django won't complain about it. And it will work fine from outside django app.
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'm working on an application where we have to review model changes before accepting them.
For this, when a user edits one of the company model objects in the app frontend, the form's initial data is filled with data from the original object and then stored into a new object that is flagged using the origin_company field (which is a foreign key to the previous version of the object).
So basically when someone edits a company, a new, inactive company is created.
To apply the changes, I want to copy all data from the changed company to the original company. (I'm doing this with custom django-admin actions.) The easiest way would probably be to start a transaction, delete the original company and change the primary key of the changed company to match the original company. But by doing that, the changed company is not UPDATEd, it is copied. And related database entries (FKs) are not updated either.
Is there an easy way to copy or move all data (including FK relations) from one model instance to another one? Or is my entire way of solving this problem messed up?
Here's the model definition:
class Company(models.Model):
company_name = models.CharField(max_length=150)
...
origin_company = models.ForeignKey('self', related_name=u'CompanyEdits',
null=True, blank=True, default=None)
Try the following:
# get the company instance's data as a dict
data = company_instance.__dict__.copy()
# remove the `id` and `origin_company` keys. don't need these
del data['id']
del data['origin_company_id']
# update the origin company instance
Company.objects.filter(id=company_instance.origin_company.id).update(**data)
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