私は最近、RESTful Web API を実装するために、Django REST フレームワーク (および Django と Python - 私は RTOS/組み込みシステム担当者です!) を使い始めました。Google で解決できなかった問題はまだありませんが、この問題で数時間困惑しています。
私は、さまざまなデバイスに関連付けられているイベントをリッスンする組み込みシステムを持っています。これは、簡潔にするためにここで説明する通話を行う電話に似ています。電話には、番号と、それに関連付けられた (それが行った) 多数の通話があります。通話には、関連付けられた電話 (通話を行った電話) と作成時刻があります。呼び出しが発生すると、API に POST する必要があります。通話と発信元の電話番号をリッスンし、API に送信する組み込みシステムがあります。組み込みシステムは電話番号を知っているので、{"srcPhone":12345678}
ではなく: を送信してほしいと思い{"srcPhone":"http://host/phones/5"}
ます。これにより、組み込みシステムがすべての電話の主キーを知る必要がなくなります (または、電話を送信するたびに番号で電話を取得する必要がなくなります)。
Google と Django のドキュメントでは、自然キーを使用してこれを実現できることが示唆されました。私の試みは次のとおりです。
models.py
from django.db import models
from datetime import datetime
from pytz import timezone
import pytz
from django.contrib.auth.models import User
# Create your models here.
def zuluTimeNow():
return datetime.now(pytz.utc)
class PhoneManager(models.Manager):
def get_by_natural_key(self, number):
return self.get(number=number)
class Phone(models.Model):
objects = PhoneManager()
number = models.IntegerField(unique=True)
#def natural_key(self):
# return self.number
class Meta:
ordering = ('number',)
class Call(models.Model):
created = models.DateTimeField(default=zuluTimeNow, blank=True)
srcPhone = models.ForeignKey('Phone', related_name='calls')
class Meta:
ordering = ('-created',)
ビュー.py
# Create your views here.
from radioApiApp.models import Call, Phone
from radioApiApp.serializers import CallSerializer, PhoneSerializer
from rest_framework import generics, permissions, renderers
from rest_framework.reverse import reverse
from rest_framework.response import Response
from rest_framework.decorators import api_view
@api_view(('GET',))
def api_root(request, format=None):
return Response({
'phones': reverse('phone-list', request=request, format=format),
'calls': reverse('call-list', request=request, format=format),
})
class CallList(generics.ListCreateAPIView):
model = Call
serializer_class = CallSerializer
permission_classes = (permissions.AllowAny,)
class CallDetail(generics.RetrieveDestroyAPIView):
model = Call
serializer_class = CallSerializer
permission_classes = (permissions.AllowAny,)
class PhoneList(generics.ListCreateAPIView):
model = Phone
serializer_class = PhoneSerializer
permission_classes = (permissions.AllowAny,)
class PhoneDetail(generics.RetrieveDestroyAPIView):
model = Phone
serializer_class = PhoneSerializer
permission_classes = (permissions.AllowAny,)
serializers.py
from django.forms import widgets
from rest_framework import serializers
from radioApiApp import models
from radioApiApp.models import Call, Phone
class CallSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Call
fields = ('url', 'created', 'srcPhone')
class PhoneSerializer(serializers.HyperlinkedModelSerializer):
calls = serializers.ManyHyperlinkedRelatedField(view_name='call-detail')
class Meta:
model = Phone
fields = ('url', 'number', 'calls')
http://host/calls/
テストするために、番号 123456 の電話を作成します。次に、(CallList ビューを実行するように urls.py で構成されている)に POST {"srcPhone":123456} を送信します。これにより、/calls/ で AttributeError が返されます - 「int」オブジェクトには属性「startswith」がありません。例外は、rest_framework/relations.py (355 行目) で発生します。役立つ場合は、トレース全体を投稿できます。Relations.py を読むと、REST フレームワークは電話を番号で検索するのではなく、srcPhone 属性を URL であるかのように処理しているように見えます。これは通常は当てはまりますが、URL を提供するのではなく、自然キーで Phones を検索するようにしたいと考えています。ここで何を見逃したのですか?
ありがとう!