我应该如何使用 .json 文件为这个 PonyORM - SQLite 数据库播种?

How should I seed this PonyORM - SQLite database using a .json file?

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

我已经尝试解决这个问题超过 6 个小时了。我查看了 PonyORM 文档和 JSON 文档。我找不到足够的信息来解决这个问题。

entities.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'

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

Database Structure

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

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

包裹起来

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

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

3) JSON 文件不是有效的 JSON,因为您没有为 Order 指定 car 属性值。实际上,它应该是 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'])

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