#はじめに
DjangoのREST frameworkを使うようなアプリケーションを持つプロジェクトではよく「uplink」でデータ収集をすることがあります.私はその逆方向の通信を行う「downlink」をする機会があったため,「そもそもuplink時に誰がデータをPOSTしてきてるの?」っていうことを動的に知る必要がありました.
そこで,データPOSTしてくるゲートウェイ等のクライアントのIPアドレスをDBに格納しておいてdownlinkのときに,そのIPアドレスを使おうってことになりました.
#結論
Djangoプロジェクトへのアクセスリクエストに含まれるHTTPヘッダの'REMOTE_ADDR'
からクライアントのIPアドレスを取得してあげれば良いみたいです.
###参考
DjangoでクライアントのIPアドレスを取得する
#実装手順
###前提
Python,Django及びREST frameworkに関して経験のあることを前提として記事を書いております.POSTAPIの作成に関しては以下の記事がわかりやすいと思います.
Django Rest Framework で RESTful な APIを作成する
###環境
CentOS Linux release 7.9.2009 (Core)
Python 3.6.15
Django 3.2.0
djangorestframework 3.12.3
###1.REST frameworkをインストールする
$ pip install djangorestframework
###2.設定ファイルにREST frameworkを追加
※設定ディレクトリ名はconfig
であると仮定してます
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
+ 'rest_framework', # データPOSTAPI
…
]
###3.uplink用のアプリケーションを作成する
$ python manage.py startapp uplink
###4.設定ファイルにuplinkアプリケーションを追加
※設定ディレクトリ名はconfig
であると仮定してます
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework', # データPOSTAPI
+ 'uplink.apps.UplinkConfig', # アップリンク(データ収集)機能
…
]
###5.uplinkアプリケーションのURLを定義する
urlpatterns = [
…
+ path('uplink/', include('uplink.urls')),
…
]
###6.IPアドレスフィールドをカラムに持つモデルを作成する
from django.db import models
from django.utils import timezone
class PostData(models.Model):
"""
POSTされるデータのモデルクラス
create_at: データPOST時刻
client_ipaddr: データをPOSTしたクライアントのIPアドレス
"""
class Meta:
db_table="post_data"
verbose_name='PostData'
verbose_name_plural='PostData'
create_at = models.DateTimeField(
verbose_name='create_at',
blank=False,
null=False,
editable=False, #編集不可
default=timezone.now,
)
client_ipaddr = models.GenericIPAddressField(
verbose_name='Client IP address',
blank=False,
null=False,
default='0.0.0.0',
editable=False, #編集不可
)
###7.adminにモデルを追加する
from django.contrib import admin
from .models import PostData
@admin.register(PostData)
class PostDataAdmin(admin.ModelAdmin):
list_display = (
'create_at',
'client_ipaddr',
)
###8.URLを定義する
from django.urls import path
from . import views
app_name = 'uplink'
urlpatterns = [
path('data_post/', views.CreateData.as_view(), name='data_post'),
]
###9.シリアライザを定義する
※このシリアライザを定義する際に,client_ipaddr = serializers.IPAddressField()
を定義しないとうまくいきませんでした.
"""
データをPOSTするときのシリアライザ
"""
from rest_framework import serializers
from .models import PostData
class PostDataSerializer(serializers.ModelSerializer):
# IPアドレス型のデータとして用意しておく
client_ipaddr = serializers.IPAddressField()
class Meta:
model = PostData
fields = (
'__all__'
)
read_only_fields = ('create_at', 'client_ipaddr', )
###10.Viewを定義する
from rest_framework.views import APIView
from rest_framework import status
from rest_framework.response import Response
from rest_framework.parsers import MultiPartParser, FormParser
from django.utils import timezone
from .serializer import PostDataSerializer
class CreateData(APIView):
"""
ゲートウェイからPOSTされたデータをデータベースに格納する
"""
parser_classes = (MultiPartParser, FormParser, )
def post(self, request, format=None):
# POSTデータのペイロードをシリアライズするために整形
data = {}
data['create_at'] = timezone.localtime(timezone.now())
client_ipaddr = request.META.get('REMOTE_ADDR')
data['client_ipaddr'] = client_ipaddr
# シリアライザにかける
serializer = PostDataSerializer(data=data)
# シラアライズの成否で処理を変更
if serializer.is_valid():
serializer.save()
print('●Valied data post.')
print(serializer.validated_data)
return Response(serializer.validated_data, status=status.HTTP_201_CREATED)
# エラーを吐いたら詳細を見せてもらう
print('●Data post is invalied.')
print(serializer.errors)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
###11.データベースマイグレーション
$ python manage.py makemigrations
$ python manage.py migrate
#まとめ
色々と書きましたが,REST frameworkを問題なく使える方にとっては「結論」の内容とシリアライザを定義するときの注意点だけ覚えていってもらえればいいと思います.Djagnoを使ったdownlinkも限定的なものになってしまいますが,随時書ければなと思います.
※疑問点や修正点などはご連絡頂けると嬉しいです
#続き
この記事の手順を完了したあとの確認方法を書いていませんでした.
【Django】REST frameworkでプロジェクトにデータPOSTしてくるクライアントのIPアドレスをDBに格納する(続)にその確認方法を書きましたので,是非ご確認ください.
#参考
アップリンク(uplink)とは - IT用語辞典 e-Words
DjangoでクライアントのIPアドレスを取得する
IPAddressField in serializers – Django REST Framework
Django Rest Framework で RESTful な APIを作成する