The settings for your project which are a machine specific should be refactored out of settings.py into localsettings.py. In your settings.py, you should do:
try:
from localsettings import *
except ImportError:
print 'localsettings could not be imported'
pass #Or raise
This should be at the end of settings.py, so that localsetting.py override settings in settings.py
This file should not be checked in your repository.
Instead of writing:
TEMPLATE_DIRS = '/home/user/project/templates'
Do:
#settings.py
import os
CURRENT_DIR = os.path.dirname(__file__)
TEMPLATE_DIRS = os.path.join(CURRENT_DIR, 'template')
In your sidebar suppose you want to show the 5 latest comments. You do not need the request to output this. Make it as a templatetag.
Instead of doing from project.app.models import ModelClass do from app.models import ModelClass. This makes you apps reusable as they are not tied to a project.
Model class names should be singular, not plural.:
class Post(models.Model):
...
and not:
class Posts(models.Model):
...
Foreign key should use the name of the referenced class.:
class Post(models.Model):
user = models.ForeignKey(User)
Querysets should be plural, instances should be singular.:
posts = Post.objects.all()
posts = Post.objects.filter(...)
post = Post.object.get(pk = 5)
post = Post.object.latest()
Sometimes you will hit bugs which show up on servers but not on your local system. To handle these, you need to debug on the server. Doing manage.py runserver only allows local connections. To allow remote connections, use:
python manage.py runserver 0.0.0.0:8000
So that your pdb.set_trace() which are on remote servers are hit when you access them from your local systems.
If you use PK in urls you are giving away sensitive information, for example, the number of entries in your table. It also makes it trivial to guess other urls.
If possible use Slugs in urls. This has the advantage of being both user and seo friendly.
If slugs do not make sense, instead use a CRC algorithm.:
class Customer(models.Model):
name = models.CharField(max_length = 100)
def get_absolute_url(self):
import zlib
#Use permalink in real case
return '/customer/%s/' % zlib.crc32(self.pk)
ModelForm already know the correct UI widgets for your underlying Models. In most of the cases ModelForm would suffice instead of Forms.
Some common scnarios
Eg, you want too create a profile for the logged in user.:
#in Forms.py
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
exclude =['user',]
#In Views:
form = ProfileForm(request.POST)
profile = form.save(commit = False)
profile.user = request.user
profile.save()
Or:
#Todo test this
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
exclude =['user',]
def __init__(self, user, *args, **kwargs)
self.user = user
super(ProfileForm, self).__init__(*args, **kwargs)
def save(*args, **kwargs):
self.instance.user = self.user
super(ProfileForm, self).save(*args, **kwargs)
As:
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
exclude =['user',]
class UserForm(forms.ModelForm):
class Meta:
model = User
exclude =[...]
#in views.py
userform = UserForm(request.POST)
profileform = ProfileForm(request.POST)
if userform.is_valid() and profileform.is_valid():
#Only if both are valid together
user = userform.save()
profile = profileform.save(commit = False)
profile.user = user
profile.save()
{# In templates #}
<form ...>
{{ userform }}
{{ profileform }}
<input type="submit" />
</form>
if your forms is a forms.ModelForm, it already knows how to save its data. If you write a forms.Form, it should have a .save(). This keeps things symmetrical with ModelForms, and allows you to do:
#in views.py
def view_func(request):
if request.method == 'POST':
form = FormClass(request.POST)
if form.is_valid():
obj = form.save()
...
...
Instead of:
if form.is_valid():
#handle the saving in DB inside of views.
The .save() should return a Model Object
Your middleware and context processors are going to be run for all requests. Have you handled all cases?
- def process_request(request):
- if user.is_authenticated():
- profile = request.user.get_profile()#Hah, I create profiles during
- #registration so this is safe.
...
Or it is? What about users created via manage.py createsuperuser, with the above middleware, the default user can not even access the admin site.
Hence handle all scenarios in middleware and context processors. This is one place where try: .. except: .. (bare except) blocks are acceptable. You do not want one middleare bringing down the entire site.