I developed a custom tag to look up the country of a certain IP
address using an IP to country database. It's sort of rough and ready,
but it should work. The idea is that you read the comment.ip_address,
feed it to the {% country %} tag, which then spits out the two letter
country code. The interesting thing is that the tag works once and
only once per page load if it has to render a variable. All subsequent
calls raise template.VariableDoesNotExist in the code below.

The interesting thing is that if you strip out the ability to
recognize an IP as a string and make it just render variables, and you
bind self.ip as a Variable object in the __init__ method and then try
to call its render method in the CountryNode's render method, it
actually raises AttributeError and claims that Variable object has no
attribute render. Weird! FYI, I'm using Django 1.2. Anyone have any
thoughts about what the heck is going on?

Here's the Python code:

from django import template
from django.template import Variable, Template
from django.db import connection

register = template.Library()

class CountryNode(template.Node):
    def __init__(self, ip):
        self.ip = ip

    def __repr__(self):
        return "<CountryNode>"

    def render(self, context):
        if self.ip[0] in '\'"':
            self.ip = self.ip.strip('\'"')
        else:
            try:
                self.ip = Variable(self.ip).resolve(context)
            except template.VariableDoesNotExist:
                return ''
        octets = [int(octet) for octet in self.ip.split('.')]
        decimal_ip = octets[0] * 256**3 + octets[1] * 256**2 +
octets[2] * 256 + octets[3]
        cursor = connection.cursor()
        cursor.execute("SELECT ctry FROM iptocountry WHERE ip_from <=
'%(decimal_ip)d' AND ip_to >='%(decimal_ip)d'" %
{'decimal_ip':decimal_ip})
        try:
            ctry = cursor.fetchone()[0]
        except TypeError:
            ctry = ""
        cursor.close()
        return ctry

@register.tag('country')
def do_country(parser, token):
    """
    {% country [ip] %}

    [ip] is a variable or string which is an IP address. The tag
attempts to
    look up the IP in the ip_to_country database table, and if
successful,
    the tag is replaced with the two letter ISO code for the country.
    """
    try:
        bits = token.split_contents()
        return CountryNode(bits[1])
    except IndexError:
        raise template.TemplateSyntaxError, "country tag requires one
argument."

And here's the piece of template:

            <table class="comment_table">
            {% for comment in comments.object_list %}
                <tr>
                    <td class="checkbox">
                        <input type="checkbox" name="comment_number"
value="{{ comment.id }}" />
                    </td>
                    <td class="comment">
                        <div class="comment_field">
                            <span class="comment_field_name">Content
Item:</span>
                            <a
href="{{ comment.content_object.get_absolute_url }}">{{ comment.content_object 
}}
</a>
                        </div>
                        <div class="comment_field">
                            <span class="comment_field_name">By:</
span>
                            {{ comment.user_name }}{% if
comment.user_url %} - <a href="{{ comment.user_url }}">Website</a>{%
endif %}{% if comment.user_email %} - <a href="mailto:
{{ comment.user_email }}">Email</a>{% endif %}
                        </div>
                        <div class="comment_field">
                            <span class="comment_field_name">From IP:</
span>
                            {{ comment.ip_address }} ({% country
comment.ip_address %})
                        </div>
                    </td>
                </tr>
            {% endfor %}
            </table>

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.

Reply via email to