The day i saw these little flags near people comments, i could not wait to implement this in my django project.
What you need
- The ip-to-country data file, 60k entries as a csv file here.
- A set of tiny flags images, some kind there which you will put in /media/img/flags/ of your project.
Then we can start looking at your django project by firstly creating a new iptocountry application >python manage.py startapp iptocountry
Models
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_iptocountry table.
from django.db import models
# ip-to-country
class IpToCountry(models.Model):
IP_FROM = models.PositiveIntegerField()
IP_TO = models.PositiveIntegerField()
COUNTRY_CODE2 = models.CharField(maxlength = 2)
COUNTRY_CODE3 = models.CharField(maxlength = 3)
COUNTRY_NAME = models.CharField(maxlength = 50)
class Admin:
ordering = ['IP_FROM']
def __str__(self):
return "%s %s %s" % (self.IP_FROM ,self.IP_TO, self.COUNTRY_NAME)
def import_csv(self, file):
import csv
# First delete all the objects before inserting
IpToCountry.objects.all().delete()
# create a reader to get the data from the file
reader = csv.reader(open(file))
count = 0
for ipf, ipt, cc2, cc3, cname in reader:
count += 1
object = IpToCountry(count,ipf, ipt, cc2, cc3, cname)
object.save()
if count % 10000 == 0:
print count
print count , "inserted. :)"
del reader
We can now install the application, first edit your settings.py and add 'your_project.iptocountry', to INSTALLED_APPS.
Import data
Then we need to actualy import the data by running import_csv, to do this get to the python shell python manage.py shell and enter the following commands which just call the wanted method.
from coulix_org.iptocountry.models import IpToCountry
iptc = IpToCountry()
iptc.import_csv('/your/file/path/ip-to-country.csv')
After few seconds you should see the first "10 000" showing, wait few minutes for the process to complete.
Filters
All of this is quite fun so far, but how do we use this for our comments ? Well, comments have an ip field by default, we will use this ip to map to a country name and get the appropriate flag. To do we need some custom filtering, which given an ip returns a path to the image.
If you have look at the ip-to-country.csv data, you can see it uses a strange way of storing ip values, it is called longip notation, we therefore need a method to convert our normal ip from the comment object to the long ip representation in our database.
Let's start this by creating a *templatetags folder in our iptocountry application folder, add an empty init.py* file to it and create a iptocountry_filter.py file wich contains :
from django import template
register = template.Library()
def ip2long(ip):
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
def get_country2(value, arg):
''' arg is the location of the flag imgs, eg '/media/img/flag/' '''
from coulix_org.iptocountry.models import IpToCountry
value = ip2long(value)
try:
# ip of comment has to be in a range of an ip-to-country object IP_FROM and IP_TO
iptc = IpToCountry.objects.get(IP_FROM__lte=value, IP_TO__gte=value)
except IpToCountry.DoesNotExist:
return " "
return "<img src='" + arg + (iptc.COUNTRY_CODE2).lower() + ".png' alt='" + (iptc.COUNTRY_NAME).lower() + "' />"
register.filter('get_country2', get_country2)
Restart your server for the new filters to be accessible.
Templates
We are finaly set, let's use it in your template after getting the list of comments, and the flag should appears (well if you are trying it with an ip of 127.0.0.1 nothing will happens, try to edit the ip in the django admin).
{% load iptocountry_filter %}
{% for comment in comment_list %}
[...]
{{ comment.ip_address|get_country2:"/media/img/flag/"}}
[...]
{% endfor %}


