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