【问题标题】:Django RDBMS model design for rest framework用于REST框架的Django RDBMS模型设计
【发布时间】:2016-06-07 16:06:41
【问题描述】:

我正在使用 Django 和 django-restfframework 来完成以下任务。 我需要这三个模型。 (1) 保存客户信息的人员模型。 (2) 传感器模型和 (3) DataPoint 模型。每个都是一对多的关系。一个人可以有很多传感器,每个传感器可以有很多数据点,但不能反过来。我在我的 models.py 文件中创建了以下模型。 ..

class Person(models.Model):
    first_name = models.CharField(max_length=30, null=False)
    last_name = models.CharField(max_length=30, null=False)

class Sensor(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    name = models.CharField(max_length=100, null=False)
    sensor_id = models.UUIDField(null=True, blank=True)

class DataPoint(models.Model):
    sensor = models.ForeignKey(Sensor, on_delete=models.CASCADE)
    date_time_instance = models.DateTimeField()
    value = models.DecimalField(max_digits=10, decimal_places=4)

Serializer.py 有以下代码...

class PersonSerializer(serializers.ModelSerializer):

    class Meta:
        model = Person
        fields = ('id', 'first_name', 'last_name')


class SensorSerializer(serializers.ModelSerializer):

    person = PersonSerializer()
    class Meta:
        model = Sensor
        fileds = ('id', 'name', 'person')

class DataPointSerializer(serializers.ModelSerializer):

    sensor = SensorSerializer()
    class Meta:
        model = DataPoint
        fileds = ('id', 'date_time_instance', 'value', 'sensor')

views.py 有以下数据点 API 请求代码...

@api_view(['GET', 'POST'])
def datapoint_list(request):
    if request.method == 'GET':
        dp = DataPoint.objects.all()
        serializer = DataPointSerializer(dp, many=True)
        return Response(serializer.data)

    elif request.method == 'POST':
        serializer = DataPointSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

这是我的问题:-

  1. 我是否创建了良好的关系数据库架构?

  2. 似乎当我执行数据点 POST 请求时,我必须提供所有人员和所有传感器信息。我怎样才能只提供数据点请求(时间戳和数据值)并让其他所有事情都得到处理(即正确的传感器和人员检查)?

  3. 非关系数据库方案会有帮助吗?怎么样?

  4. 在哪里可以在我的 django 应用中指定所有请求都是 JSON 请求?

提前感谢您的帮助。

【问题讨论】:

  • 你能澄清一下#2吗?我想我明白您的意思,但是对数据点 API 端点的 POST 请求将创建一个全新的数据点,因此除非您指定,否则无法知道人员和传感器。如果要更新数据点,可以接受 PUT 和 PATCH 方法。如果您设置为仅使用 POST,则可以在 DataPointSerializer 中编写 save() 方法,以便从 URL 中解析 Person 和 Sensor。例如:POST 到 `/api/datapoint///',然后在创建(或更新,如果存在)数据点时从 URL 中提取 kwargs。

标签: django database-design django-rest-framework


【解决方案1】:

在考虑了你的问题之后,我想我明白你想要做什么了。更新数据点没有意义(我猜)所以 POST 确实是唯一感兴趣的创建方法。

序列化程序create() 方法在实例化序列化程序时被调用,因此如果您覆盖它,您可以根据需要指定传感器,它会在save() 中得到处理。您只需要确保在创建序列化程序时传入传感器 - 否则我认为没有任何方法可以正确设置关系。

假设在端点 URL 中指定了传感器,我会这样做。这假设 Sensor 已经存在,但为了使其更健壮,您可以使用 get_or_create() - 尽管在 POST 中包含未使用的 Sensor id 可能会很困难/很奇怪,但使用不同的端点创建一个更有意义新传感器优先:

views.py:

@api_view(['GET', 'POST'])
def datapoint_list(self, request):
  if request.method == 'GET':
    dp = DataPoint.objects.all()
    serializer = DataPointSerializer(dp, many=True)
    return Response(serializer.data)

  elif request.method == 'POST':
    serializer = DataPointSerializer(data=request.data, context = {'sensor': self.kwargs['sensor'],})
    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

serializers.py:

class DataPointSerializer(serializers.ModelSerializer):

    sensor = SensorSerializer()
    class Meta:
        model = DataPoint
        fileds = ('id', 'date_time_instance', 'value', 'sensor')

    def create(self, validated_data):
      sensor = Sensor.objects.get(id=self.context.get('sensor'))
      datapoint = DataPoint.objects.create(sensor=sensor)
      value = validated_data.pop('value')
      datapoint.value = value
      datapoint.save()
      return datapoint

然后,如果您将value 发布到/api/<sensor_id>/ 之类的东西上,那应该可以。如果我错了,希望有人能纠正我。

我希望这会有所帮助——您之前似乎在 POST 中传递了传感器和人员,这应该是一种解决方法。如果这不是您要查找的内容,只需编辑您的问题并提供更多详细信息。

几个注意事项:

如果 Person 是已知的,那么它也可能是 URL 的一部分。如果 Person 是请求用户,则可以从请求中提取该条件并在 create() 方法中使用 - 只需在序列化程序上下文中传递请求。

目前您的 GET 分支返回所有数据点,但如果您使用我提到的 URL,您可以过滤 URL 中的传感器 ID。或者您可能想要所有这些,如果没有更多上下文,很难说出您的目标。

如果您希望它在 POST 上接受多个 value,则需要在 POST 分支的序列化程序实例化中添加 many=True

编辑:我太专注于#2,以至于忘记了您的其他观点。

  1. 我认为您的架构很好——就像我说的那样,没有任何其他上下文很难评估,但是从您所说的数据点、传感器和人员之间的关系来看,这似乎是理想的配置。

  2. 我对非关系数据库了解得不够多,但我不明白为什么在这种情况下会更好。

  3. 我不知道您是否可以设置默认请求格式,尽管这当然是可能的。如果您在 API 端点将“/?format=json”附加到您的请求中,DRF 会正确解释它并仅返回 JSON。

【讨论】:

  • 非常感谢您的回答@dkhaupt,我的问题是正确的,我想知道当我发出帖子请求以输入新的数据点。通过您的解决方案,似乎我至少必须为每个数据点 JSON POST 请求提供人员 ID 和传感器 ID(而不是整个对象),这是没有办法的。
  • 我之前通过自己的 POST 请求创建了 Person 和 Sensor,因此没有未知数。所以重申一下,我的 JSON REST POST 请求的标头为“Content-Type:application/json”,我的数据点 JSON POST 有效负载应该有这个,对吧? { "sensor_id": 1, "person_id": 1, "value": 1.15, }
  • 我不相信你需要'person_id'- 如果传感器 id 是已知的,那应该足够了,因为数据点没有 Person 的外键。当您从 POST 中省略 'person_id' 时会发生什么?
  • @LuckyStarr 您是否尝试在 POST 中省略 person_id
  • @LuckyStarr 如果此答案对您有所帮助,您可以接受它,以便其他有此问题的人知道它对您的情况有所帮助
猜你喜欢
  • 2017-03-27
  • 2018-12-10
  • 2015-12-02
  • 2018-10-02
  • 1970-01-01
  • 2016-05-30
  • 2017-06-04
  • 2013-04-26
  • 1970-01-01
相关资源
最近更新 更多