Django - 创建一个保存聚合外键值的模型

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

我有一个 Django

Model
定义为
ServiceEvent
,另一个定义为
Part

class ServiceEvent(Model):
    date = DateTimeField(null=False, blank=False, db_column='date', 
                         default=datetime.now())
    vehicle = ForeignKey(Vehicle, on_delete=models.CASCADE)
    description = TextField(null=True, blank=False, db_column='description')
    
    # The contents of the notifications to create for this event.
    notification_contents = TextField(null=True, blank=False, 
                                      db_column='notification_contents')
    
    # The mileage the event should occur.
    target_mileage = DecimalField(max_digits=10, decimal_places=2, 
                                  null=True, blank=False, 
                                  db_column='target_mileage')
    
    # The mileage at the time of the event.
    event_mileage = DecimalField(max_digits=10, decimal_places=2, 
                                 null=True, blank=False, 
                                 db_column='event_mileage')

class Part(Model):
    part_number = CharField(max_length=100, null=False, blank=False, 
                            db_column='part_number')
    description = CharField(max_length=100, null=False, blank=False, 
                            db_column='description')
    price = DecimalField(max_digits=10, decimal_places=2, null=False, 
                         db_column='price')
    service_event = ForeignKey(ServiceEvent, on_delete=models.CASCADE)

每个

Parts
可以有多个
ServiceEvent

ServiceEvent
表中存储包含属于给定事件的所有零件加起来的价格的列的方法是什么?

我想这样做是为了提高效率。

我希望能够做一些事情:

price = service_event_obj.total_price

我正在使用 SQLite。

django database sqlite relational-database
1个回答
0
投票

在 ServiceEvent 表中存储包含属于给定事件的所有零件的价格的列的方法是什么?

您可以使用

TRIGGER
BUT 来完成此操作,因为在提取数据时,可以从现有数据生成/计算/导出价格的
sum

示范

这是根据您的代码松散地基于架构的演示:-

/* Cleanup test environment (just in case)*/
DROP TABLE IF EXISTS part;
DROP TABLE IF EXISTS serviceevent;
DROP TABLE IF EXISTS vehicle;
CREATE TABLE IF NOT EXISTS vehicle (
    description TEXT PRIMARY KEY, 
    otherData TEXT DEFAULT 'blah'
);
CREATE TABLE IF NOT EXISTS serviceevent (
    date TEXT PRIMARY KEY DEFAULT CURRENT_TIMESTAMP,
    description TEXT REFERENCES vehicle(description) ON DELETE CASCADE ON UPDATE CASCADE,
    notification_contents TEXT,
    target_mileage REAL,
    event_mileage REAL

);
CREATE TABLE IF NOT EXISTS part (
    part_number TEXT PRIMARY KEY,
    description TEXT,
    price REAL,
    service_event TEXT REFERENCES serviceevent ON DELETE CASCADE ON  UPDATE CASCADE
);
/* Add some vehicles */
INSERT INTO vehicle (description) VALUES ('CAR001'),('CAR002'),('CAR003');
/* Add some serviceevents for the vehicles */
INSERT INTO serviceevent VALUES
    ('2023-03-14 10:20:00','CAR001','10k Service',10000.00,9100.01),
    ('2024-03-13 11:00:00','CAR001','20k Service',20000.00,19100.01),
    ('2023-03-15 14:20:00','CAR002','10k Service',10000.00,9100.02),
    ('2024-03-16 15:00:00','CAR002','20k Service',20000.00,19100.02),
    ('2023-03-17 18:20:00','CAR003','10k Service',10000.00,9100.01),
    ('2024-03-18 19:00:00','CAR003','20k Service',20000.00,19100.01)
;
/* add some parts to service events (not all for brevity)*/
INSERT INTO part VALUES
    /* 10k service for Car001 (i.e. serviceevent '2023-03-14 10:20:00')*/
    ('p001','Air Filter',25.68,'2023-03-14 10:20:00'),
    ('p002','Spark Plug Set',15.20,'2023-03-14 10:20:00'),
    ('p003','OIL (5L)',32.32,'2023-03-14 10:20:00'),
    /* 10k service for Car002 (i.e. serviceevent '2023-03-15 14:20:00)*/
    /* Note just the 2 parts */
    ('p004','Air Filter',25.68,'2023-03-15 14:20:00'),
    ('p005','Spark Plug Set',15.20,'2023-03-15 14:20:00')
;
SELECT 
    vehicle.*, /* include ALL of the vehicle columns in the output */
    serviceevent.*, /* include ALL of the serviceevent columns in the output */
    
    /* Use Aggregate functions to show all the parts and the sum of the prices */
    group_concat(part.description),sum(part.price) AS total_parts_price
FROM vehicle 
    JOIN serviceevent ON vehicle.description = serviceevent.description
    JOIN part ON part.service_event = serviceevent.date
GROUP BY service_event /* group the output insto sets per service event (to which the aggregate functions apply) */
;
/* Cleanup test environment (After run)*/
DROP TABLE IF EXISTS part;
DROP TABLE IF EXISTS serviceevent;
DROP TABLE IF EXISTS vehicle;

这会导致:-

  • CAR001 的 10k 服务于 2023 年 3 月 14 日 10:20 完成,拥有/使用过的零件(空气滤清器、机油滤清器和机油)总计 73.20 美元
  • Car002 的 10k 服务于 2023 年 3 月 15 日 14:20 完成,拥有/使用过的零件(空气过滤器和机油过滤器)总计 40.88 美元
  • 即无需额外列即可获得预期结果
© www.soinside.com 2019 - 2024. All rights reserved.