在Django Rest Framework中向JSON响应添加多个模型和自定义字段 [英] Add multiple models and custom fields to a json response in Django Rest Framework

查看:105
本文介绍了在Django Rest Framework中向JSON响应添加多个模型和自定义字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Python / Django编程的新手,但是我在做的一个个人项目中陷入了困境。我的问题是我想根据我的应用程序的不同模型返回自定义响应,其中一些值将来自自定义查询,而其他值则是模型本身的一部分。

i'm new into Python/Django programming and i got stuck with something in a personal project that i'm doing. My issue is that i want to return a custom response based on different models of my application, some of the values will come from custom queries and others are part of the models itself.

因此,我在我的应用中使用了以下模型(删除了一些字段以使发布时间不会太长):

So, i have the following models in my app(some fields were deleted to not make the post too long):

class Parking(models.Model):
    google_id = models.CharField(max_length=100)
    short_name = models.CharField(max_length=100)
    long_name = models.CharField(max_length=300)
    price = models.DecimalField(max_digits=4, decimal_places=2, null=True, blank=True)

class ParkingLot(models.Model):        
    parking = models.ForeignKey(Parking, on_delete=models.CASCADE, null=False, related_name='parkinglots')
    size = models.ForeignKey(Size, on_delete=models.DO_NOTHING, null=False, related_name='size')
    width = models.DecimalField(max_digits=3, decimal_places=2, null=True, blank=True)
    height = models.DecimalField(max_digits=3, decimal_places=2, null=True, blank=True)

class ParkingAvailability(models.Model):
    parkinglot = models.ForeignKey(ParkingLot, on_delete=models.CASCADE, null=False, related_name='availability')
    available = models.BooleanField(null=False, blank=False)
    from_hour = models.TimeField(auto_now=False, auto_now_add=False, default='09:00:00')
    to_hour = models.TimeField(auto_now=False, auto_now_add=False, default='21:00:00')

这些模型是我数据库表的精确表示。都好。我的问题是,现在我想进行自定义json响应,这需要在这些表上运行查询,但不显示整个对象,在某些情况下,基于过滤器的自定义字段或我需要在表上运行的操作(对于例如,基于parking_id和size_id的停车位数量)。因此,假设我需要的东西看起来像这样:

These models are an exact representation of my database tables. All good. My problem is that now i want to make a custom json response, this needs to run queries over these tables but not show the entire objects and in some cases, custom fields based on filter or operations that i need to run over the tables (for example, numbers of parkinglots based on a parking_id and size_id). So, let's assume that i need something that will look like this:

[
    {
        "id": 1,
        "google_id": "JSDKKLAD888737283",
        "short_name": "Fernandez Albano",
        "long_name": "Comunidad Fernandez Albano",
        "price": 18.5,
        "parkinglots": 88, 
        "hours": {
            "from_hour": "09:00:00",
            "to_hour": "21:00:00",
        }
    }
]

第一个4个json值来自Parking模型,字段parkinglots是带有一些过滤器(parking_id,size_id)的parkinglots模型的.count()。可用性是来自ParkingAvailability模型的自定义查询,我可以通过我的parkinglot_id值进行访问。

The first 4 json values come from Parking model, the field parkinglots is the .count() of the parkinglots model with some filters (parking_id, size_id). Availability is a custom query from ParkingAvailability model that i can access through my parkinglot_id value.

到目前为止,我有类似的内容,但是在我看来,这不是确定的:

So far, i have something like this but it seems to me that is not ok:

class parkingList(APIView):
    def get(self, request, format=None):
        parkinglotNumber=ParkingLot.objects.filter(parking_id = 2, size_id = 1).count()
        parkinglot = ParkingLot.objects.filter(parking_id = 2, size_id = 1)
        hours = ParkingAvailability.objects.filter(parkinglot__in=parkinglot, available=True).aggregate(Min('from_hour'), Max('to_hour'))

        content = {
            'parkinglots_number': parkinglotNumber,
            'hours': hours
        }

        return Response(content)

所以,我的问题是:


  1. 可以运行这样的查询吗?如果要(例如)将我的停车位模型完全添加到该响应中,我将需要运行另一个查询,例如 ParkingLot.objects.filter(parking_id = 2,size_id = 1),并将其添加到我的停车响应中?

  2. 我的序列化器序列化了所有模型字段,但在这种情况下我不使用它,可以在没有序列化器类的情况下返回它吗?

  3. 我怎么能建立复杂的JSON响应?像在这种情况下,我需要从不同的模型和自定义字段向json添加不同的部分。

感谢您的帮助!抱歉,我的英语不是我的母语。

Thanks for your help! Sorry for my English but is not mi native language.

