Favorite Django Tips & Features? - python

Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
Inspired by the question series 'Hidden features of ...', I am curious to hear about your favorite Django tips or lesser known but useful features you know of.
Please, include only one tip per answer.
Add Django version requirements if there are any.

I'm just going to start with a tip from myself :)
Use os.path.dirname() in settings.py to avoid hardcoded dirnames.
Don't hardcode path's in your settings.py if you want to run your project in different locations. Use the following code in settings.py if your templates and static files are located within the Django project directory:
# settings.py
import os
PROJECT_DIR = os.path.dirname(__file__)
...
STATIC_DOC_ROOT = os.path.join(PROJECT_DIR, "static")
...
TEMPLATE_DIRS = (
os.path.join(PROJECT_DIR, "templates"),
)
Credits: I got this tip from the screencast 'Django From the Ground Up'.

Install Django Command Extensions and pygraphviz and then issue the following command to get a really nice looking Django model visualization:
./manage.py graph_models -a -g -o my_project.png

Use django-annoying's render_to decorator instead of render_to_response.
#render_to('template.html')
def foo(request):
bars = Bar.objects.all()
if request.user.is_authenticated():
return HttpResponseRedirect("/some/url/")
else:
return {'bars': bars}
# equals to
def foo(request):
bars = Bar.objects.all()
if request.user.is_authenticated():
return HttpResponseRedirect("/some/url/")
else:
return render_to_response('template.html',
{'bars': bars},
context_instance=RequestContext(request))
Edited to point out that returning an HttpResponse (such as a redirect) will short circuit the decorator and work just as you expect.

There's a set of custom tags I use all over my site's templates. Looking for a way to autoload it (DRY, remember?), I found the following:
from django import template
template.add_to_builtins('project.app.templatetags.custom_tag_module')
If you put this in a module that's loaded by default (your main urlconf for instance), you'll have the tags and filters from your custom tag module available in any template, without using {% load custom_tag_module %}.
The argument passed to template.add_to_builtins() can be any module path; your custom tag module doesn't have to live in a specific application. For example, it can also be a module in your project's root directory (eg. 'project.custom_tag_module').

Virtualenv + Python = life saver if you are working on multiple Django projects and there is a possibility that they all don't depend on the same version of Django/an application.

