I'm building a Django app that will work against a pre-existing PostgreSQL 
database.  Every user data table in my DB has an auditing column called 
last_updated_by.  The requirement I need to meet is that every time an 
UPDATE is run against a table, that column is automatically set to the id 
of the logged-in user.

By "automatically", I mean that this is done without any effort (or choice) 
on the part of the Django developer who writes an UPDATE (either as a SQL 
query or as an update on a Django object representing a row of that table) 
on a particular user data table.

For example (from https://docs.djangoproject.com/en/1.7/topics/db/queries/), 
the declarer of the Blog class, which corresponds to the blog table, can 
declare the class as:

class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

and a developer can write an update as:

>>> b5.name = 'New name'>>> b5.save()

Neither the declarer or the developer gave a thought to the last_updated_by 
column.  But when logged-in user 12345 causes this code to execute, the 
blog.last_updated_by column of that row will be set to 12345.

The nub of this problem is that when the database receives an UPDATE query, 
that query does not identify the Django end user that caused the query to 
be submitted.  The DB contains a list of the users (auth_user), and my DB 
also contains a list of the currently active user sessions (and the 
logged-in user of each session).  But multiple users can be logged in at 
once, and there is no way for the DB to deduce which of them issued this 
particular update.  The fact that this update came from user 12345 is known 
only within the Django app.  

So the problem is:  How to get this info from the app to the database, 
without requiring the developer to put this bit of housekeeping explicitly 
into every update?

Three possibilities have occurred to me:

1. A decade ago, when I was using the Zope framework, I found the Zope 
module (called a database connector) that actually formulates the SQL query 
strings en route from Zope apps to the DB.  I wrote a routine that inserts 
"last_updated_by = <the Zope function that returns the user id>" into the 
SET clause of each UPDATE query, and called this routine from the Zope 
database connector code.  This worked.  But it's an ugly hack and, worse, 
involves tinkering with the framework's DNA, so it would not have survived 
the next version of the database connector module.

2. Could this be done by defining last_updated_by in an abstract base 
class, as in https://docs.djangoproject.com/en/1.7/topics/db/models/, that 
includes an update method that automatically assigns the user id to 
last_update_by for each update?

3. Or could it be done with a modified Manager, with a modified QuerySet (
https://docs.djangoproject.com/en/1.7/topics/db/managers/)?
Not sure if this is relevant, but let me add that in the PostgreSQL 
database, the last_updated_by column is in all user data tables because 
their CREATE TABLE definitions all include an "INHERITS FROM when_and_who" 
clause, where when_and_who is the table that actually contains the 
last_updated_by column.  I'm not sure if Django's inspectdb utility makes 
any use of INHERITS FROM.

Thanks in advance for any suggestions you have for meeting this requirement!

~ Ken

-- 
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 django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
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/e81651b5-3363-4b86-83b5-dd72d8a75196%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to