[TOC]
#Django Tips
###Upgrade Django To upgrade django, first uninstall
pip uninstall Django
pip-3.3 uninstall Django
Then instal Django
pip-3.3 install Django ==1.6b
pip install git+https://github.com/django/django.git@1.6b1
To check what’s installed
pip-3.3 freeze
>Django==1.5.1
>South==0.8.1
>distribute==0.6.34
###To install SQLITE 3
sudo apt-get install sqlite3 libsqlite3-dev
- To login:
sqlite3
- To show all table in django with fields:
.schema
- To show just tables:
.tables
###Using South
####First time use for new database create your model run your initial migration
./manage.py schemamigration southtut --initial
apply your migration
./manage.py migrate southtut
####Convert an app to use South:
*Edit your settings.py and put south
into INSTALLED_APPS
*Run ./manage.py syncdb
to load the South
table into the database. Note that syncdb looks different now - South modifies it.
*Run ./manage.py convert_to_south myapp
- South
will automatically make and pretend to apply your first migration.
####Changing the model After any database change, first, make the new migration, using the –auto feature. First, make the new migration, using the –auto feature:
./manage.py schemamigration southtut --auto
Then apply the migration
$ ./manage.py migrate southtut
multi-tenant database achitechture (using django ensuring data isolation
yinka@penguin:~$ heroku login
Enter your Heroku credentials.
Email: adeyinka.adeyeye@gmail.com
Password (typing will be hidden):
Could not find an existing public key.
Would you like to generate one? [Yn] y
Generating new SSH public key.
Uploading SSH public key /home/yinka/.ssh/id_rsa.pub... done
Authentication successful.
yinka@penguin:~$
##Build python from source http://goo.gl/RuKhi
- dowload python version
- untar
- cd to folder version, run
./configure
# with these options--prefix=/home/<user>/.localpython
- --with-ssl
- –with-zlib=/usr/include
- download zlib h first with:
sudo apt-get install zlib1g-dev
, # on others it might just be:zlib-dev
orzlib-devel
- OR look at your setup files
./Python2.5/Modules/Setup
and uncomment the line starting withzlib zlibmodule.c …
before you run configure and make
- make
- make install
You can check what configuration options are available with ./configure --help
and see what your system python was compiled with by doing:
python -c "import sysconfig; print sysconfig.get_config_var('CONFIG_ARGS')"
###Pip for Python 3.2 http://goo.gl/z6zH3o
curl -O https://raw.github.com/pypa/pip/master/contrib/get-pip.py
sudo python3.2 get-pip.py
###Postgress Needed dependencies globally
sudo apt-get install postgresql
sudo apt-get install libpq-dev
sudo apt-get install postgresql-server-dev-9.1
sudo apt-get install python-dev
sudo apt-get install python3.3-dev #for python3
Postgress automatically creates a linux user called postgres
.
Set the password using:
sudo passwd postgres
and enter in the password twice.
To create a django user named django_login
for the db, enter:
sudo -u postgres createuser -P django_login
su postgress to switch
enter password
, enter db name like psql
\q to quit
\l to list databases
edit pg hba conf
sudo gedit /etc/postgresql/9.1/main/pg_hba.conf
start server with
sudo /etc/init.d/postgresql start
##How to read Django docs http://goo.gl/ryxq1
-
Getting Started - Introductory http://goo.gl/wIWJA/ The introductory material is designed for people new to Django – or to Web development in general. It doesn’t cover anything in depth, but instead gives a high-level overview of how developing in Django feels.
-
Topic Guides - Using Django http://goo.gl/KYptG Introductions to all the key parts of Django you’ll need to know. The topic guides dive deep into individual parts of Django. There are complete guides to Django’s model system, template engine, forms framework, and much more. This is probably where you’ll want to spend most of your time; if you work your way through these guides you should come out knowing pretty much everything there is to know about Django.
-
How-to guides http://goo.gl/45vUV Web development is often broad, not deep – problems span many domains. We’ve written a set of how-to guides that answer common How do I ...? questions. Here you’ll find information about generating PDFs with Django, writing custom template tags, and more.
-
Django FAQ http://goo.gl/Eqd45 Answers to really common questions can also be found in the FAQ.
-
Django api reference http://goo.gl/YiFGE The guides and how-to's dont cover every single class, function, and method available in Django – that would be overwhelming when you're trying to learn. Instead, details about individual classes, functions, methods, and modules are kept in the reference. This is where you'll turn to find the details of a particular function or whathaveyou.
-
Release notes http://goo.gl/XOAlI
-
Django internals http://goo.gl/o9mtu
-
Meta-documentation and miscellany http://goo.gl/ObPWQ
-
Django documentation contents http://goo.gl/7BpBp
-
Index http://goo.gl/lM6Fw
-
Python Module Index http://goo.gl/hAJE0
-
Search page http://goo.gl/0qyQU
###Django video tutorials
- Youtube Mike Hibbert http://goo.gl/QY3ra
- Building a Cloud Service with Python http://goo.gl/Y9FAY
- Django and Deployment http://goo.gl/tIi9H
- Django in Depth http://goo.gl/bVrIu
##Auto-populated fields
Published November 2, 2006. - James Bennett http://www.b-list.org/weblog/2006/nov/02/django-tips-auto-populated-fields/
How do you set up a model with one or more fields that never show up in add/edit forms, and get automatically populated with some specific value?
###Alternative to auto_now
& auto_now_add
Let’s say you’re writing a to-do list application, and you want to have fields on the list model to store the date it was created and the time it was last updated. The model might look something like this:
class TodoList(models.Model):
title = models.CharField(maxlength=100)
created = models.DateField()
updated = models.DateTimeField()
Now, in an ideal world you’d never publicly display the created
and updated
fields in a form; you’d just have them filled in automatically with the right values. So let’s make that happen by editing the model slightly:
import datetime
class TodoList(models.Model):
title = models.CharField(maxlength=100)
created = models.DateField(editable=False)
updated = models.DateTimeField(editable=False)
def save(self):
if not self.id:
self.created = datetime.date.today()
self.updated = datetime.datetime.today()
super(TodoList, self).save()
OR
import datetime
class User(models.Model):
created = models.DateTimeField(editable=False)
modified = models.DateTimeField()
def save(self, *args, **kwargs):
''' On save, update timestamps '''
if not self.id:
self.created = datetime.datetime.today()
self.modified = datetime.datetime.today()
return super(User, self).save(*args, **kwargs)
There are two changes that stand out here:
The created
and updated
fields now have editable=False
. This means that they will never show up in an automatic manipulator or in the admin. They’re still required, they just won’t be displayed anywhere.
There’s now a custom save
method on the model which does the actual work. The first time a new to-do list is saved, it won’t have an id because there’s no row for it in the database yet. So the if not self.id
check tells us that the to-do list is being saved for the first time, and we drop in a single line which fills the current date into the created
field. We also want the updated
field to be updated on every save, so we add a line which sets that to the current date and time. Then the super
call saves the list.
It really is that easy, and it works for a lot of field types — just give the field editable=False
and fill it in with a custom save
method. If the field is only supposed to be filled in for the first save, use the if not self.id
trick to accomplish that. The only thing that will vary is how you fill in the field; if you wanted to automatically populate a SlugField
, for example, you could import the slugify
function from django.template.defaultfilters
and use that to generate a slug from some other field.
But the thing people really clamor for is a foreign key to the auth User
model which automatically fills in the current user, for doing something like a created_by
field. This trick won’t work there, because models intentionally have no access to the current user
— that decoupling makes it possible to use Django for things that aren’t web applications (and thus don’t have HttpRequest
instances which carry user instances around with them), but it keeps this trick from working out-of-the-box for that particular case.
So how can we auto-populate a user
into a model?
###Autopopulate user
First, let’s change the model to have a created_by
field:
class TodoList(models.Model):
title = models.CharField(maxlength=100)
created = models.DateField()
updated = models.DateTimeField()
created_by = models.ForeignKey(User)
def save(self):
if not self.id:
self.created = datetime.date.today()
self.updated = datetime.datetime.today()
super(TodoList, self).save()
Of course, you’ll want to add from django.contrib.auth.models import User
up at the top of the file so you can reference User like that. Now, solving this is going to require two short pieces of code: a custom manager and a custom manipulator. Here’s the manager class:
class TodoListManager(models.Manager):
def create_list(self, title, user):
new_list = self.model(title=title, created_by=user)
new_list.save()
return new_list
Then make it the default manager for the TodoList class by adding objects=TodoListManager()
in the model definition. All of the normal querying methods will work as expected, because we haven’t overridden any of them. But we have added a new method: create_list
, which expects a title and a User
instance, and creates a new to-do list using them (the created
and updated
fields will, as before, be automatically filled in when the new list is saved). To see how that works, let’s look at the manipulator:
from django import forms
class TodoListForm(forms.Manipulator):
def __init__(self, request):
self.fields = (
forms.TextField(field_name='title', length=30, maxlength=100, is_required=True),
)
self.request = request
def save(self, new_data):
return TodoList.objects.create_list(new_data['title'], self.request.user)
Here’s a simple view which puts it all together:
@login_required
def create_todo_list(request):
manipulator = TodoListForm(request)
if request.POST:
new_data = request.POST.copy()
errors = manipulator.get_validation_errors(new_data)
if not errors:
manipulator.do_html2python(new_data)
new_list = manipulator.save(new_data)
return HttpResponseRedirect(new_list.get_absolute_url())
else:
errors = new_data = {}
form = forms.FormWrapper(manipulator, new_data, errors)
return render_to_response('create_todo_list.html', {'form': form})
The trick here is that creating the custom manipulator takes the HttpRequest
as an argument, and later when you use it to save, it pulls the User
out of that request and uses it to create the new to-do list. The view has the login_required
decorator to make sure there will always be a valid user.
And voilà . You have a to-do list which automatically gets the current user assigned to its created_by
field. Not hard at all, right? And as a bonus, the create_list
method on the manager is useful in other circumstances as well — any time you have access to a valid User
object, you can call this method to create a new list with that user filled in.
One caveat
Now, some people are probably going to be unhappy with the fact that the automatic user population doesn’t integrate into Django’s admin application in any way. That’s unavoidable, and my own humble opinion is that this isn’t something that should — the admin is for people who are 100% trusted to do the right thing with your site’s content, so if you’re doing all your model creation through the admin you should just show the created_by
field and trust your site staff to fill it in correctly.
But for the (probably more common) case where users are creating content, it’s great: just point them at a view like the one I’ve listed above, and everything will happen as it should.
Another option is a trivial field subclass - proposed by Jacob Kaplan Moss
https://groups.google.com/forum/#!msg/django-developers/TNYxwiXLTlI/L7srKCO8eEsJ
class AutoDateTimeField(models.DateTimeField):
def pre_save(self, model_instance, add):
return datetime.datetime.now()
###Why custom method may be better
created = models.DateTimeField(editable=False, auto_now_add=True) # Only on creation
updated = models.DateTimeField(editable=False, auto_now=True) # On every save
The reason why I just stick with overloading save() vs. relying on these field arguments is two-fold:
- The aforementioned ups and downs with their reliability. These arguments are heavily reliant on the way each type of database that Django knows how to interact with treats a date/time stamp field, and seems to break and/or change between every release. (Which I believe is the impetus behind the call to have them removed altogether).
- The fact that they only work on DateField, DateTimeField, and TimeField, and by using this technique you are able to automatically populate any field type every time an item is saved.
###Overide editable=False
Date fields with properties editable=False
dont usually show up in the Admin, to display them as read-only; use Readonly Fields <https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.readonly_fields>
_ like so:
class MyModelAdmin(admin.ModelAdmin):
readonly_fields=('first',)
To make a non editable field only editable in the admin and non editable elsewhere, you will need to use a custom ModelForm
in admin. This form can override the required field to make it editable. Thereby you retain editable=False
everywhere else but Admin. For e.g. (tested with Django 1.2.3)
# models.py
class FooModel(models.Model):
first = models.CharField(max_length = 255, editable = False)
second = models.CharField(max_length = 255)
def __unicode__(self):
return "{0} {1}".format(self.first, self.second)
# admin.py
class CustomFooForm(forms.ModelForm):
first = forms.CharField()
class Meta:
model = FooModel
fields = ('second',)
class FooAdmin(admin.ModelAdmin):
form = CustomFooForm
admin.site.register(FooModel, FooAdmin)