爲了實現REST風格的Web API,我最近開始使用Django REST框架(以及Django和Python--我是一個RTOS /嵌入式系統人員!)。目前還沒有任何問題無法用Google解決,但是這個問題讓我現在陷入了幾個小時的困境。Django REST框架 - 發佈包含自然鍵的外鍵字段?
我有一個嵌入式系統,用於監聽與一系列設備相關的事件 - 類似於撥打電話的電話,這是我在這裏爲簡潔起見而討論的。一個電話有一個號碼和一大堆呼叫(它已經)與之相關聯。呼叫具有關聯的電話(發起呼叫的電話)和創建時間。發生呼叫時,應將其發送到API。我有一個嵌入式系統,用於監聽呼叫及其始發電話號碼,並將它們提交給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',)
views.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')
ŧ o測試,我創建了一個號碼爲123456的電話。然後我POST {「srcPhone」:123456}到http://host/calls/
(在urls.py中配置它來運行CallList視圖)。這在/ calls/- 'int'對象的AttributeError中沒有屬性'startswith'。 rest_framework/relations.py中出現異常(第355行)。可以發佈整個跟蹤,如果它會有所幫助。在閱讀關係.py時,它看起來像REST框架沒有按數字查找電話,而是像處理URL一樣處理srcPhone屬性。這通常是真實的,但我希望它通過自然鍵來查找電話,而不是提供URL。我在這裏錯過了什麼?
謝謝!
謝謝你湯姆 - 現在我只能提交一個整數srcPhone號碼的呼叫。 – EwanC
剛剛找到了這個答案,並解決了我的問題!非常好解釋 – zeroliu