2015-12-14

Auto loading user-defined models in Django shell

I would like the Django shell to auto-load all user-defined models on startup without the 
use of a third-party app. Below is that I did.

[00] # FILE .djangoshellrc
[01] # alias m='PYTHONSTARTUP="path/to/.djangoshellrc" python manage.py'
[02] 
[03] import sys
[04] 
[05] from django.apps import apps
[06] 
[07] def load_models():
[08]     try:
[09]         models = [m for m in apps.get_models() if not m.__module__.startswith('django')]
[10]         for model in sorted(models, key=lambda x: x.__name__):
[11]             name = model.__name__
[12]             globals()[name] = model
[13]             print("[+] imported %s" % name)
[14]     except:
[15]         print("[*] %s" % sys.exc_info()[0])
[16]         print("[*] %s" % sys.exc_info()[1])
[17] 
[18] load_models()

Line 00-01: To use this script, create a bash alias to start the Django shell, with 
this script specified in the PYTHONSTARTUP environ variable.  In other words, this 
script will be run on startup as long as the alias is used to start the Django shell.

Line 03-05: All the necessary imports.

Line 09: Ask Django to provide a list of all the app models, with the django built-in 
models filtered out.

Line 10: Iterate the models list after sorting them based on the model names.

Line 11-13: Add the models to the globals dict with the model name as the key,
effectively doing a "from <app>.models import <Model> in the Django shell."

Hope this script is useful to you.

2015-12-07

Comparing changes in a Django form

With the help of the Form.changed_data list, the Form.initial dict, and the Form.cleaned_data dict, Django makes it easy to compare changes in a form.
For example, we can override the form_valid method in an UpdateView to print the old and new values of all the changed fields as below:
def form_valid(self, form):
    for fieldname in form.changed_data:
        print(fieldname)
        print("old=%s" % form.initial[fieldname])
        print("new=%s" % form.cleaned_data[fieldname])
    return super().form_valid(form)

References:
Form.changed_data
Form.initial
Form.cleaned_data