リクエスト元のIPアドレスから、アクセスしている国を特定する必要があり、Django で実現する方法を調べたところ、Geolocation with GeoIP2 | Django ドキュメント | Django というライブラリを使えば実現できそうに思いました。
ユースケースとして、Web API でリクエスト元のIPアドレスから 地域を推定したかったので、GeoIP2
と、djangorestframework を使ってWeb API を書いてみました。
事前準備として実施したこと、作ったAPIについて記載します。
前提
OS の情報と、Django、djangorestframework の Version 情報 は以下の通りです。
-
OS の Version
cat /etc/redhat-release CentOS Linux release 7.8.2003 (Core)
-
DjangoのVersion
pip list | grep Django Django 1.11.20
-
djangorestframeworkのVersion
pip list | grep djangorestframework djangorestframework 3.9.2
CentOS 7 に、geoipupdate
をインストールして、GeoIP2のデータベースを自動更新する
Django の GeoIP2
を動かすには、IP Geolocation and Online Fraud Prevention | MaxMind のデータベースファイルが必要になります。
これは、毎週火曜日に更新されるのですが、自動更新を可能にするgeoipupdate
というライブラリがあり、Web API を書く前に、自動更新の設定をします。
インストール、設定方法は以下の記事が参考になりました。
CentOS 7のGeoIP Free Databaseの更新 ← RootLinks Co., Ltd.
-
インストール
Version 2.5.0 がインストールされました。yum -y install geoipupdate
geoipupdate -V geoipupdate 2.5.0
-
GeoIP.confの編集
データベースの更新には、アカウント情報とライセンスキーが必要になります。
ライセンスキーは、GeoLite2 Sign Up | MaxMind でアカウントを作ると発行できるようになります。
ちなみに、データベースのダウンロードにも、アカウント登録が必要です。
CentOS 7 だと、/etc/GeoIP.conf
にファイルは配置されています。
AccuntID
、LicenseKey
に払い出された情報を設定します。
# Enter your account ID and license key below. These are available from # https://www.maxmind.com/en/my_license_key. If you are only using free # GeoLite databases, you may leave the 0 values. AccountID YOUR_ACCOUNT_IDYOUR_ACCOUNT_ID LicenseKey YOUR_LICENSE_KEY # Enter the edition IDs of the databases you would like to update. # Multiple edition IDs are separated by spaces. EditionIDs GeoLite2-Country GeoLite2-City
-
ライセンスキー発行時の注意点
ライセンスキー発行時に、geoipupdate
で使用するか否かのチェックボックスがあり、チェックしないと、geoipupdate
では使用できないキーになります。
CentOS 7 のyum でインストールできる
geoipupdate
のVesion が2.5.0 なので 3.1.1以下を選択しています。この設定ですと、ライセンスキーはハッシュ形式で保存されないため、安全性が低くなる旨の警告がこの後のページで出力されます。私は気にしませんでしたが、気にされる方は yum でのインストールではなく、ソースからビルドをかけるなど実施したほうが良いかもしれません。 -
ディレクトリ作成
を実行したところ、/bin/geoipupdate
と出力されました。/usr/share/GeoIP does not exist
データベースの格納先がないので、ディレクトリを作成します。
mkdir /usr/share/GeoIP
-
スケジュール実行
参考記事と同様に、木曜日に実行するように設定しました。
0 12 * * 4 /bin/geoipupdate # GeoIP Update
以上で、データベースの自動更新の設定は完了です。
djangorestframework で Web API を建てる
djangorestframework で リクエスト送信元のIPアドレスを元に、都市の情報を返す Web API を作成します。
-
geoip2 のインストール
StackOverFlow の記事で、Django 1.11 の場合、Version指定してインストールしていたので、それを参考にバージョン指定しています。
pip install geoip2==2.9.0
-
settings.pyの編集
GEOIP_PATH
を追加します。GEOIP_COUNTRY
と、GEOIP_CITY
もありますが、デフォルト設定で問題ないので、記載しませんでした。
################## # GEOIP SETTINGS ################## GEOIP_PATH='/usr/share/GeoIP'
-
urls.pyの編集
import apis url("^geoip/$",apis.geoip, name="geoip")
-
apis.py
@api_view
デコレータで、関数APIを作りました。
from rest_framework.decorators import api_view from django.contrib.gis.geoip2 import GeoIP2 from rest_framework.response import Response @api_view(['GET']) def geoip(request): g = GeoIP2() client_addr = request.META.get('REMOTE_ADDR') city = g.city(client_addr) return Response(city)
追記. django-geoip2-extras を使う
template で、国コードで制御したい画面項目がある場合は、django-geoip2-extras · PyPI を使うのが良いかと思います。
tempalteタグで使用するまでの手順を記載します。
-
インストール
pip install django-geoip2-extras
-
settings.py に
geoip2_extras.middleware.GeoIP2Middleware
を追加
MIDDLEWARE = ( ..., 'django.contrib.sessions.middleware.SessionMiddleware', 'geoip2_extras.middleware.GeoIP2Middleware', ... )
これで、request.geo_data
に以下の情報が設定されるようになります。
- ip_address
- city
- postal_code
- region
- country_code
- country_name
- latitude
- longitude
-
is_unknown
-
templateで使う
Django のtemplate内では以下のように使用できます。
{% if request.geo_data is None or request.geo_data.country_code == "JP" %} <div class="blog-item"> <!-- blog本文下の広告 --> <ins class="adsbygoogle" style="display:block" data-ad-client="{{ settings.CLEAN_BLOG_GOOGLE_ADS_CLIENT_ID }}" data-ad-slot="{{ settings.CLEAN_BLOG_GOOGLE_ADS_SLOT_ID }}" data-ad-format="auto"></ins> <hr> </div> {% endif %}
-
注意点
template内で使用する際の注意点を記載します。-
Cacheの設定の確認 Django の Cache の設定によっては、templateの評価が行われず、requestごとに判定されない場合があります。
Django’s cache framework | Django ドキュメント | Django にtemplateに対するCache設定についての記載があります。 -
django.core.context_processors.request を有効にする。
template 内で request にオブジェクトにアクセスするには、Django.core.context_processors.request
をTEMPLATE_CONTEXT_PROCESSORS
に登録する必要があります。
-
参考
以下、参考にした記事になります。
-
IPアドレスから地域特定するGeoIP系技術について調べてみた(追記あり)|TechRacho(テックラッチョ)〜エンジニアの「?」を「!」に〜|BPS株式会社
-
Automatic Updates for GeoIP2 and GeoIP Legacy Databases « MaxMind Developer Site
-
geodjango - Django: ImportError: cannot import name ‘GeoIP2’ - Stack Overflow
以上です。
コメント