I like programming in Python. I like learning about it, I like using it, and so I wish to share it.

Friday, July 18, 2008

Django templates by examples

I've always had to learn this again and again. Finally here's the steps to finally do it. Here they are:

1. Make sure django can find that page. Modify the urls.py so that it would point to the function in the correct module. Here's a very short sample.

from django.conf.urls.defaults import *

urlpatterns = patterns('',
(r'^$','mylogin.myapp.views.main'),
(r'^report$','mylogin.myapp.reports.index'),
# Example:
# (r'^mylogin/', include('mylogin.foo.urls')),

# Uncomment this for admin:
# (r'^admin/', include('django.contrib.admin.urls')),
)

The comments are already there originally and I would like to say DO NOT BE FOOLED!!.. I spent quite a lot of time figuring out why on earth it would say that the module doesn't exist whilst I have clearly created it already. Answer is don't use the include. Just point to the function directly. Note the projectname.appname.module.function format.

2. Write the function. My example above points to 2 modules and here they are:

<views.py>
# Create your views here.

from django.template import Context, loader
from django.http import HttpResponse

def main(response):
t = loader.get_template('main.html')
c = Context({'username':'abdullah'})
return HttpResponse(t.render(c))

<reports.py>
from django.shortcuts import render_to_response

def index(request):
return render_to_response('report.html')


Note that in views.py I did the step to step of what it takes to display a template. In reports.py I used the django.shortcuts render_to_reponse function which takes a template file as the first variable and a dictionary to set the context as the optional second variable (and I didn't use it here).

3. Set the template location. You have to define it in the TEMPLATE_DIRS variable in your settings.py. Here's my sample:

TEMPLATE_DIRS = (
# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
"/home/abdullah/python/mylogin/templates",
)


4. Create the directory you defined and put your templates in there. So here are my samples:

<mylogin/templates/main.html>
This is the new templated main {{username}}

<mylogin/tempaltes/report.html>
This is my report to you


Not much is it.. ;)

And that should be it.. You can now modify it and stuff.

Wednesday, July 16, 2008

Escaping sql in python

Learned how to escape an sql statement when using the MySQLdb module in python today. Accoding to the docs which can be found at: http://mysql-python.sourceforge.net/MySQLdb.html the execute method will actually escape the input for you if it is necessary. For example:


connect.execute("insert into student (name,address) values (%s,%s)",(name,address,))

Will actually escape the name and address variable first before running it. So a few things to note:
1. There is no need to put quotation marks around the variable inside the query (ie. %s)
2. It is not a normal python substitute string as there is no % after the string but a , which means it is already the second variable to the function execute
3. The variables have to be a tuple and so we add a comma at the end of the list of variables to force it to become a tuple

All in all quite interesting...

Wow.. Plone with templates.. nice...

I have to make some changes to the knowledge bank today. Whenever service providers key in their homepage, sometimes they do not include the http:// part of the address and the default plone behaviour is to consider it an internal link and thus it will link back into the knowledge bank. My first idea was to change the way the products save it's data (ie: appending the http if it is missing). But after some googling I find that would not be very wise. It's better to make the product template append the http if it was missing.

So after much googling I found a few references:
http://www.owlfish.com/software/simpleTAL/tal-guide.html
http://wiki.zope.org/ZPT/TALSpecification14
http://svn.python.org/projects/tracker/instances/python-dev/html/keyword.item.html
http://mail.zope.org/pipermail/zpt/2003-August/004774.html

So after much testing it out, this is what works:

<tal:x tal:define="gothttp python: (path('here/homepage')[:7]=='http://')">
<tal:x tal:condition="gothttp">
<a tal:attributes="href here/homepage"><span tal:replace="here/Title"/>'s Homepage</a>
</tal:x>
<tal:x tal:condition="not:gothttp">
<a tal:define="homepage python: 'http://'+path('here/homepage')" tal:attributes="href homepage"><span tal:replace="here/Title"/>'s Homepage</a>
</tal:x>
</tal:x>


It's working great. And just for completion sake I also changed so that the bracket around the name will not be shown if there is no phone number (ie: length of phone number is 0)

