我正在为 ESP8266 构建一个简单的 API,以便在物联网应用程序中连接,传递一个 JSON 字符串。在此应用程序中,每个站点(位置/地址)有多个监视器(互联网连接设备),每个站点/监视器有多个日志条目。
API 最初设置有如下端点: /api/logentries/
发布一个 JSON 字符串,例如: {"site":"abcd","monitor":"xyz","data_point":"value"}
在对象模型中,Monitor是Site的child,但是为了方便条目的创建和上报,各个设备发布的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 跨站点唯一时保存。
但是,如果两个站点的监视器具有相同的 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 之类的内容来实现,这样可以将此信息作为请求/上下文的一部分提供,并且从规范化的角度来看也更好。但是,这将需要重新刷新许多已部署的设备以反射(reflect)已更改的 API 详细信息,因此我想尽可能避免此类更改,即使经过反射(reflection)这可能是一个更清洁的解决方案/方法 long-术语。)
提前致谢。
最佳答案
您需要编写自己的 SlugRelatedField
子类。适用于 SlugRelatedField
的唯一性约束不适用于您的情况。
这可以通过创建子字段并覆盖 get_value
来检索站点/监视器元组和 to_internal_value
来选择适当的监视器来完成。
关于python - 当 unique_together 应用于 django-rest 时,SlugRelatedField 的查询集值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37108174/