3:43 p.m.
I spotted a pylon version resulting from this post : btbytes there nice :).
8:48 p.m.
Grégory, Thanks for the cool idea:) Working with Pylons is a lot of fun.
11:28 p.m.
Testing... :)
12:42 a.m.
Thanks for sharing this cool tips!
Also testing ;-)
12:54 a.m.
pas de problemes :), la traduction francaise arrivera bientot.
11:32 a.m.
Hi. I bet people comment just to see the new flags. I did :)
1:05 p.m.
I did too, nice blog :-)
6:38 p.m.
hey nice stuff
10:48 a.m.
only test!
3:44 p.m.
another test
5:51 p.m.
testing
8:04 p.m.
yet another test (yat)
8:07 p.m.
no worries guys, all the flag are there haha
8:20 p.m.
I wanna see the dutch flag :)
3:47 a.m.
singapore?
2:22 p.m.
test it ok!
7:18 p.m.
Thanks for cool tip.
One question: way do you have:
del readeron the end of import_csv method? I thought, that python have garbage collector, so after end of this method, reference count will be 0, and reader will be deleted automaticaly. Am I wrong?
8:03 p.m.
True its useless. :)
10:37 p.m.
I've just tried this tutorial, using Postgresql database, unfortunately it doesn't work in Postgresql, because Postgresql have no Positive Integer type, so range is only to about 0 - 2,000,000,000 (0 - 2^31), which is not enough for IP adresses (2^32). And what is worse, there is no BigIntegerField type in django (svn version). I found patch on django source site, but it's old and unapplicable for current version of django. There is one more patch for big integer on that page, but only for MySQL :(. I don't understand, how could django be without such a base thing like big integer?
10:56 p.m.
Hum true that's a problem Postgresql has a big integer type ? then maybe we could ask the dev to do something about it. check irc #django. And show us your website when you are done :)
7:17 a.m.
If you read that page, you will see, that there was patch for BigIntegerField type for django ONE YEAR ago - and developers didn't applied it to project. Nowadays, structure of django sources was chang so that patch is inapplicable.
Second patch is only few days old, but only for MySQL, and if there will be no patch for other databases, I'm sure that developers don't use it.
And about my website: I've just come through "Writing your first Django app" tutorial, and found your site when I was looking for example apps in django. So my django site is quite far away ;).
9 a.m.
Thank you for cool idea!
6:18 a.m.
My countryflag here too
9:20 p.m.
italy
6:45 p.m.
Latvia?
8:31 a.m.
poland plz
7:41 p.m.
romania :)
7:48 p.m.
Sweden!
9:36 p.m.
india
1:53 a.m.
Thanks! very cool :)
Norway!
4:31 p.m.
argentina! lol very cool, will use someday in some project ;D
1:36 a.m.
Belgium (hopefully)
10:56 p.m.
and germany, too..
12:19 a.m.
netherlands
5:03 p.m.
Québec!
9:28 p.m.
Bulgaria
10:42 a.m.
New Zealand
11 p.m.
Checking Serbia
8:44 p.m.
Austria
1:02 a.m.
from Japan. GeoIP?
10 a.m.
greece?
5:11 a.m.
this is cool dude.. keep up the good work
4:56 a.m.
Ukraine?
2:46 a.m.
Yeah! Germany!
6:37 a.m.
yeah baby
7:47 a.m.
checkin' the flag
8:59 p.m.
Just love my flag... lets see if it works... (I's UY by the way)
9:59 p.m.
Now we can't have he swiss flag missing can we? :)
6:08 a.m.
Euskadi (Basque Country)
12:23 a.m.
Switzerland
2:19 a.m.
brazil ?
5:47 p.m.
france
11:01 p.m.
russia
2:09 p.m.
seems not geoip? similar one
12:17 a.m.
Korea?
3:28 a.m.
South Africa?
9:33 p.m.
This is nice! :)
PS. Finland!
2:58 a.m.
Dominican Republic
12:49 a.m.
my country
9:50 p.m.
Kenya? Cool!
9:53 p.m.
oups no kenya :) i should update the db
10:37 a.m.
What about the sunny Barranquilla, Colombia?
7:53 a.m.
test
11:08 a.m.
From Brazil... :P
8:48 p.m.
From Switzerland
11:30 p.m.
Here's the cute Korean flag again :)
Merry Christmas, my love! Isn't there NC regional flag???
2:27 a.m.
PL
10:29 p.m.
UK
6:44 p.m.
Sounds Very nice!
4:53 a.m.
Uruguay
12:15 p.m.
CHILE!
10:33 p.m.
UK!
3:29 a.m.
Mongolia!
3:30 a.m.
Ok, i was lying about mongolia.
7:03 p.m.
Looks like your missing kenya and south africa
7:13 p.m.
Right NOW: 8:13 UTC (whats up with your time?)
12:13 p.m.
turkey?
2:22 a.m.
Bangladesh?
7:26 a.m.
Iceland?
8:19 a.m.
Seems nice idea, but why the CAPITALIZED variable names in model, they're not constants, right.
12:50 p.m.
test
10:30 p.m.
¿con eñes?
10:56 p.m.
sitting in the heart of europe
1:06 p.m.
Australia
12:05 a.m.
China?
5:50 a.m.
uh
1:47 p.m.
Pilipinas
6:42 p.m.
russia
8:56 a.m.
hum there is a bug in the comments numbering, i guess it increments the number including the spams which are not shown :/.
11:08 a.m.
USA again!
7:01 p.m.
interesting i wanna see
5:46 a.m.
Just a Testing :P
4:30 p.m.
Quite a few Aussies... so here's another :)
5:55 p.m.
Yet another spaghetti-eater :)
1:49 a.m.
From Thailand
8:38 a.m.
Has anyone's flag turned out wrong in this list? I was just thinking about asking the user to supply their country as a way of preventing spam bot attacks.
9:24 a.m.
Testing again. Nice idea!
2:20 a.m.
Türkiye
3:03 p.m.
Testing.
4:20 p.m.
Very Nice
9:39 a.m.
Nigeria?
5:34 p.m.
uniquely
5:35 p.m.
Post #114 got hijacked.
10:43 p.m.
havent fixed the comments counter yet :/
3:37 a.m.
test
2:35 a.m.
Testing also (should be canada!)
10:40 p.m.
chinese
8:48 a.m.
ukraine
4:29 p.m.
HK
1:17 p.m.
china,wuhan The flags images is gif format now
2:04 a.m.
test
4:08 p.m.
test2
12:54 p.m.
just had to do it
12:14 a.m.
Make it #130. Hope you are not running out of tab
3:37 a.m.
Hi all from Italy! :)
1:16 a.m.
test!
8:04 a.m.
Hi! Good site respect! home depot canada Visit home depot canada Thanks!
1:38 a.m.
Testing US
7:57 a.m.
test123
10:44 p.m.
test
8:06 a.m.
testing again...
11:57 p.m.
test
6:25 p.m.
test
9:52 p.m.
armenia?
8:54 p.m.
tara Moldova
8:23 a.m.
Canada, Alberta
6:01 p.m.
China
8:20 a.m.
bharat :)
12:16 a.m.
test
12:27 p.m.
Home
10:54 a.m.
Dog Acres, USA
7:24 a.m.
Holger Danske
7:25 a.m.
Hmm, it seems that my danish work IP isn't registered, better try it at home too.
3:58 a.m.
Trying from my home ADSL.
3:23 p.m.
From Japan!!
1:31 a.m.
Taiwan
1:38 a.m.
from morocco
7:34 p.m.
poland :)
8:44 a.m.
Thanks!
8:18 p.m.
test
7:03 p.m.
testing
11:35 p.m.
Canada
9:32 a.m.
Spain
4:48 a.m.
testing
8:11 a.m.
Spain
1:41 a.m.
Works from Russia
4:32 a.m.
Seems like I'm the first from Slovenia.
Cool project! :-)
5:03 a.m.
Nice one..
9:01 p.m.
testing
11:28 p.m.
test
2:12 a.m.
cool!
8:53 a.m.
Test from Russia
3:38 a.m.
Brazil