1

我应该如何通过 setup.py 将数据从 .json 文件加载到数据库?

我一直在尝试解决这个问题超过 6 小时。我查看了 PonyORM 文档和 JSON 文档。我无法找到足够的信息来解决问题。

entity.py 文件应该是正确的,仅供参考,我已将数据库的预期结构附加为图像。populate_database() 信息在创建后添加到数据库中。这按预期工作。

config.py 确实可以正常工作。

首先我运行这段代码来创建数据库和表:

    #entities.py
    from datetime import date
    from pony.orm import *

    # creating db
    db = Database()
    db.bind('sqlite', 'db/mydata.sqlite', create_db=True)

    # defining the brand class
    class Brand(db.Entity):
            name = PrimaryKey(str)                          #Primary Key - Brand, /only one/
            nationality = Required(str)                     #Nationality, /only one/
            cars = Set('Car')                               #Brand can have multiple cars, /one or more/

    # defining the car class
    class Car(db.Entity): 
            id = PrimaryKey(int, auto=True)                 #Primary Key - Car ID, /only one/
            model = Required(str)                           #Model, /only one/
            price = Required(float)                         #Price, /only one/
            availability = Required(int)                    #Availability, /only one/
            brand = Required(Brand)                         #A car must have only one brand, /only one/
            order = Optional('Order')                       #A car may or may not belong to an order, /one or none/

    # defining the order class
    class Order(db.Entity):
            id = PrimaryKey(int, auto=True)                 #Primary Key - Order ID, /only one/
            dop = Required(date)                            #Date of purchase, automatically set when record is added, /only one/
            cars = Set(Car)                                 #Order can have multiple cars, /one or more/
            customer = Required('Customer')                 #Customer to whom the order belongs, /only one/

    # defining the customer class
    class Customer(db.Entity):
            number = PrimaryKey(str, 11)                    #Primary Key - Phone Number (because it is a unique attribute), /only one/
            name = Required(str)                            #First name, /only one/
            surname = Required(str)                         #Surname, /only one/
            orders = Set(Order)                             #Order, One customer could have multiple orders, /one or more/

    db.generate_mapping(create_tables=True)

    @db_session
    def populate_database():

            Fiat = Brand(name='Fiat', nationality='Italian')
            car1 = Car(model='Punto', price='123.00', availability='5', brand=ferrari)
            jay= Customer(number='01211100001', name='Jay',surname='Son')
            order1 = Order(dop='01/01/2017', cars=car1, customer=jay)
            order1.cars.add(car1)

    populate_database() 

在我运行此代码以将数据从 json 文件加载到数据库后:

#setup.py
import json
import config
from entities import *
'''
    Setup module
    ===========

    The setup module should have all the methods that has to be executed before
    the application is started (i.e. seeding the database).
'''


'''
    Seed the database with information from the json dump file.
    NOTE:   this method is specific to each application, which means you have
            to write your import method for your application.
'''
@db_session
def seed_database(dump_filename):
    # reading the json file
    data = json.load(open(dump_filename, 'r'))

    # going through the list of customers
    for record in data['Customer']:
        customer = Customer(name = record['name'],
                          surname = record['surname'],
                            number = record['number'])

    # going through the list of brands
    for record in data['Brand']:
        brand = Brand(name = record['name'],
                      nationality = record['nationality'])


    # going through the list of cars
    for record in data['Car']:
        car = Car(model = record['model'],
                  price = record['price'],
                  availability = record['availability'],
                  brand = record['brand'])

    # going throught the list of customers
    for record in data['Order']:
        order = Order(dop = record['dop'],
                      cars = record['car'],
                      customer = record['customer'])

if __name__ == "__main__":
    seed_database(config.DB_DUMP_FILE_NAME)

这是json文件内容:

{
"Customer": [{
    "number": "01277000000",
    "name": "John",
    "surname": "Green"
}],
"Brand": [{
    "name": "Ferrari",
    "nationality": "Italian" 
}],
"Car": [{
    "model": "Enzo",
    "price": 123.00,
    "availability": 5,
    "brand": "Ferrari"
}, {
    "model": "458",
    "price": 432.10,
    "availability": 4,
    "brand": "Ferrari"
}],
"Order": [{
    "dop": "01/01/2017",
    "car": ,
    "customer": "01277000000"
}, {
    "dop": "01/02/2017",
    "car": ,
    "customer": "01277000000"
}]
}

config.py 只包含:

# DB_FILE_NAME : path to the SQLite database file.
DB_FILE_NAME = 'db/mydata.sqlite'

# DB_DUMP_FILE_NAME : path to the json file that will be used to seed the database.
DB_DUMP_FILE_NAME = 'data/data.json'

任何建议将不胜感激,在此先感谢。

数据库结构

4

1 回答 1

0

除了一些细节外,您的加载脚本几乎是正确的:

1)您不应该无条件地调用populate_database()in entities.py,因为它会尝试在每次导入时插入相同的数据并由于重复数据而引发错误。用if __name__ == '__main__'.

2)从JSON文件加载初始数据时,需要硬编码加载对象的主键,因此需要id为每个Car描述添加值:

"Car": [{
    "id": 1,
    ...
}, {
    "id": 2,
    ...
}],

3) JSON 文件不是有效的 JSON,因为您没有carOrder. 其实应该是cars,不是car,因为Order实体定义中的cars属性是有Set类型的。在 JSON 文件中,您可以指定汽车 ID 列表:

"Order": [{
    "dop": "01/01/2017",
    "cars": [1],
    "customer": "01277000000"
}, {
    "dop": "01/02/2017",
    "cars": [2],
    "customer": "01277000000"
}]

seed_database函数中,您需要将每个id从数据库转换为相应的汽车:

# going throught the list of customers
for record in data['Order']:
    order = Order(dop = record['dop'],
                  cars = [Car[id] for id in record['cars']],  # <<< see here
                  customer = record['customer'])

之后,您的加载脚本应该按预期工作

于 2017-03-05T15:48:49.843 回答