PS:我的序列化器类返回模型的所有信息。该类的一部分是这样的:

PS: My serializer class return all the information of my models. A part of the class it's like this:

class ParkingLotSerializer(serializers.ModelSerializer):
    size = SizeSerializer(many=False, read_only=True)
    availability = ParkingAvailabilitySerializer(many=True, read_only=True)
    class Meta:
        model = ParkingLot
        fields = ['id', 'price', 'floor', 'number', 'width', 'size', 'availability']

class ParkingSerializer(serializers.ModelSerializer):
    adress = AdressSerializer(many=False, read_only=True)
    parkinglots = ParkingLotSerializer(many=True, read_only=True)
    class Meta:
        model = Parking
        fields = ['id', 'google_id', 'price', 'short_name', 'long_name', 'adress', 'parkinglots' ]


推荐答案

您的其他相关模型应该可以通过 Parking 对象的 related_name 访问。 code>。例如,要访问相关的 ParkingLot ,您可以执行 obj.parkinglots.count()。如果需要,您甚至可以进一步过滤,例如 obj.parkinglots.filter(size_id = 1).count()。因此,您可以使用 SerializerMethodField

Your other related models should be available through the Parking object via their related_name. For example, to access related ParkingLots, you could do obj.parkinglots.count(). You could even further filter if that was needed, such as obj.parkinglots.filter(size_id=1).count(). Because of this, you could use a SerializerMethodField.

class ParkingSerializer(serializers.ModelSerializer):
    ...
    parkinglots_count = serializers.SerializerMethodField()

    ...
    def get_parkinglots_count(self, obj):
        return obj.parkinglots.count()

您可以将字段重命名为对您的api有意义的名称,但是使用的方法应该为 get_< FIELD_NAME> ,并确保将其添加到您的字段 Meta 属性!如果您想做更多的自定义字段,可以使用类似的方法。

You can rename the field to whatever makes sense for your api, but the method used should be get_<FIELD_NAME>, and be sure to add it to your fields Meta attribute! If you'd like to do more custom fields, this can work similarly.

要解决您的问题:


可以这样运行查询吗?如果要(例如)将我的停车位模型完全添加到该响应中,我将需要运行另一个查询,例如 ParkingLot.objects.filter(parking_id = 2,size_id = 1),并将其添加到我的停车响应中?

It's ok to run queries like that? If want to add (for example) my parkinglot model entirely to that response i will need to run another query like "ParkingLot.objects.filter(parking_id = 2, size_id = 1)" and add it to my parking response?

这可能会导致称为 n + 1 的问题,因为您需要运行每个序列化器实例的查询。因此,在清单上,如果您退还了25个停车场,则可能会运行25个计数查询。您可以通过执行>注释来解决此问题您的查询集以帮助减少查询次数。也就是说,是的,很好!

This can cause what's called an n+1 problem, since you will need to run a query for each serializer instance. So on your list, if you returned 25 parking lots, you might run 25 count queries. You can get around this by doing things like annotating to your queryset to help reduce the query count. That said, yes it's fine! It's really common to do things like this.


我的序列化程序将所有模型字段序列化,但是在这种情况下,我不使用它,可以在没有序列化程序类的情况下返回它吗?

My serializer serialize all the models fields but in this case i don't use it, it's ok to return this with no serializers class?

我想我明白。您是在询问不使用的字段的序列化吗?你绝对可以做到的。如果您有兴趣动态关闭字段(即时关闭或使用序列化程序),请查看 django-restql (对不起的插件很抱歉!)。

I think I understand. You're asking about serializing fields you don't use? You definitely can do that. If you're interested in dynamically turning off fields (either on the fly, or when you use the serializer), look into something like django-restql (sorry for the shameless plug!).


我如何构建复杂的json响应?像在这种情况下,我需要从不同的模型和自定义字段向json添加不同的部分。

How i can build complex json response? Like in this case, i need to add different part to my json from different models and custom fields.

只要数据传递具有您所需的内容后,您可以制作一个序列化器。只需将字典传递给序列化器以在api上返回序列化器,这种情况并不少见。序列化器不一定需要与模型绑定,如答案所述,您可以根据需要创建自己的自定义字段以进行工作。 Django Rest Framework的好教程涉及非模型序列化程序。

As long as the data you pass in has what you need, you can make a serializer. It's not uncommon to make a serializer that you just pass a dictionary in to in order to return it on your api. Serializers don't necessarily need to be tied to models, and as covered in the answer, you can make your own custom fields to do work if needed. Django Rest Framework has a good tutorial that touches on non-model serializers.

这篇关于在Django Rest Framework中向JSON响应添加多个模型和自定义字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