gpt4 book ai didi

Django REST Framework - 发布包含自然键的外键字段?

转载 作者:行者123 更新时间:2023-12-04 00:56:41 25 4
gpt4 key购买 nike

我最近开始使用 Django REST 框架(以及 Django 和 Python——我是 RTOS/嵌入式系统人员!)以实现 RESTful Web API。还没有任何无法通过 Google 解决的问题,但是这个问题已经让我难倒了几个小时。

我有一个嵌入式系统,它监听与一系列设备相关的事件——类似于电话调用电话,为了简洁起见,我将在这里讨论。电话有一个号码和大量与之相关的调用(它已调用)。调用具有关联的电话(发出调用的电话)和创建时间。发生调用时,应将其发布到 API。我有一个嵌入式系统,它监听调用及其始发电话号码,并将它们提交给 API。由于嵌入式系统知道电话号码,我希望它提交: {"srcPhone":12345678} 而不是 {"srcPhone":"http://host/phones/5"} 。这避免了我的嵌入式系统需要知道每部电话的主键(或每次要提交调用时按号码获取电话)。

谷歌和 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,)

序列化程序.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')

为了测试,我创建了一个号码为 123456 的电话。然后我 POST {"srcPhone":123456} 到 http://host/calls/(在 urls.py 中配置以运行 CallList View )。这会在/calls/处产生 AttributeError -“int”对象没有属性“startswith”。异常发生在 rest_framework/relations.py(第 355 行)中。如果有帮助,可以发布整个跟踪。在阅读了relationship.py 后,看起来REST 框架并没有按号码查找电话,而是将srcPhone 属性当作一个URL 来处理。这通常是正确的,但我希望它通过自然键查找电话,而不是提供 URL。我在这里错过了什么?

谢谢!

最佳答案

你要找的是SlugRelatedField .见 docs here .

but processing the srcPhone attribute as if it was a URL.


确切地。您正在使用 HyperlinkedModelSerializer ,所以 srcPhone key 默认使用超链接关系。 'int' object has no attribute 'startswith'您看到的异常是因为它需要一个 URL 字符串,但接收一个整数。真的应该导致描述性验证错误,所以我有 created a ticket for that .
如果您改为使用类似这样的序列化程序:
class CallSerializer(serializers.HyperlinkedModelSerializer):
srcPhone = serializers.SlugRelatedField(slug_field='number')

class Meta:
model = Call
fields = ('url', 'created', 'srcPhone')
然后 'srcPhone'键将改为使用 'number' 表示关系关系目标上的字段。
我计划在不久的某个时候对关系文档进行更多的工作,所以希望这在 future 会更加明显。

关于Django REST Framework - 发布包含自然键的外键字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14367595/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com