As soon as I saw this post by Grégory Tappéro on planet python I couldn't wait to implement this in my Pylons powered blog.
(Note: To compare the effort needed on Pylons to implement this as compared to Django, I'll follow the same procedure as Gregory has followed, so that you can compare the steps 1-on-1.)
I'm implementing this on my home brewed blog software - Chiselman
(unreleased). Please replace all references to chiselman with your proejects name.
Create a iptocountry.py
model file under chiselman/chiselman/models/
folder. Then we edit the models.py file, we need to make the fields match the ip-to-country.csv data file, and to add a method to import this data from cvs to your project database iptocountry
table.
from sqlalchemy import * dburi = 'mysql://user:passwd@localhost/chiselman' db = create_engine(dburi) metadata = BoundMetaData(db) iptocountry = Table('iptocountry', metadata, Column('id', Integer, primary_key=True), Column('ip_from', Integer), Column('ip_to', Integer), Column('country_code2', String(2)), Column('country_code3', String(3)), Column('country_name', String(50)) ) class IPToCountry(object): def __repr__(self): return "%s %s %s" % (self.ip_from, self.ip_to, self.country_name) def __init__(self, ipf=None, ipt=None, cc2=None, cc3=None, cname=None): if ipf and ipt and cc2 and cc3 and cname: self.ip_from = ipf self.ip_to = ipt self.country_code2 = cc2 self.country_code3 = cc3 self.country_name = cname def import_csv(csvfile): """ import entries from csv file""" import csv reader = csv.reader(open(csvfile)) count = 0 session = create_session() for ipf, ipt, cc2, cc3, cname in reader: count += 1 obj = IPToCountry(ipf, ipt, cc2, cc3,cname) session.save(obj) if count % 10000 == 0: print count print count , "inserted. :)" session.flush() del reader ip2c_mapper = mapper(IPToCountry, iptocountry)
Imported these into controllers/blog.py
where we need them.
Attached them to the global c
variable.
from chiselman.models.iptocountry import iptocountry, IPToCountry . . class BlogController(BaseController): ... @dispatch_on(POST='create_comment') def blog_post(self,slug): ... c.iptocountry = iptocountry c.IPToCountry = IPToCountry ...
Then we need to actualy import the data by running import_csv, to do this get to the paster shell
.
Paster shell is very nice. It is in same league as django-admin shell
and serves the same purpose.
Enter the following commands which calls the wanted function.
>>>import chiselman.models.iptocountry as ip2c #create the table in the database >>>ip2c.iptocountry.create() #import data from the csv file. >>>ip2c.import_csv('/home/pradeepgowda/projects/chiselman/ip-to-country.csv') # wait for a while the import to complete(> 67,000 records.)
This where Pylons differs significantly from Django. While Django best practice is to create a filter
, you can do with a simple Myghty component in Pylons.
IMO, writing a component feels much more "with the flow" than writing a filter. Somehow creating a filter feels like its more work than writing a quick component. One reason could be that, you can write the code that does the 'filtering' inline with your existing code; see it working and refactor it out into a proper component later.
The code below shows the comment display component which takes care of displaying the comments.
from markdown import markdown
from sqlalchemy import and_, create_session
comment
</%args>
body = markdown(comment.message)
if not comment.web.startswith('http://'):
url = 'http://'+comment.web
else:
url = comment.web
session=create_session()
iptc = cc2 = ccname = None
if len(comment.ip) > 0:
ip = m.comp('ip2long',ip=comment.ip)
if ip:
iptc = session.query(c.IPToCountry).selectfirst(and_(c.IPToCountry.c.ip_from = ip))
if iptc:
cc2 = iptc.country_code2.lower()
ccname = iptc.country_name.lower()
</%python>
% if cc2:
.gif" alt=" flag"/>
%
</%def>
ip2long
is the function which converts the ip address from xxx.xxx.xxx.xxx format into a integer.
I've copied that function verbatim from Gregory's code and made it into a myghty module.
ip </%args> ip_array = ip.split('.') ip_long = int(ip_array[0]) * 16777216 + int(ip_array[1]) * 65536 + int(ip_array[2]) * 256 + int(ip_array[3]) return ip_long </%python> </%def>
You can see this feature in action here .
© 2003-2011 Pradeep Gowda