Don't hard-code your URLs!
Use url names instead, and the reverse function to get the URL itself.
When you define your URL mappings, give names to your URLs.
urlpatterns += ('project.application.views'
url( r'^something/$', 'view_function', name="url-name" ),
....
)
Make sure the name is unique per URL.
I usually have a consistent format "project-appplication-view", e.g. "cbx-forum-thread" for a thread view.
UPDATE (shamelessly stealing ayaz's addition):
This name can be used in templates with the url tag.

Use django debug toolbar. For example, it allows to view all SQL queries performed while rendering view and you can also view stacktrace for any of them.

Don't write your own login pages. If you're using django.contrib.auth.
The real, dirty secret is that if you're also using django.contrib.admin, and django.template.loaders.app_directories.load_template_source is in your template loaders, you can get your templates free too!
# somewhere in urls.py
urlpatterns += patterns('django.contrib.auth',
(r'^accounts/login/$','views.login', {'template_name': 'admin/login.html'}),
(r'^accounts/logout/$','views.logout'),
)

Context processors are awesome.
Say you have a different user model and you want to include
that in every response. Instead of doing this:
def myview(request, arg, arg2=None, template='my/template.html'):
''' My view... '''
response = dict()
myuser = MyUser.objects.get(user=request.user)
response['my_user'] = myuser
...
return render_to_response(template,
response,
context_instance=RequestContext(request))
Context processes give you the ability to pass any variable to your
templates. I typically put mine in 'my_project/apps/core/context.py:
def my_context(request):
try:
return dict(my_user=MyUser.objects.get(user=request.user))
except ObjectNotFound:
return dict(my_user='')
In your settings.py add the following line to your TEMPLATE_CONTEXT_PROCESSORS
TEMPLATE_CONTEXT_PROCESSORS = (
'my_project.apps.core.context.my_context',
...
)
Now every time a request is made it includes the my_user key automatically.
Also signals win.
I wrote a blog post about this a few months ago so I'm just going to cut and paste:
Out of the box Django gives you several signals that are
incredibly useful. You have the ability to do things pre and
post save, init, delete, or even when a request is being
processed. So lets get away from the concepts and
demonstrate how these are used. Say we’ve got a blog
from django.utils.translation import ugettext_lazy as _
class Post(models.Model):
title = models.CharField(_('title'), max_length=255)
body = models.TextField(_('body'))
created = models.DateTimeField(auto_now_add=True)
So somehow you want to notify one of the many blog-pinging
services we’ve made a new post, rebuild the most recent
posts cache, and tweet about it. Well with signals you have
the ability to do all of this without having to add any
methods to the Post class.
import twitter
from django.core.cache import cache
from django.db.models.signals import post_save
from django.conf import settings
def posted_blog(sender, created=None, instance=None, **kwargs):
''' Listens for a blog post to save and alerts some services. '''
if (created and instance is not None):
tweet = 'New blog post! %s' instance.title
t = twitter.PostUpdate(settings.TWITTER_USER,
settings.TWITTER_PASSWD,
tweet)
cache.set(instance.cache_key, instance, 60*5)
# send pingbacks
# ...
# whatever else
else:
cache.delete(instance.cache_key)
post_save.connect(posted_blog, sender=Post)
There we go, by defining that function and using the
post_init signal to connect the function to the Post model
and execute it after it has been saved.

When I was starting out, I didn't know that there was a Paginator, make sure you know of its existence!!

Use IPython to jump into your code at any level and debug using the power of IPython. Once you have installed IPython just put this code in wherever you want to debug:
from IPython.Shell import IPShellEmbed; IPShellEmbed()()
Then, refresh the page, go to your runserver window and you will be in an interactive IPython window.
I have a snippet set up in TextMate so I just type ipshell and hit tab. I couldn't live without it.

Run a development SMTP server that will just output whatever is sent to it (if you don't want to actually install SMTP on your dev server.)
command line:
python -m smtpd -n -c DebuggingServer localhost:1025

From the django-admin documentation:
If you use the Bash shell, consider installing the Django bash completion script, which lives in extras/django_bash_completion in the Django distribution. It enables tab-completion of django-admin.py and manage.py commands, so you can, for instance...
Type django-admin.py.
Press [TAB] to see all available options.
Type sql, then [TAB], to see all available options whose names start with sql.

The ./manage.py runserver_plus facilty which comes with django_extensions is truly awesome.
It creates an enhanced debug page that, amongst other things, uses the Werkzeug debugger to create interactive debugging consoles for each point in the stack (see screenshot). It also provides a very useful convenience debugging method dump() for displaying information about an object/frame.
To install, you can use pip:
pip install django_extensions
pip install Werkzeug
Then add 'django_extensions' to your INSTALLED_APPS tuple in settings.py and start the development server with the new extension:
./manage.py runserver_plus
This will change the way you debug.

I like to use the Python debugger pdb to debug Django projects.
This is a helpful link for learning how to use it: http://www.ferg.org/papers/debugging_in_python.html

When trying to exchange data between Django and another application, request.raw_post_data is a good friend. Use it to receive and custom-process, say, XML data.
Documentation:
http://docs.djangoproject.com/en/dev/ref/request-response/

Use Jinja2 alongside Django.
If you find the Django template language extremely restricting (like me!) then you don't have to be stuck with it. Django is flexible, and the template language is loosely coupled to the rest of the system, so just plug-in another template language and use it to render your http responses!
I use Jinja2, it's almost like a powered-up version of the django template language, it uses the same syntax, and allows you to use expressions in if statements! no more making a custom if-tags such as if_item_in_list! you can simply say %{ if item in list %}, or {% if object.field < 10 %}.
But that's not all; it has many more features to ease template creation, that I can't go though all of them in here.

Add assert False in your view code to dump debug information.

This adds to the reply above about Django URL names and reverse URL dispatching.
The URL names can also be effectively used within templates. For example, for a given URL pattern:
url(r'(?P<project_id>\d+)/team/$', 'project_team', name='project_team')
you can have the following in templates:
Team

Since Django "views" only need to be callables that return an HttpResponse, you can easily create class-based views like those in Ruby on Rails and other frameworks.
There are several ways to create class-based views, here's my favorite:
from django import http
class RestView(object):
methods = ('GET', 'HEAD')
#classmethod
def dispatch(cls, request, *args, **kwargs):
resource = cls()
if request.method.lower() not in (method.lower() for method in resource.methods):
return http.HttpResponseNotAllowed(resource.methods)
try:
method = getattr(resource, request.method.lower())
except AttributeError:
raise Exception("View method `%s` does not exist." % request.method.lower())
if not callable(method):
raise Exception("View method `%s` is not callable." % request.method.lower())
return method(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
return http.HttpResponse()
def head(self, request, *args, **kwargs):
response = self.get(request, *args, **kwargs)
response.content = ''
return response
You can add all sorts of other stuff like conditional request handling and authorization in your base view.
Once you've got your views setup your urls.py will look something like this:
from django.conf.urls.defaults import *
from views import MyRestView
urlpatterns = patterns('',
(r'^restview/', MyRestView.dispatch),
)

Instead of using render_to_response to bind your context to a template and render it (which is what the Django docs usually show) use the generic view direct_to_template. It does the same thing that render_to_response does but it also automatically adds RequestContext to the template context, implicitly allowing context processors to be used. You can do this manually using render_to_response, but why bother? It's just another step to remember and another LOC. Besides making use of context processors, having RequestContext in your template allows you to do things like:
A frog
which is very useful. In fact, +1 on generic views in general. The Django docs mostly show them as shortcuts for not even having a views.py file for simple apps, but you can also use them inside your own view functions:
from django.views.generic import simple
def article_detail(request, slug=None):
article = get_object_or_404(Article, slug=slug)
return simple.direct_to_template(request,
template="articles/article_detail.html",
extra_context={'article': article}
)

I don't have enough reputation to reply to the comment in question, but it's important to note that if you're going to use Jinja, it does NOT support the '-' character in template block names, while Django does. This caused me a lot of problems and wasted time trying to track down the very obscure error message it generated.

The webdesign app is very useful when starting to design your website. Once imported, you can add this to generate sample text:
{% load webdesign %}
{% lorem 5 p %}

django.db.models.get_model does allow you to retrieve a model without importing it.
James shows how handy it can be: "Django tips: Write better template tags — Iteration 4 ".

Everybody knows there is a development server you can run with "manage.py runserver", but did you know that there is a development view for serving static files (CSS / JS / IMG) as well ?
Newcomers are always puzzled because Django doesn't come with any way to serve static files. This is because the dev team think it is the job for a real life Web server.
But when developing, you may not want to set up Apache + mod_wisgi, it's heavy. Then you can just add the following to urls.py:
(r'^site_media/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': '/path/to/media'}),
Your CSS / JS / IMG will be available at www.yoursite.com/site_media/.
Of course, don't use it in a production environment.

I learned this one from the documentation for the sorl-thumbnails app. You can use the "as" keyword in template tags to use the results of the call elsewhere in your template.
For example:
{% url image-processor uid as img_src %}
<img src="{% thumbnail img_src 100x100 %}"/>
This is mentioned in passing in the Django templatetag documentation, but in reference to loops only. They don't call out that you can use this elsewhere (anywhere?) as well.

django.views.generic.list_detail.object_list -- It provides all the logic & template variables for pagination (one of those I've-written-that-a-thousand-times-now drudgeries). Wrapping it allows for any logic you need. This gem has saved me many hours of debugging off-by-one errors in my "Search Results" pages and makes the view code cleaner in the process.

PyCharm IDE is a nice environment to code and especially debug, with built-in support for Django.

Use xml_models to create Django models that use an XML REST API backend (instead of a SQL one). This is very useful especially when modelling third party APIs - you get all the same QuerySet syntax that you're used to. You can install it from PyPI.
XML from an API:
<profile id=4>
<email>joe#example.com</email>
<first_name>Joe</first_name>
<last_name>Example</last_name>
<date_of_birth>1975-05-15</date_of_birth>
</profile>
And now in python:
class Profile(xml_models.Model):
user_id = xml_models.IntField(xpath='/profile/#id')
email = xml_models.CharField(xpath='/profile/email')
first = xml_models.CharField(xpath='/profile/first_name')
last = xml_models.CharField(xpath='/profile/last_name')
birthday = xml_models.DateField(xpath='/profile/date_of_birth')
finders = {
(user_id,): settings.API_URL +'/api/v1/profile/userid/%s',
(email,): settings.API_URL +'/api/v1/profile/email/%s',
}
profile = Profile.objects.get(user_id=4)
print profile.email
# would print 'joe#example.com'
It can also handle relationships and collections. We use it every day in heavily used production code, so even though it's beta it's very usable. It also has a good set of stubs that you can use in your tests.
(Disclaimer: while I'm not the author of this library, I am now a committer, having made a few minor commits)

Use database migrations. Use South.

Related

pyramid.httpexceptions.HTTPNotFound: The resource could not be found

I am working off of Safari's Pyramid tutorial
WEB APPLICATIONS WITH PYTHON AND THE PYRAMID FRAMEWORK
Inside of my views.py file I having a problem with the following code:
#property
def current(self):
todo_id = self.request.matchdict.get('id')
todo = sample_todos.get(todo_id)
if not todo:
raise HTTPNotFound()
return todo
particularly when the following view function calls this property
#view_config(route_name='view', renderer='templates/view.jinja2')
def view(self):
return dict(todo=self.current)
when I am running the application http://0.0.0.0:6543/5 will not trigger the anticipated HTTPNotFound(), see route below.
config.add_route('view', '/{id}')
the error logs return:
File "/Users/alex/zdev/t-oreilly/mysite/views.py", line 50, in view
return dict(todo=self.current)
File "/Users/alex/zdev/t-oreilly/mysite/views.py", line 25, in current
raise HTTPNotFound()
pyramid.httpexceptions.HTTPNotFound: The resource could not be found.
On the browser waitress returns a default server error.
What is the proper way to remove this error?
I have uploaded this work to github, commit aaf562e
the tutorial link is here, for those eager to help, it can be accessed with their 10 day trial. This problem is from video 17/48.
thank you, if you need additional information please let me know.
This is a different HTTPNotFound exception and it is raised at the route-matching step before your view is even executed. The reason is that you have config.add_route('view', '/{id}'). Note the /{id} NOT /{id}/. Pyramid considers these two different routes and thus the latter does not match. The simplest solution to this is to register all of our canonical routes with a / suffix such as /{id}/ and then pass append_slash=True to your notfound view configuration such as config.add_notfound_view(..., append_slash=True) or #notfound_view_config(append_slash=True). This will trigger a redirect when a user visits the version without the trailing slash.
In two of your Jinja templates you reference the #property view.current. However, since the property throws an HTTPNotFound() exception, your Jinja templates end up hitting that and explode, causing your problem.
Either remove the calls to view.current from your Jinja templates or modify your view.current function so that it doesn't throw.
I'm not sure if this is the solution you are looking for, but it doesn't deviate from the tutorial.

How do I print a list from views.py to the console?

I'm a near-total newbie to Django, and am trying to debug a piece of code which is returning a null list to a template even though it should be returning a list with items in it. Is there any way to print the list to the console from within views.py for debugging purposes? I obviously can't run python views.py as the info I want is stored in a SQLite database, but if I try to include a print statement within the view I'm using, nothing prints when I refresh the page (and the server contacts my code). Is there a solution? I've looked around for a long time and can't find anything.
Firstly, you never run Django code with python views.py
However, you can see each HTTP request in your console that you open to start your local Django webserver.
If you do e.g. in your index() view function print, you should be able to see the output directly in your console:
def index(request):
a_list = [1,2,3,4]
print a_list
return render(request, 'index.html', {'list':a_list})
ask if something is unclear to you ;)
If you are using the runserver command, you will see the output of print-statements in that command prompt, like a live logging.
You could just include a debug line in your view function. Your views.py would look like :
import pdb
def myview(request):
...
pdb.set_trace()
...
When running python manage.py runserverand querying the corresponding url in your browser, your command line will stop on the pdb.set_trace(). You can then explore and test everything you want.

Setting cookies for static files using bottle.py

New to python. I am using bottle.py as a web server.
I have a set of static HTML files that need to be rendered on different routes. I am using static_file() function for the same. I also want to set a session based cookie for the page. SO I am using response.set_cookie().
But it turns out that when I am returning a static_file the cookie is never set. However if I change the response to a simple string, set_cookie() works fine. Can anyone explain why? And how can I fix this?
#app.route("/index")
def landingPage():
response.set_cookie("bigUId", "uid12345")
# return "Hello there"
return static_file("/html/index.html", root=config.path_configs['webapp_path'])
Welcome to Bottle and to Python. :)
Looking at the Bottle source code, the problem is readily apparent. Look how static_file ends:
def static_file(...):
...
return HTTPResponse(body, **headers)
static_file creates a new HTTPResponse object--so any headers you've set before then will be discarded.
A very simple way around this is to set the cookies after you call static_file, like this:
#app.route("/index")
def landingPage():
resp = static_file("/html/index.html", root=config.path_configs["webapp_path"])
resp.set_cookie("bigUId", "uid12345")
return resp
I just tried it, and it works perfectly. Good luck!
Well, I just tried, indeed it's not working, I never tried to use cookie with a static_file() before ... However, you can do the following to return a static file as a template, and the cookie will be set :
Your routing function :
#route('/test')
def cookie_test():
response.set_cookie("test", "Yeah")
return template('template/test.html')
And for this to work, you'll need to define a route for /template this way :
#route('/template/<filepath:path>')
def server_static(filepath):
return static_file(filepath, root="./template")
(Obviously, change "/template" to whatever you need according to your project path !)
I'm doing it this way, and it's working fine ! I'm not sure why it doesn't work when you try to set a cookie with static_file(), it might come from the fact that IT IS a static file that you're serving, or whatever, I really don't know.
Also, using the template() function in order to server a "static" html page might not be the right way to do it, but I'm personnaly doing it since a while, and I've never had any issue with this.
Hope it helps !

How can I create a file with a variable name in pyramid?

#view_config(route_name='home_page', renderer='templates/edit.pt')
def home_page(request):
if 'form.submitted' in request.params:
name= request.params['name']
body = request.params['body']
renderer_dict = dict(name=name,body=body)
new_comment = render('new_page.pt', renderer_dict, request=request)
with open('tutorial:templates/{name}.html','w') as file:
file.write(new_comment)
return HTTPFound(location=request.static_url('tutorial:pages/{pagename}.html',pagename=name))
return {}
Right now this is a view callable I have in my pyramid app that is for my apps home page. I am concerned about the line where file is created (with open...). I want the name of the file to be the same name defined by the request.params in the code above but I am not sure how to pass the variable (I doubt brackets are the right solution). I then want .html to be added to that name to make it a full file name. I am not sure what syntax to use in order to do this
Edit: I also would like advice on how to correctly do this on the return HTTPFound line. I would like it to redirect to that new file. Right now I have {pagename}.html but doubt that this is sufficient. I feel like the solution to this is the same as to the with open line but please correct me if Im wrong.
first off, i think you probably should NOT be doing whatever it is that you're trying to do.
second, to open the file...
name = request.params['name']
app_dir = SEE_BELOW
filename = "%(app_dir)s/templates/%(name)s" % { 'app_dir':app_dir , 'name':name }
filename = "%s/templates/%s" % ( app_dir , name )
with open(filename,'w') as file:
file.write(new_comment)
i'm going to note a few things:
app_dir - i forget how to get the actual pyramid app dir. i usually get spooked by this stuff, so only use specific subdirectories like such:
env.ini
templates_writable_dir = %(here)s/app/templates/writable/
then i can access it via:
request.registry.settings['templates_writable_dir']
note that i made a specific writable subfolder. i don't want the main stuff writable. i'll chmod/grp that writable folder so the user pyramid runs as can ed it. i won't allow that user to write to anything else.
"tutorial:templates/{name}.html" that is using the templated syntax, which only works in the templates. one of your pyramid plugins injects the renderer_dict into the template and renders it for you. you need to use normal python string formatting, as i showed above using two options.
More importantly...
based on your question, you're not just new to pyramid but to python too. i'd suggest doing a few quick python tutorials before jumping into Pyramid - or any other framework.
I don't think so that standard open understand tutorial:templtes and even {name}
use request.static_path there before use open

how to get current request's url in webpy

I am using webpy framework. I want get current request's url in webpy.
please help me, thanks.
Just try printing web.ctx in your controller method and you will see a bunch of environmental variables.
from pprint import pprint
pprint(web.ctx)
So your url probably should be ctx.home + ctx.path + ctx.query or ctx.home + ctx.fullpath.
UPD: You may also take a look at web.url and web.changequery, find them in api docs: http://webpy.org/docs/0.3/api
Is ctx path what you are after?
Data Found in ctx
Request
path – the path requested by the user, relative to the current
application. If you are using subapplications, any part of the url
matched by the outer application will be trimmed off. E.g. you have a
main app in code.py, and a subapplication called admin.py. In code.py,
you point /admin to admin.app. In admin.py, you point /stories to a
class called stories. Within stories, web.ctx.path will be /stories,
not /admin/stories. E.g. /articles/845

Categories

Resources