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

#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

Related

Using the paste "call" scheme when starting a Pyramid application

I have a Pyramid application which I can start using pserve some.ini. The ini file contains the usual paste configuration and everything works fine. In production, I use uwsgi, having a paste = config:/path/to/some.ini entry, which works fine too.
But instead of reading my configuration from a static ini file, I want to retrieve it from some external key value store. Reading the paste documentation and source code, I figured out, that there is a call scheme, which calls a python function to retrieve the "settings".
I implemented some get_conf method and try to start my application using pserve call:my.module:get_conf. If the module/method do not exist, I get an appropriate error, so the method seems to be used. But whatever I return from the method, I end up with this error message:
AssertionError: Protocol None unknown
I have no idea what return value of the method is expected and how to implement it. I tried to find documentation or examples, but without success. How do I have to implement this method?
While not the answer to your exact question, I think this is the answer to what you want to do. When pyramid starts, your ini file vars from the ini file just get parsed into the settings object that is set on your registry, and you access them through the registry from the rest of your app. So if you want to get settings somewhere else (say env vars, or some other third party source), all you need to do is build yourself a factory component for getting them, and use that in the server start up method that is typically in your base _ _ init _ _.py file. You don't need to get anything from the ini file if that's not convenenient, and if you don't, it doesn't matter how you deploy it. The rest of your app doesn't need to know where they came from. Here's an example of how I do this for getting settings from env vars because I have a distributed app with three separate processes and I don't want to be mucking about with three sets of ini files (instead I have one file of env vars that doesn't go in git and gets sourced before anything gets turned on):
# the method that runs on server startup, no matter
# how you deploy.
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application."""
# settings has your values from the ini file
# go ahead and stick things it from any source you'd like
settings['db_url'] = os.environ.get('DB_URL')
config = Configurator(
settings=settings,
# your other configurator args
)
# you can also just stick things directly on the registry
# for other components to use, as everyone has access to
# request.registry.
# here we look in an env var and fall back to the ini file
amqp_url = os.environ.get('AMQP_URL', settings['amqp.url'] )
config.registry.bus = MessageClient( amqp_url=amqp_url )
# rest of your server start up code.... below

Can anyone figure out my problem [Python]

I have been trying to debug the below python cgi code but doesn't seems to work. When i try in new file it these three lines seems to work
filename=unique_file('C:/wamp/www/project/input.fasta')
prefix, suffix = os.path.splitext(filename)
fd, filename = tempfile.mkstemp(suffix, prefix+"_", dirname)
But, when i try like this way then i get error unique_file is not define >>>
form=cgi.FieldStorage()
i=(form["dfile"].value)
j=(form["sequence"].value)
if (i!="" and j=="" ):
filename=(form["dfile"].filename)
(name, ext) = os.path.splitext(filename)
alignfile=name + '.aln'
elif(j!="" and i==""):
filename=unique_file('C:/wamp/www/project/input.fasta')
prefix, suffix = os.path.splitext(filename)
fd, filename = tempfile.mkstemp(suffix, prefix+"_", dirname)
file = open(filename, 'w')
value=str(j)
file.write(value)
file.close()
(name, ext) = os.path.splitext(filename)
alignfile=name + '.aln'
What i am trying to do is check two options from form:- Fileupload and textarea. If fileupload is true then there is nothing to do except separating file and its extension. But when textarea is true then i have to generate unique file name and write content in it and pass filename and its extension.
Error i got is...
type 'exceptions.NameError'>: name 'unique_file' is not defined
args = ("name 'unique_file' is not defined",)
message = "name 'unique_file' is not defined"
Any suggestions and corrections are appreciated
Thanks for your concern
unique_file() isn't a built-in function of Python. So I assume, either you forget a line in your first code snippet which actually imports this function, or you configured your python interpreter to load a startup file (http://docs.python.org/using/cmdline.html#envvar-PYTHONSTARTUP). In the second case, the CGI script can't find this function because it runs with the web server identity which probably lacks the PYTHONSTARTUP env. variable definition.
You need to either import or define your unique_file method before using it.
They will look something like:
from mymodule import unique_file
or:
def unique_file():
# return a unique file
Usually when a compiler or interpreter says something isn't defined, that's precisely what the problem is. So, you have to answer the question "why is it not defined?". Have you actually defined a method named "unique_file"? If so, maybe the name is misspelled, or maybe it's not defined before this code is executed.
If the function is in another file or module, have you imported that module to gain access to the function?
When you say it works in one way but not the other, what's the difference? Does one method auto-import some functions that the other does not?
Since unique_file is not a built-in command, you're probably forgetting to actually define a function with that name, or forgetting to import it from an existing module.

Suspicious Operation Django

I've been running into a problem while trying to delete uploaded images.
The error is along these lines:
SuspiciousOperation: Attempted access to '/media/artists/12-stones/154339.jpg' denied.
After reading around it looks like the error is due to the fact that it's looking for the image in the wrong place (notice first slash, /media/ doesn't exist on the filesystem)
My MEDIA_ROOT and MEDIA_URL are:
MEDIA_ROOT = '/home/tsoporan/site/media/'
MEDIA_URL = "/media/
My models upload_to parameter is passed this function:
def get_artist_path(instance, filename):
return os.path.join('artists', slugify(instance.name), filename)
My questions are:
1) How can I fix this problem for future uploads?
2) Is it possible to fix my current images' paths without having to reupload?
Regards,
Titus
I got this error when I put a leading slash in the upload_to definition.
BAD
pic = models.ImageField(upload_to="/uploads/product_images/")
GOOD
pic = models.ImageField(upload_to="uploads/product_images/")
Well, a little grepping around in the code shows that there may be a deeper error message that got homogenized along the way.
in django/core/files/storage.py, line 210 (this is in 1.1.1) we have:
def path(self, name):
try:
path = safe_join(self.location, name)
except ValueError:
raise SuspiciousOperation("Attempted access to '%s' denied." % name)
return smart_str(os.path.normpath(path))
So the error has to be coming out of safe_join().
In django/utils/_os.py, we have the following. Note the ValueError it throws on the third to last line:
===========================
def safe_join(base, *paths):
"""
Joins one or more path components to the base path component intelligently.
Returns a normalized, absolute version of the final path.
The final path must be located inside of the base path component (otherwise
a ValueError is raised).
"""
# We need to use normcase to ensure we don't false-negative on case
# insensitive operating systems (like Windows).
base = force_unicode(base)
paths = [force_unicode(p) for p in paths]
final_path = normcase(abspathu(join(base, *paths)))
base_path = normcase(abspathu(base))
base_path_len = len(base_path)
# Ensure final_path starts with base_path and that the next character after
# the final path is os.sep (or nothing, in which case final_path must be
# equal to base_path).
if not final_path.startswith(base_path) \
or final_path[base_path_len:base_path_len+1] not in ('', sep):
raise ValueError('the joined path is located outside of the base path'
' component')
return final_path
==================
Hmmm, "The joined path is located outside of the base path component". Now there are a couple of calls to abspathu() in there (which is defined just above this routine and is different for NT than for other OSes). abspathu() converts all non-absolute paths to absolute by tacking on os.cwdu(), the current working directory.
Question: By any chance do you have a symlink (symbolic link) to your media directory? In other words, it's not a direct child of the project directory? I don't know if this is a valid question, it just popped out of my head.
Question: What are the values of self.location and name that are being passed to safe_join()?
Wild-ass-guess: is self.location empty?
Another wild-ass-guess: did MEDIA_ROOT somehow get changed to /media/?
If you have your own copy of Django installed (it's not hard to do), trying putting some print statements in these routines and then run it as the development server. The print output will go to the console.
Update: Hmmm. You said "2) The values for self.location and name are: /home/tsoporan/site/media and /media/albums/anthem-for-the-underdog/30103635.jpg"
Does the following path make any sense?
"/home/tsoporan/site/media/media/albums/anthem-for-the-underdog"
Note the .../media/media/... in there.
Also, what OS is this? Django rev?
As a note for others this issue can be caused when you have a double '//' in the static file resource you are looking for.
{{ STATIC_URL }}/style.css # Causes the issue it should be
{{ STATIC_URL }}style.css
Ah figured it out, slightly embarrassing, but it turns out the error was higher up. I was plugging these images in by a script and while going over it again realized that my paths started with /media/.
Now I have about 4000 images with wrong paths ... is there a way to somehow amend the paths for all these images? Or will the need to be reuploaded?
Thanks everyone, apologies for my mistake.
You really should just ask a new question on this. Try the following:
Write a standalone django script that looks something like this:
from django.core.management import setup_environ
from mysite import settings
setup_environ(settings)
from django.db import transaction
from app.models import Album # or whatever your model name is
for a in Album.objects.all():
# Do something to cleanup the filename.
# NOTE! This will not move the files, just change the value in the field.
a.filename = re.sub(r'^/media', '', a.filename)
a.save()
transaction.commit_unless_managed() # flush all changes
Use SimpleUploadedFile if your temporary file is not part of the MEDIA_ROOT folder. This won't throw a SuspiciousOperation error:
upload_file = SimpleUploadedFile(name=basename(out_file), content=open(out_file, 'rb').read())
object = YourModel.objects.create(file=upload_file)
Use File if your temporary file is already a part of MEDIA_ROOT. This is useful if you want to link an existing Django file to an object.
object = YourModel.objects.create(file=File(open(file_path, 'rb')))
if you want use other location ,such as /data/images/myfile/ , you should set you MEDIA_ROOT to /data/images in django settings.py file .
I found out, by using dumb print statements, that some media files have /media prefixed in their url paths. While the default storage option handles that, there is a problem if you use S3BotoStorage from django-storages.
So I fixed it by overriding the _normalize_name (guided by the answer by #peter-rowell):
class MediaStorage(FixedUrlBotoStorage):
location = settings.MEDIAFILES_LOCATION
# Overriding function because some media files are stored with '/media' prefixed (which causes problems)
def _normalize_name(self, name):
if name.startswith('/media'):
name = name.lstrip('/media')
return super(MediaStorage, self)._normalize_name(name)
I fixed this in a very simple way, go to utils.py in this folder
djk\lib\site-packages\django\core\files\utils.py
(djk is the name of the virtualenv)
In the file just make line 7 and line 8 python comments and that's it, job's done.
I got this error too. Debugging through I found that the following exception is being raised.
SuspiciousOperation(u"Attempted access to '2015-03-19-08:29:51-2-f8945842891244629dfd0c0af4c72a9c.pdf' denied.",)
BTW, I am using django-storages (v1.1.8) to store my media files onto S3 (using S3boto backend). I am using django 1.7.6.
But if I switch to storing with file name with out colons (:) it seems to work. I haven't figured out yet what is the root cause. Just posting this in case this is helpful to somebody else. Apparently, django or django-storages does not like filenames with colons.
This bug is fixed in django 1.2.5. See http://docs.djangoproject.com/en/dev/releases/1.2.5/#filefield-no-longer-deletes-files

What's the official way of storing settings for Python programs?

Django uses real Python files for settings, Trac uses a .ini file, and some other pieces of software uses XML files to hold this information.
Are one of these approaches blessed by Guido and/or the Python community more than another?
Depends on the predominant intended audience.
If it is programmers who change the file anyway, just use python files like settings.py
If it is end users then, think about ini files.
As many have said, there is no "offical" way. There are, however, many choices. There was a talk at PyCon this year about many of the available options.
Don't know if this can be considered "official", but it is in standard library: 14.2. ConfigParser — Configuration file parser.
This is, obviously, not an universal solution, though. Just use whatever feels most appropriate to the task, without any necessary complexity (and — especially — Turing-completeness! Think about automatic or GUI configurators).
I use a shelf ( http://docs.python.org/library/shelve.html ):
shelf = shelve.open(filename)
shelf["users"] = ["David", "Abraham"]
shelf.sync() # Save
Just one more option, PyQt. Qt has a platform independent way of storing settings with the QSettings class. Underneath the hood, on windows it uses the registry and in linux it stores the settings in a hidden conf file. QSettings works very well and is pretty seemless.
There is no blessed solution as far as I know. There is no right or wrong way to storing app settings neither, xml, json or all types of files are fine as long as you are confortable with. For python I personally use pypref it's very easy, cross platform and straightforward.
pypref is very useful as one can store static and dynamic settings and preferences ...
from pypref import Preferences
# create singleton preferences instance
pref = Preferences(filename="preferences_test.py")
# create preferences dict
pdict = {'preference 1': 1, 12345: 'I am a number'}
# set preferences. This would automatically create preferences_test.py
# in your home directory. Go and check it.
pref.set_preferences(pdict)
# lets update the preferences. This would automatically update
# preferences_test.py file, you can verify that.
pref.update_preferences({'preference 1': 2})
# lets get some preferences. This would return the value of the preference if
# it is defined or default value if it is not.
print pref.get('preference 1')
# In some cases we must use raw strings. This is most likely needed when
# working with paths in a windows systems or when a preference includes
# especial characters. That's how to do it ...
pref.update_preferences({'my path': " r'C:\Users\Me\Desktop' "})
# Sometimes preferences to change dynamically or to be evaluated real time.
# This also can be done by using dynamic property. In this example password
# generator preference is set using uuid module. dynamic dictionary
# must include all modules name that must be imported upon evaluating
# a dynamic preference
pre = {'password generator': "str(uuid.uuid1())"}
dyn = {'password generator': ['uuid',]}
pref.update_preferences(preferences=pre, dynamic=dyn)
# lets pull 'password generator' preferences twice and notice how
# passwords are different at every pull
print pref.get('password generator')
print pref.get('password generator')
# those preferences can be accessed later. Let's simulate that by creating
# another preferences instances which will automatically detect the
# existance of a preferences file and connect to it
newPref = Preferences(filename="preferences_test.py")
# let's print 'my path' preference
print newPref.get('my path')
I am not sure that there is an 'official' way (it is not mentioned in the Zen of Python :) )- I tend to use the Config Parser module myself and I think that you will find that pretty common. I prefer that over the python file approach because you can write back to it and dynamically reload if you want.
One of the easiest ways which is use is using the json module.
Save the file in config.json with the details as shown below.
Saving data in the json file:
{
"john" : {
"number" : "948075049" ,
"password":"thisisit"
}
}
Reading from json file:
import json
#open the config.json file
with open('config.json') as f:
mydata = json.load(f) ;
#Now mydata is a python dictionary
print("username is " , mydata.get('john').get('number') , " password is " , mydata.get('john').get('password')) ;
It depends largely on how complicated your configuration is. If you're doing a simple key-value mapping and you want the capability to edit the settings with a text editor, I think ConfigParser is the way to go.
If your settings are complicated and include lists and nested data structures, I'd use XML or JSON and create a configuration editor.
For really complicated things where the end user isn't expected to change the settings much, or is more trusted, just create a set of Python classes and evaluate a Python script to get the configuration.
For web applications I like using OS environment variables: os.environ.get('CONFIG_OPTION')
This works especially well for settings that vary between deploys. You can read more about the rationale behind using env vars here: http://www.12factor.net/config
Of course, this only works for read-only values because changes to the environment are usually not persistent. But if you don't need write access they are a very good solution.
It is more of convenience. There is no official way per say. But using XML files would make sense as they can be manipulated by various other applications/libraries.
Not an official one but this way works well for all my Python projects.
pip install python-settings
Docs here: https://github.com/charlsagente/python-settings
You need a settings.py file with all your defined constants like:
# settings.py
DATABASE_HOST = '10.0.0.1'
Then you need to either set an env variable (export SETTINGS_MODULE=settings) or manually calling the configure method:
# something_else.py
from python_settings import settings
from . import settings as my_local_settings
settings.configure(my_local_settings) # configure() receives a python module
The utility also supports Lazy initialization for heavy to load objects, so when you run your python project it loads faster since it only evaluates the settings variable when its needed
# settings.py
from python_settings import LazySetting
from my_awesome_library import HeavyInitializationClass # Heavy to initialize object
LAZY_INITIALIZATION = LazySetting(HeavyInitializationClass, "127.0.0.1:4222")
# LazySetting(Class, *args, **kwargs)
Just configure once and now call your variables where is needed:
# my_awesome_file.py
from python_settings import settings
print(settings.DATABASE_HOST) # Will print '10.0.0.1'
why would Guido blessed something that is out of his scope? No there is nothing particular blessed.

Favorite Django Tips & Features?

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.

Categories

Resources