📜 ⬆️ ⬇️

GeoIP and Django

Web developers often face the classic task of locating a user by their IP address. There are many different solutions, for example, based on the global base of Maxmind Geolite or Russian IpgeoBase. All of them have quite low-level APIs, well, that's understandable: at the entrance there is an aypishnik, at the exit a country, or a city and, if lucky, there is some other useful information.

All sites with GeoIP, which we launched, have a common feature: they not only need simple geolocation, it is also necessary to display different content on the site depending on the location of the user. To simplify this task for ourselves, we wrote a small django-geoip battery , inspired by the django-ipgeobase application.


Django-geoip


The main advantage of the application: it can automatically determine the geography of the user and pass it to the request object. Now content on a site that has “regionality” can be easily filtered into views.py by the value of request.location.
')
Features


Features of the implementation

The django-geoip application supports the geography hierarchy of Country - Region - City, which is stored in a normalized form in a DBMS. Data on the range of IP-addresses with links to all elements of geography - in the fourth table. The current version works only with the data of ipgeobase.ru, it is almost a thousand cities of Russia and Ukraine and 150 thousand IP ranges.

One of the reasons for storing data in a database is the need to create its own geography model that meets the objectives of business logic. For example, in one of the projects we limit the definition of a user's location to areas of Russia, in the other - to a set of cities in which the company is present. This model implements the “facade” pattern to the ipgeobase hierarchy of geography, allowing you to flexibly configure geolocation for you.

Imagine that our site has several regional "versions", each of which may contain its own content. At the same time, a region can have an arbitrary name and, for example, contain several regions of the Russian Federation (geo_location table in the diagram):

Here is an example of how it is configured and works. Define your geography model MyCustomLocation:

# geo/models.py class MyCustomLocation(GeoLocationFacade): name = models.CharField(max_length=100) region = models.OneToOneField(Region, related_name='my_custom_location') is_default = models.BooleanField(default=False) @classmethod def get_by_ip_range(cls, ip_range): """     IP-.       , ,   ,       """ return ip_range.region.geo_location @classmethod def get_default_location(cls): """  -,  ,       IP""" return cls.objects.get(is_default=True) @classmethod def get_available_locations(cls): return cls.objects.all() class Meta: db_table = 'geo_location' 

This is a regular django model, supplemented with three class methods that implement the “interface” of the GeoIP facade. The purpose of each function is clear from the title and pre-stringing. It remains to fill the base with the names of cities and link them to the models djagno-geoip.

Register in settings.py:
 GEOIP_LOCATION_MODEL = 'geo.models.MyCustomLocation' 

Add middleware to automatically determine the region:
 MIDDLEWARE_CLASSES = (... 'django_geoip.middleware.LocationMiddleware', ... ) 

And voila: request.location now contains the value of our MyCustomLocation model for each user.
 def my_view(request): """ Passing location into template """ ... context['location'] = request.location ... 

If the user is not in any of these cities, he will be assigned the region by default (get_default_location).

This approach greatly simplifies the task of creating “regional” sites that differ from each other in content depending on the location of the user.

What's next


The application, although alpha, works well with us in production (version 0.2.2). The alpha status hints that the API will change in the future. We plan to support and develop it further, including implementing the definition of a region not only for Russia, but also for the rest of the world . Also interesting was the idea of optimizing the search for a suitable IP range on the base .

Source codes are available on github , waiting for your comments.

Source: https://habr.com/ru/post/142347/


All Articles