选择了多个设备的帖子组名称

时间:2017-03-02 02:16:21

标签: python django django-rest-framework

我正在尝试为设备组和设备创建api。设备组可以有多个设备,我希望设备组具有多个设备的后api,因为只有在选择了设备且用户可能选择多个设备然后创建新组时才会显示组创建。这样,在创建组时,这些选定的设备也应显示为device_list

这是我的代码,我不确定如何发布请求

class BaseDevice(PolymorphicModel):
  name = models.CharField(max_length=250, blank=False, null=False)
  group = models.ForeignKey('DeviceGroup', related_name="groups", null=True, blank=True)

class Device(BaseDevice):
  description = models.TextField(blank=True, null=True)

class DeviceGroup(models.Model):
    name = models.CharField(max_length=250, blank=False, null=False)  

class DeviceIdSerializer(serializers.ModelSerializer):
    id = serializers.UUIDField(source='token', format='hex', read_only=True)
    class Meta:
        model = Device
        # id is the token of the device and name is the name of the device
        fields = ('id', 'name')

class DeviceGroupSerializer(serializers.ModelSerializer):
    name = serializers.StringRelatedField()
    device_list = DeviceIdSerializer(read_only=False, many=True, required=False, source="groups")
    class Meta:
        model = DeviceGroup
        # name is the name of group created and device_list is the list of devices with id(token) and device name
        fields = ('id', 'name', 'device_list')

    def create(self, validated_data):
        print ('validated_data', validated_data)
        device_list_data = validated_data.pop('device_list')
        group = DeviceGroup.objects.create(**validated_data)
        for device_list in device_list_data:
            BaseDevice.objects.create(group=group, **device_list)
        return group

class DeviceGroupAPIView(APIView):
    permission_classes = (permissions.IsAuthenticated,)

    def get_object(self, user, token):
        try:
            return BaseDevice.objects.filter(owner=user).get(token=token)
        except ObjectDoesNotExist:
            return error.RequestedResourceNotFound().as_response()


    def post(self, request, token=None, format=None):
        device_group_instance = DeviceGroup.objects.get(token=token)
        for device_token in request.data['devices']:
            device = Device.objects.get(token=device_token, owner=request.user)
            device.group = device_group_instance

这是我的api设计

{
   "data":[
      {
         "id":1,
         "name":"Home",
         "device_list":[
            {
               "id":"481cfef5a4884e52a63d135967fbc367",
               "name":"Oxygen Provider"
            },
            {
               "id":"7eb006d6db50479aa47f887da0d4f10e",
               "name":"Fan Speed"
            }
         ]
      },
      {
         "id":2,
         "name":"Business",
         "device_list":[

         ]
      }
   ]
}

更新

url(r'^device_group/(?P<token>[0-9a-f]+)/add$', DeviceGroupAPIView.as_view(), name='device_group'),

1 个答案:

答案 0 :(得分:1)

我已经改变了你的代码

class BaseDevice(PolymorphicModel):
    name = models.CharField(max_length=250, blank=False, null=False)
    group = models.ForeignKey('DeviceGroup', related_name="groups", null=True, blank=True)

class Device(BaseDevice):
    description = models.TextField(blank=True, null=True)

class DeviceGroup(models.Model):
    name = models.CharField(max_length=250, blank=False, null=False)

class DeviceIdSerializer(serializers.ModelSerializer):
    id = serializers.UUIDField(source='token', format='hex', read_only=True)
    # token does not exist in your model so this will not be included
    class Meta:
        model = Device
        # id is the token of the device and name is the name of the device
        fields = ('id', 'name')

class DeviceGroupSerializer(serializers.ModelSerializer):
    device_list = DeviceIdSerializer(read_only=False, many=True, required=False, source="groups")
    class Meta:
        model = DeviceGroup
        # name is the name of group created and device_list is the list of devices with id(token) and device name
        fields = ('id', 'name', 'device_list')

    def create(self, validated_data):
        print ('validated_data', validated_data)
        device_list_data = validated_data.pop('groups', [])
        # notice that I pop 'groups' because validation changes the input data 
        # to match the field names
        # Also since it is not required I've added a default value
        group = DeviceGroup.objects.create(**validated_data)
        devices = [BaseDevice(group=group, **device_list) for device_list in device_list_data] 
        BaseDevice.objects.bulk_create(devices)
        # Use bulk create when you have to create multiple objects
        # It hits the db only once instead of multiple times
        return group

class DeviceGroupAPIView(ModelViewSet):
    permission_classes = (permissions.IsAuthenticated,)
    serializer_class = DeviceGroupSerializer
    queryset = DeviceGroup.objects.all()
    # Although I have used ModelViewSet, you could use any other one
    # I used this so that I don't need to write the code for create,
    # update, delete or list


# urls.py
router = routers.DefaultRouter()
router.register(r'device_group', DeviceGroupAPIView, base_name='device_group')
# this gives the following urls
# /device_group/ POST to create, GET to list    
# /device_group/(?<pk>\d+)/  GET to retrieve single DeviceGroup, PATCH/PUT to update it, and DELETE to delete it

这是用于创建带有一堆设备的新DeviceGroup的POST的JSON结构

{
   "name":"Group Name",
   "device_list":[
      {
         "name":"Device 1"
      },
      {
         "name":"Device 2"
      },
      {
         "name":"Device 3"
      }
   ]
}

希望这有帮助

此外,您应该阅读有关Django-Rest-Framework

的更多信息