GeoIP tracking with MaxMind and Django

readthedocs: geoip2.readthedocs.io/en/latest/
pypi: pypi.org/project/geoip2/

 

Content:

 

MaxMind

 

  1. Create an account in Maxmind: MaxMind.
  2. After logging in, click Manage license keys in the left menu.
  3. Click the button Generate a new license key.
  4. Make sure to save your license key securely.

     
GeoLite ASN Identifies the ASN (Autonomous System Number) and the organization owning the IP.
GeoLite City Provides detailed IP location including city, region, and country.
GeoLite Country    Provides only the country associated with an IP.

 

Downloading a database:

  1. Click Download files in the left menu.
  2. For this tutorial we will be downloading: GeoLite City as GZIP

 

 

Getting the Data in Django

 

pip install geoip2

 

from django.urls import path
from .views import *

urlpatterns = [
    path("", index.as_view(), name="index"),
]

 

from django.views.generic import TemplateView
from django.conf import settings

import geoip2.database

class index(TemplateView):
    template_name = 'polls/index.html'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        ip = self.request.META.get('HTTP_X_FORWARDED_FOR')
        if ip: ip = ip.split(',')[0].strip()
        else: ip = self.request.META.get('REMOTE_ADDR', '8.8.8.8')
        if ip in ("127.0.0.1", "::1"): ip = "8.8.8.8"
 
        reader = geoip2.database.Reader(settings.BASE_DIR / 'GeoLite2-City.mmdb')
        response = reader.city(ip)

        location = {
            'ip': ip,
            'country': response.country.name,
            'country_iso_code': response.country.iso_code,
            'city': response.city.name,
            'latitude': response.location.latitude,
            'longitude': response.location.longitude
        }

        reader.close()

        context['location'] = location
        print(location)

        return context

 

<table>
        <tr> <td>ip</td>                <td>{{location.ip}}  </td> </tr>
        <tr> <td>city</td>              <td>{{location.city}}  </td> </tr>
        <tr> <td>country</td>           <td>{{location.country}}  </td> </tr>
        <tr> <td>country_iso_code</td>  <td>{{location.country_iso_code}} </td> </tr>
        <tr> <td>latitude</td>          <td>{{location.latitude}}  </td> </tr>
        <tr> <td>longitude</td>         <td>{{location.longitude}}  </td> </tr>
        
</table>

 

 

Always-On task

 

Since IP address allocations can change, MaxMind updates these files twice a week, on Tuesdays and Fridays.
MaxMind Update Schedule
Therefore, it’s important to have a mechanism in place to regularly update the database files.
The script below can be scheduled as an Always-On task, triggered on those days.

 

from pathlib import Path
import shutil
import tarfile
import requests

BASE_DIR = Path(__file__).resolve().parent

id = "xxxxx"
key = "xxxxx"

url = 'https://download.maxmind.com/geoip/databases/GeoLite2-City/download?suffix=tar.gz'
auth = (id, key)
save_path = BASE_DIR / 'GeoLite2-City.tar.gz'

response = requests.get(url, auth=auth, stream=True)
if response.status_code != 200:
    print(f"Download failed, HTTP Code: {response.status_code}")

with save_path.open('wb') as f:
    for chunk in response.iter_content(chunk_size=8192):
        if chunk:
            f.write(chunk)

with tarfile.open(save_path, 'r:gz') as tar:
    tar.extractall(path=BASE_DIR)

save_path.unlink() 

extracted_folders = list(BASE_DIR.glob("GeoLite2-City_*"))
if not extracted_folders:
    raise FileNotFoundError("Extracted folder GeoLite2-City not found.")
extracted_folder = extracted_folders[0]

mmdb_source = extracted_folder / "GeoLite2-City.mmdb"
mmdb_dest = BASE_DIR / "GeoLite2-City.mmdb"

if mmdb_dest.exists():
    mmdb_dest.unlink()

shutil.move(str(mmdb_source), str(mmdb_dest))
shutil.rmtree(extracted_folder)

print("Database GeoLite2-City updated.")

 

 


Tested with:
Django 5.2
geoip2==5.1.0



12 Aug. 2025 | Last Updated: 03 Dec. 2025 | jaimedcsilva

Related
  • Using ngrok with Django
  • Opening a Django project through a .exe file
  • Creating an online store with Django
  • CRUD
  • Creating a Basic Django Project Automatically
  • Filter Horizontal in a custom template
  • GeoIP tracking with IpInfo and Django
  • GeoIP tracking with MaxMind and Django
  • Django User Agents
  • Generating Temporary Download Links
  • Cython - Hiding the Code of a Django Project
  • Quick & Easy Django Deployment on PythonAnywhere
  • A Brief History of Django
  • Django & Paypal Webhooks
  • Generating QR Codes with Django

  • Buy Me a Coffee