<span tal:define="phonelen python:len(path('here/contactPhone'))" tal:condition="phonelen">
<span tal:replace="here/contactPhone"/> ( </span><span tal:replace="here/contactName"/><span tal:define="phonelen python:len(path('here/contactPhone'))" tal:condition="phonelen">)</span>


great stuf.. :D

Saturday, July 12, 2008

Learning to configure django with lighttpd

So far I'm not having much luck setting up django with lighttpd. Followed the official docs here: http://www.djangoproject.com/documentation/fastcgi/ . Almost got it but when I try to access is says that the connection is refused because permission is denied. From http://home.badc.rl.ac.uk/lawrence/blog/2006/10/26/exploring_web_server_backends_-_installing_fastcgi_and_lighttpd I get the idea to `sudo su www-data` to start as the same user as lighttpd. But it can't write to the disk so I created a folder and chown it to www-data. Then rewrote the start-up script and configuration to create the socket and pid files in there. It works. But now I have a problem with the redirect. The system was supposed to run under a subfolder. But when I go to the subfolder/admin it gets redirected to admin. Which of course does not exists. Wondering whether I have to redirect admin too. But that seems ridicoluous. Whichever it I've got to keep on trying.

*Update - Found http://www.cyberciti.biz/tips/configure-lighttpd-alias-mod_alias.html which explains a bit more about the mod_alias directive. So it was because I needed to use 'alias.url +=' rather than 'alias.url ='. At the least now the media looks kinda right.

**Update - Finally asked on irc and got the subdirectory working. Just modify the urls in urls.py so that django itself will translate it properly. Fuh..

Wednesday, July 9, 2008

Small file to auto-create php comments spaceholder

I'm so lazy. Wrote a script to help me comment my commentless php code.


#!/usr/bin/env python

import sys
import re

def main():
try:
print "Trying to open %s" % (sys.argv[1])
fin=open(sys.argv[1],'r')
fout=open(sys.argv[1]+'.out','w')
except:
print 'Unable to open file'
quit()
varcond=re.compile('(\$(?!this)\w+)')
classvarcond=re.compile('var\s')
funccond=re.compile('function\s(\w+)')
for line in fin:
if classvarcond.search(line):
variables=varcond.findall(line)
outtext = "/**\n * Define %s\n *\n */\n" % (variables[0])
fout.write(outtext)
if funccond.search(line):
funcname=funccond.findall(line)
variables=varcond.findall(line)
print funcname," function is found"
outtext = "/**\n * Describe %s\n *\n" % (funcname[0])
for variable in variables:
outtext += " * @param %s\n" % (variable)
outtext += " * @return null\n */\n"

fout.write(outtext)
fout.write(line)

if __name__=="__main__":
if len(sys.argv)>1:
main()
else:
print 'Please provide filename'



Just put it here to share in case anyone find it useful. And also as a backup.. :P

Python short reference

Nice short reference for python can be found at http://codesyntax.netfirms.com/lang-python.htm

Saturday, July 5, 2008

Using MySQL in python

Using mysql in python is quite easy. First step, make sure the python module for mysql exists:


import MySQLdb

If it comes out with an error, you might have to install some python-mysql package for your distro.
Once than is done you need to connect to the database and create a cursor for it by doing:

db = MySQLdb.connect(host="localhost",user="username",passwd="password",db="database_name")
cursor=db.cursor()

Once that is done you can execute sql statements to your hearts contend with:

cursor.execute("select * from sample_table where sample_field=sample_rule")

You can even put in dynamic string using variables like this:

cursor.execute("select * from sample_table where sample_field=%s" % sample_rule)

And finally to get the data there is a few function you can choose from. Either do a:

result=cursor.fetchall()

which will return a tuple of tuples of all the records available. Or you can do a:

result=cursor.fetchone()

which will return only one row of data. You can check how many rows of data available by doing:

cursor.rowcount

And lastly you can do a :

cursor.fetchmany(num_of_rows)

to read in specific amount of data rows.
In fact you can even execute many which would save time if you had to repeat an insert operation again and again for example.

cursor.executemany("insert into students (name,ic) values (%s,%s)",[("abdullah","810218-71-5055"),("kassim","830521-03-4533")])

or you could actually have pre-created it before the sql statement.