Django REST框架:验证两个字段上没有pk和UNIQUE索引的串行器列表更新(PUT)

时间:2017-05-26 14:14:10

标签: django rest api validation

我已经花了几天时间阅读这些房子(我有几次rtfm ......或许我还没有理解tfm)。接近几个答案,我担心最终我知道Django / Serilizers(原文如此)是如何工作的。

我将从我的基本问题开始,以保​​持简单,而不是我为使这项工作所做的众多尝试。

我正在尝试执行以下操作:

  1. 工作)从Django rest_framework API获取值列表 基于双索引,其中一个字段在URL中传递 传入(control_sys)并传入第二个字段的多个值 (JSON)提交给API的数据(transactionID)。
  2. 不工作)更新(PUT)基于相同值的列表 逻辑为GET(上图)。
  3. 还没到达目前)创建(POST)基于值的列表 与GET(上图)相同的逻辑。
  4. 如上所述,GET声明正在发挥作用。该视图基于transactionID列表和URL中传递的control_sys(sysID)检索查询集。它将此传递给序列化器并通过API返回数据。

    更新(PUT)无效。我的问题似乎是我没有将模型的pk(id字段)传递给API,并且它在发布到API的数据中不可用。我需要以与GET语句相同的方式检索查询集并将其传递给更新,此时当我尝试验证seriliser时,我收到以下错误:

      

    AttributeError:' QuerySet'对象没有属性' pk'

    Django Rest Framework Validator Code

    第155行的验证者正在提出这个问题

    我很困惑,因为我已经检查过,并且查询集中的每个项都有一个值id(当我引用pk时返回)。我也尝试更新视图中的数据以附加pk / id值无效。

    我正在通过' many = True'以便seriliser知道它是一个接收的查询集而不是单个模型实例。

    到目前为止,我尝试过:

    1. 将id和pk附加到request.data
    2. 使用required = True / False和read_only = True / False明确地将id和pk添加到seriliser的各种尝试
    3. 对ListSerializer进行子类化并使用META:list_serializer_class来控制seriliser的工作方式。
    4. 我知道验证失败但我不知道如何解决这个问题。

      非常欢迎任何建议。

      下面有一些参考信息......我会根据要求发布更多信息。

      型号:

       ## Comms Queue
      class CommsQueue(models.Model):
          # primary key
          # foreign key
          control_sys = models.IntegerField("Control system foreign key (passive)", blank=True, null=True, default=None)
          meter = models.IntegerField("Meter foreign key (passive)", blank=True, null=True, default=None)
          # string
          data = models.CharField("Comm data", max_length=200, blank=True, null=True, default=None)
          # int
          transactionID = models.BigIntegerField("Comms Transaction ID", blank=True, null=False)
          source = models.IntegerField("Originating source for event", blank=True, null=False)
          target = models.IntegerField("Target destination for event", blank=True, null=False, db_index=True)
          priority = models.IntegerField("Comms priority", blank=True, default=0)
          # url
          URI = models.URLField("Comm URI",max_length=200, blank=True, null=True, default=None)
          # bool
          #comm_send = models.BooleanField("Event requires uplink/downlink", blank=False, default=True) # TODO delete?
          comm_sent = models.BooleanField("Uplink/Downlink sent", blank=True, default=False)
          complete_req = models.BooleanField("Require completion notice", blank=True, default=False)
          complete = models.BooleanField("Event complete", blank=True, default=False)
          # date
          create_date = models.DateTimeField("Date created", auto_now=False, auto_now_add=True)
          last_date = models.DateTimeField("Date accessed", auto_now=True, auto_now_add=False)
      
          class Meta:
              unique_together = (("control_sys","transactionID"),)
              index_together = [("control_sys","transactionID"),]
      
          def __unicode__(self):
              return "Transaction ID: %s, Complete: %s" % (str(self.transactionID), str(self.complete))
      

      Serilizer

      class CommsSerialiser(serializers.HyperlinkedModelSerializer):
      URI = ParameterisedHyperlinkedIdentityField(view_name="comms-detail", lookup_fields=(('control_sys', 'sysID'), ('transactionID', 'tID')), read_only=True)
      # convert MySQL bool to int bool
      complete_req = serializers.IntegerField(read_only=False)
      complete = serializers.IntegerField(read_only=False)
      
      class Meta:
          model = CommsQueue
          fields = ('control_sys', 'meter', 'data', 'transactionID', 'source', 'target', 'priority', 'complete_req', 'complete', 'URI')
      
          validators = [
              UniqueTogetherValidator(
                  queryset=CommsQueue.objects.all(),
                  fields=('control_sys', 'transactionID')
              )
          ]
      

      查看

      class CommsDetail(APIView):
      """
      Retrieve, update or delete MULTIPLE comms from queue.
      
      """
      # session permissions
      permission_classes = (permissions.IsAuthenticated, IsAuthedCommQueue,)
      
      def get_object(self, sysID, transactionID_list):
          try:
      
              # get comms queue for control unit ...allow retrieve of complete comms
              comm_objects = CommsQueue.objects.filter(control_sys=sysID,transactionID__in=transactionID_list)
      
              # Auth user for control unit
              self.check_object_permissions(self.request, comm_objects[0])
      
              # get object
              return comm_objects
      
          except ObjectDoesNotExist:
              raise Http404
      
      
      def get(self, request, sysID, format=None):
      
          # build list of transaction ID to retrieve
          transactionID_list = []
          for transaction in request.data:
              transactionID_list.append(transaction['transactionID'])
      
          comms = self.get_object(sysID,transactionID_list)
          serializer = CommsSerialiser(comms, context={'request': request}, many=True)
          return Response(serializer.data)
      
      def put(self, request, sysID, format=None):
      
          # build list of transaction ID to retrieve
          transactionID_list = []
          for transaction in request.data:
              transactionID_list.append(transaction['transactionID'])
              print transaction
      
          comms = self.get_object(sysID,transactionID_list)
          serializer = CommsSerialiser(comms, data=request.data, context={'request': request}, many=True)
      
          if serializer.is_valid():
              serializer.save()
              return Response(serializer.data)
          return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
      

      ' print serilizer'输出:

      CommsSerialiser(<QuerySet[
          <CommsQueue: TransactionID: 313011,
          Complete: False>,
          <CommsQueue: TransactionID: 313013,
          Complete: False>,
          <CommsQueue: TransactionID: 313102,
          Complete: False>
      ]>,
      context={
          u'request': <rest_framework.request.Requestobject>
      },
      data=[
          {
              u'control_sys': 710017,
              u'complete': 1,
              u'data': u'"{data innit}"',
              u'URI': u'http: //172.16.32.40: 8000/api/0.1/comm/710017/313102/',
              u'transactionID': 313102,
              u'complete_req': 1
          },
          {
              u'control_sys': 710017,
              u'complete': 1,
              u'data': u'"{data innit}"',
              u'URI': u'http: //172.16.32.40: 8000/api/0.1/comm/710017/313011/',
              u'transactionID': 313011,
              u'complete_req': 1
          },
          {
              u'control_sys': 710017,
              u'complete': 1,
              u'data': u'"{data arg}"',
              u'URI': u'http: //172.16.32.40: 8000/api/0.1/comm/710017/313013/',
              u'transactionID': 313013,
              u'complete_req': 1
          }
      ],
      many=True): 
          control_sys = IntegerField(allow_null=True, label='Control system foreign key (passive)', max_value=2147483647, min_value=-2147483648, required=False)
          meter = IntegerField(allow_null=True, label='Meter foreign key (passive)', max_value=2147483647, min_value=-2147483648, required=False)
          data = CharField(allow_blank=True, allow_null=True, label='Comm data', max_length=200, required=False)
          transactionID = IntegerField(label='Comms Transaction ID', max_value=9223372036854775807, min_value=-9223372036854775808, required=False)
          source = IntegerField(label='Originating source for event', max_value=2147483647, min_value=-2147483648, required=False)
          target = IntegerField(label='Target destination for event', max_value=2147483647, min_value=-2147483648, required=False)
          priority = IntegerField(label='Comms priority', max_value=2147483647, min_value=-2147483648, required=False)
          complete_req = IntegerField(read_only=False)
          complete = IntegerField(read_only=False)
          URI = ParameterisedHyperlinkedIdentityField(lookup_fields=(('control_sys', 'sysID'), ('transactionID', 'tID')), read_only=True, view_name='comms-detail')
      

0 个答案:

没有答案