用Django反序列化嵌套的JSON API响应。

问题描述 投票:0回答:1

我对DRF和序列化deserializing很陌生。在电晕病毒期间,我在慢慢的为自己的企业建立一个仪表盘,并学习代码。我是有点深陷其中,但是在upwork上花了一万多块钱在开发人员身上,并没有真正得到什么结果,我想,我有什么损失呢?

我们的软件供应商有一个完整的API,可以满足我们的需求 https:/developer.myvr.comapi。但绝对没有仪表板来报告有关我们客户预订数据的统计数据。

最终的结果将是同步的一些数据从他们的API到我的数据库,这将是通过AWS托管。我选择这样做是由于必须对API中的数据进行一些后处理。例如,我们需要计算出租率(这不是一个终端),从我们的会计连接和其他一些小的计算中,数据还没有在提供的API中。 我原本想只使用API中的数据,但由于上述原因,我很犹豫。

这是背景故事,下面是问题。

  1. API的响应非常复杂,而且嵌套多次,什么是最好的做法来提取复制数据的结构到我自己的Database?我是否要为每个字段手动创建模型?

响应示例。

```{
"uri": "https://api.myvr.com/v1/properties/b6b0f2fe278f612b/", 
"id": "b6b0f2fe278f612b", 
"key": "b6b0f2fe278f612b", 
"accessDescription": null, 
"accommodates": 11, 
"active": false, 
"addressOne": "11496 Zermatt Dr", 
"addressTwo": null, 
"allowTurns": true, 
"amenities": "https://api.myvr.com/v1/property-amenities/?propertyId=b6b0f2fe278f612b", 
"automaticallyApprove": false, 
"baseNightlyRate": "395.00", 
"baseRate": {
    "uri": "https://api.myvr.com/v1/rates/660c299d4785c32e/", 
    "id": "660c299d4785c32e", 
    "key": "660c299d4785c32e", 
    "externalId": null, 
    "baseRate": true, 
    "changeoverDay": null, 
    "created": "2019-01-19T08:02:36Z", 
    "currency": "USD", 
    "endDate": "2020-01-18", 
    "minStay": 3, 
    "modified": "2019-01-19T08:02:36Z", 
    "monthly": 0, 
    "name": "Base Rate", 
    "weekNight": 39500, 
    "nightly": 39500, 
    "position": 0, 
    "property": {
        "name": "API Demo Property", 
        "uri": "https://api.myvr.com/v1/properties/b6b0f2fe278f612b/", 
        "id": "b6b0f2fe278f612b", 
        "externalId": null, 
        "key": "b6b0f2fe278f612b", 
        "slug": "api-demo-property"
    }, 
    "ratePlan": {
        "uri": "https://api.myvr.com/v1/rate-plans/862caa3f5267602d/", 
        "key": "862caa3f5267602d", 
        "name": "Default Rates for Property"
    }, 
    "repeat": true, 
    "startDate": "2020-01-18", 
    "weekend": 0, 
    "weekendNight": 0, 
    "weekly": 250000
}, 
"bathrooms": "4.0", 
"bedrooms": 4, 
"bookingUrl": "https://myvr.com/reservation/redirect/booking/b6b0f2fe278f612b/", 
"checkInTime": "16:00:00", 
"checkOutTime": "10:00:00", 
"city": "Truckee", 
"commissionStructure": null, 
"countryCode": "US", 
"created": "2016-01-19T00:01:48Z", 
"currency": "USD", 
"customFields": {}, 
"description": "Luxurious living, scenic mountain setting, entertainment galore. Located on a quiet street in Tahoe Donner, our well equipped modern home is nestled into the wilderness. A babbling creek greets visitors approaching the front step as it collects into a small pond with a cascading waterfall. <br/>\n<br/>\nInside, over 3,000 sqft of luxurious living space divides itself between two floors. On the first floor, a beautiful kitchen with granite counters, gas stove and stainless steel appliances opens to a large great room centered around a wood burning fireplace and featuring 30' soaring ceilings. A spacious loft overlooks the great room, showcasing a large poker/card table. Upstairs features a large entertainment room, complete with wet bar, shuffleboard table, and state-of-the-art television setup with surround sound. The scenic backyard is accessible from a large deck featuring a new hot tub with seating for 7.", 
"externalId": null, 
"feePlan": {
    "uri": "https://api.myvr.com/v1/fee-plans/4d1c44383755051b/", 
    "key": "4d1c44383755051b", 
    "name": "Default Fees for Listing"
}, 
"headline": "Beautiful Four Bedroom Lake Front Property", 
"houseRules": null, 
"instantBookingsEnabled": false, 
"lat": "39.3422523000", 
"level": "unit", 
"localAreaDescription": "Tahoe Donner is a year round activity resort. The amenities include private beach/boat launching facilities, pools, recreation center, tennis, horseback riding, golf, downhill skiing as well as cross country skiing. Truckee is a historical mining town-having a western feel but also has museums, theaters, fine dining plus 2 large supermarkets-all less than 3 miles from the house. Our home is also located within a 15 minute drive to 4 major ski resorts. Downtown Reno is a short 40 minute drive away for those seeking a night on the town or the thrill of a Nevada casino.", 
"lon": "-120.2271947000", 
"lowestNightlyRate": "395.00", 
"manual": "", 
"modified": "2019-10-18T17:18:43Z", 
"name": "API Demo Property", 
"owner": null, 
"postalCode": "96161", 
"ratePlan": {
    "uri": "https://api.myvr.com/v1/rate-plans/862caa3f5267602d/", 
    "key": "862caa3f5267602d", 
    "name": "Default Rates for Property"
}, 
"ratePlanLocked": false, 
"region": "CA", 
"shortCode": "API", 
"size": 3000, 
"slug": "api-demo-property", 
"suitableElderly": "yes", 
"suitableEvents": "unknown", 
"suitableGroups": "yes", 
"suitableHandicap": "no", 
"suitableInfants": "unknown", 
"suitableKids": "yes", 
"suitablePets": "no", 
"suitableSmoking": "no", 
"transitDescription": null, 
"type": "house", 
"weekendNights": [
    5, 
    6
]

}```

  1. 我认为填充数据库的最好方法是运行一个自定义的管理命令,运行一个一次性的脚本,我之前已经用另一个数据库做过了,然而我还是被卡住了,因为我真的不想手动写这些模型。另外一个担心的问题是,如果缺少一个字段或者结构发生变化。

