【发布时间】:2016-09-03 15:21:35
【问题描述】:
我正在为 ESP8266 构建一个简单的 API,以便在 IoT 应用程序中连接,并传递一个 JSON 字符串。在此应用程序中,每个站点(位置/地址)有多个监视器(互联网连接设备),每个站点/监视器有多个日志条目。
API 最初是使用如下端点设置的: /api/logentries/
发布一个 JSON 字符串,例如: {"site":"abcd","monitor":"xyz","data_point":"value"}
在对象模型中,Monitor 是 Site 的子对象,但是为了方便创建条目和上报,各设备发布的 LogEntry 的 JSON 格式将这个结构扁平化了,也就是说 LogEntry 模型也有 FK 关系站点和监视器。在下面的代码中,“textID”是在 API 上下文中用于站点/监视器的 ID(例如,PK 值对于 API 调用者保持“隐藏”)。
在models.py中:
class Site(models.Model):
name = models.CharField(max_length=32)
textID = models.CharField(max_length=32, blank=True, db_index=True, unique=True)
class Monitor(models.Model):
textID = models.CharField(max_length=32)
site = models.ForeignKey(Site, on_delete=models.CASCADE)
class Meta:
unique_together = ('site', 'textID')
class LogEntry(models.Model):
site = models.ForeignKey(Site, on_delete=models.CASCADE)
monitor = models.ForeignKey(Monitor, on_delete=models.CASCADE)
data_point = models.CharField(max_length=8, default='')
为了让它在单个站点上工作,我创建了一个自定义序列化程序:
class LogEntrySerializer(serializers.HyperlinkedModelSerializer):
site = serializers.SlugRelatedField(slug_field='textID', queryset=Site.objects.all())
monitor = serializers.SlugRelatedField(slug_field='textID', queryset=Monitor.objects.filter())
class Meta:
model = LogEntry
fields = ('pk', 'site', 'monitor', 'data_point', )
这适用于读取有效数据,并在所有监视器 ID 跨站点唯一时保存。
但是,如果两个站点的 Monitor 具有相同的 textID,例如“Site1/001”和“Site2/001”这会中断,因为 Monitor.objects.all() 会导致检索到多个记录(这是有道理的,并且是预期的行为)。
我想要做的是将第二个查询集(用于监视器)限制为指定站点,以避免此错误。
This post 几乎回答了我的问题,但是它受益于请求对象中可用的第二个字段值(用户),在这种情况下不可用。
有没有一种方法可以检索 Site.pk 或 Site.textID 以正确解析查询集值——例如queryset=Monitor.objects.filter(site__textID=xxx)--“xxx”是什么?还是我需要完全覆盖序列化程序(而不依赖于 SlugRelatedField)?或者其他一些可能有效的方法?
(顺便说一句:我认识到这可以通过将 URL 模式修改为 /api///logentries 之类的东西来实现,然后将这些信息作为请求/上下文的一部分提供,并且从规范化的角度来看会也更好。然而,这将需要重新刷新许多已经部署的设备以反映更改的 API 详细信息,所以我想尽可能避免这种更改,即使经过反思,这可能是一个更清洁的解决方案/方法——术语。)
提前致谢。
【问题讨论】:
标签: python json django django-rest-framework