这个项目绝对超出了我的能力范围,而且非常有野心,但我会感谢任何人的任何反馈或建议。

谢谢,Darren

json django django-rest-framework
1个回答
0
投票

所以我对这个问题并没有什么兴趣,但最后还是自己解决了。希望有人上网查一下,可能会有帮助。

import requests
from rest_framework.response import Response
from django.core.management.base import BaseCommand, CommandError
from reservation.models import Reservation
import time

MYVR_URL = 'https://api.myvr.com/'
MYVR_RESERVATION = 'v1/reservations/?limit=100'

headers = {
    'Authorization': 'Basic SOmeAPiCodeHeRe123=',
}


class Command(BaseCommand):
    help = 'Imports new properties and saves the objects in the database'

    def handle(self, *args, **options):

        url = MYVR_URL + MYVR_RESERVATION
        print("Populating Reservations")

        def looping_api(url, headers):
            while url:
                r = requests.request("GET", url, headers=headers)
                url = r.json().get('next')
                props_data = r.json().get('results')
                start_time = time.time()

                for prop in props_data:
                    try:
                        created = Reservation.objects.update_or_create(
                            myvr_key=prop.get('key'),
                            adults=prop.get('adults'),
                            children=prop.get('children'),
                            checkin=prop.get('checkIn'),
                            checkout=prop.get('checkOut'),
                            checkinTime=prop.get('checkInTime'),
                            checkoutTime=prop.get('checkOutTime'),
                            guestFirstName=prop.get('firstName'),
                            dateCreated=prop.get('created'),
                            dateBooked=prop.get('dateBooked'),
                            dateCancelled=prop.get('dateCanceled'),
                            contact=prop.get('contact').get('name'),
                            contact_key=prop.get('contact').get('key'),
                            guest_type=prop.get('guestType'),
                            property_name=prop.get('property').get('name'),
                            property_key=prop.get('property').get('key'),
                            source_code=prop.get('source').get('code'),
                            source_name=prop.get('source').get('name'),
                            total_due=prop.get('quote').get('totalDue'),
                            total_refundables=prop.get(
                                'quote').get('totalRefundableFees'),
                            total_nonrefundables=prop.get(
                                'quote').get('totalNonrefundableFees'),
                            reference_id=prop.get('referenceId'),

                        )
                        print(
                            f"Added obj {prop.get('key')}")

                    except AttributeError as error:
                        print(f"{error} attribute is null or owner booking")

                url = r.json().get('next')
                print(r.json().get('next'))
                print(len(props_data))
                end_time = time.time()
                duration = (end_time - start_time)
                print(duration)

        looping_api(url, headers)
© www.soinside.com 2019 - 2024. All rights reserved.