python: SQLAlchemy (ORM) Simple example using mysql in Ubuntu 24.04

mysql sql script:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
create table School  表
(
  `SchoolId` char(5) NOT NULL comment'主鍵primary key,學校編號',
    `SchoolName` nvarchar(500) NOT NULL DEFAULT '' comment' 學校名稱',
    `SchoolTelNo`  varchar(8)  NULL DEFAULT '' comment'電話號碼',
  PRIMARY KEY (SchoolId)   #主鍵
)COMMENT='學校表 School Table' DEFAULT CHARSET=utf8;
  
create table Teacher
(
    `TeacherId` char(5) NOT NULL comment'主鍵primary key,老师編號',
    `TeacherFirstName` nvarchar(100) NOT NULL DEFAULT '' comment' 名',
    `TeacherLastName` nvarchar(20) NOT NULL DEFAULT '' comment' 姓',
    `TeacherGender` char(2) NOT NULL DEFAULT '' comment'性別',
    `TeacherTelNo`  varchar(8)  NULL DEFAULT '' comment'電話號碼',
     `TeacherSchoolId`  char(5) NOT NULL DEFAULT '' comment'外鍵 foreign key 學校ID',
     PRIMARY KEY (TeacherId),   #主鍵
     FOREIGN KEY(TeacherSchoolId) REFERENCES School(SchoolId)  #外鍵
)COMMENT='老師表Teacher Table' DEFAULT CHARSET=utf8;

  

 项目结构

 

领域层(Domain Layer)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# encoding: utf-8
# 版权所有 2025 ©涂聚文有限公司 ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2023.1 python 3.11
# OS        : Ubuntu 24.0
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  oracle 21c Neo4j
# Datetime  : 2025/2/20 20:23
# User      : geovindu
# Product   : PyCharm
# Project   : pyMySqlDDDOrmDemo
# File      : domain/entities/school.py
# explain   : 学习
'''
create table School  表
(
  `SchoolId` char(5) NOT NULL comment'主鍵primary key,學校編號',
    `SchoolName` nvarchar(500) NOT NULL DEFAULT '' comment' 學校名稱',
    `SchoolTelNo`  varchar(8)  NULL DEFAULT '' comment'電話號碼',
  PRIMARY KEY (SchoolId)   #主鍵
)COMMENT='學校表 School Table' DEFAULT CHARSET=utf8;
'''
  
  
  
class School:
    """
    领域层(Domain Layer)
    定义业务实体
    """
    def __init__(self, school_id, school_name, school_tel_no):
        """
        :param school_id: 學校編號
        :param school_name: 學校名稱
        :param school_tel_no:電話號碼
        """
        self.school_id = school_id
        self.school_name = school_name
        self.school_tel_no = school_tel_no
  
  
# encoding: utf-8
# 版权所有 2025 ©涂聚文有限公司 ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2023.1 python 3.11
# OS        : Ubuntu 24.0
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  oracle 21c Neo4j
# Datetime  : 2025/2/20 20:27
# User      : geovindu
# Product   : PyCharm
# Project   : pyMySqlDDDOrmDemo
# File      : domain/repositories/school.py
# explain   : 学习
from abc import ABC, abstractmethod
from typing import List
from ..entities.school import School
  
  
class SchoolRepository(ABC):
    """
    领域层(Domain Layer)
    存储库接口
    """
    @abstractmethod
    def add(self, school: School):
        pass
  
    @abstractmethod
    def update(self, school: School):
        pass
  
    @abstractmethod
    def delete(self, school_id: str):
        """
        删除
        :param school_id:
        :return:
        """
        pass
  
    def get_schoolall(self) -> List[School]:
        """
        所有
        :return:
        """
        pass
  
    @abstractmethod
    def get_all(self, page: int, page_size: int, search_query: str = "") -> List[School]:
        """
        分页
        :param page:
        :param page_size:
        :param search_query:
        :return:
        """
  
        pass
  
    @abstractmethod
    def get_total_count(self, search_query: str = "") -> int:
        pass

  

基础设施层(Infrastructure Layer)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# encoding: utf-8
# 版权所有 2025 ©涂聚文有限公司 ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2023.1 python 3.11
# OS        : Ubuntu 24.0
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  oracle 21c Neo4j
# Datetime  : 2025/2/20 20:46
# User      : geovindu
# Product   : PyCharm
# Project   : pyMySqlDDDOrmDemo
# File      : infrastructure/model/school.py
# explain   : 学习
  
from sqlalchemy import create_engine, Column, String, ForeignKey
from sqlalchemy.orm import sessionmaker, declarative_base, relationship
  
  
  
Base = declarative_base()
  
  
class SchoolModel(Base):
    """
    基础设施层(Infrastructure Layer)
    数据库交互
    分开会报错
    """
    __tablename__ = 'School'
    SchoolId = Column(String(5), primary_key=True)
    SchoolName = Column(String(500), nullable=False, default='')
    SchoolTelNo = Column(String(8), nullable=True, default='')
    teachers = relationship("TeacherModel", back_populates="school")
  
class TeacherModel(Base):
    """
    基础设施层(Infrastructure)
    数据库交互
    """
    __tablename__ = 'Teacher'
    TeacherId = Column(String(5), primary_key=True)
    TeacherFirstName = Column(String(100), nullable=False, default='')
    TeacherLastName = Column(String(20), nullable=False, default='')
    TeacherGender = Column(String(2), nullable=False, default='')
    TeacherTelNo = Column(String(8), nullable=True, default='')
    TeacherSchoolId = Column(String(5), ForeignKey('School.SchoolId'), nullable=False, default='')
    school = relationship("SchoolModel", back_populates="teachers")
  
  
# encoding: utf-8
# 版权所有 2025 ©涂聚文有限公司 ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2023.1 python 3.11
# OS        : Ubuntu 24.0
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  oracle 21c Neo4j
# Datetime  : 2025/2/20 20:46
# User      : geovindu
# Product   : PyCharm
# Project   : pyMySqlDDDOrmDemo
# File      : infrastructure/repositories/school.py
# explain   : 学习
from sqlalchemy import create_engine, Column, String, ForeignKey
from sqlalchemy.orm import sessionmaker, declarative_base, relationship
from domain.entities.school import School
from ..model.school import SchoolModel
from ..database.mysqlHelper import MysqlHeler
from typing import List
class SchoolRepository:
    """
    基础设施层(Infrastructure Layer)
    实现存储库接口
    """
    def __init__(self):
        """
        """
        self._Session = MysqlHeler()
  
  
  
    def add(self, school: School):
        """
        :param school:
        :return:
        """
        session = self._Session.getSession()
        school_model = SchoolModel(SchoolId=school.school_id, SchoolName=school.school_name,
                                   SchoolTelNo=school.school_tel_no)
        session.add(school_model)
        session.commit()
        session.close()
  
    def update(self, school: School):
        """
        :param school:
        :return:
        """
        session = self._Session.getSession()
        school_model = session.query(SchoolModel).filter_by(SchoolId=school.school_id).first()
        if school_model:
            school_model.SchoolName = school.school_name
            school_model.SchoolTelNo = school.school_tel_no
            session.commit()
        session.close()
  
    def delete(self, school_id: str):
        """
        :param school_id:
        :return:
        """
        session = self._Session.getSession()
        school_model = session.query(SchoolModel).filter_by(SchoolId=school_id).first()
        if school_model:
            session.delete(school_model)
            session.commit()
        session.close()
  
    def get_schoolall(self) -> List[School]:
        """
        查询所有所学校
        :return:
        """
        session = self._Session.getSession()
        query = session.query(SchoolModel).all()
        '''
        li=[School(school.SchoolId, school.SchoolName, school.SchoolTelNo) for school in query]
        for i in li:
            print(i.school_id,i.school_name,i.school_tel_no)
        print("query", [School(school.SchoolId, school.SchoolName, school.SchoolTelNo) for school in query])
        '''
        session.close()
        return [School(school.SchoolId, school.SchoolName, school.SchoolTelNo) for school in query]
  
    def get_all(self, page: int, page_size: int, search_query: str = "") -> List[School]:
        """
        :param page:
        :param page_size:
        :param search_query:
        :return:
        """
        session = self._Session.getSession()
        query = session.query(SchoolModel)
        if search_query:
            query = query.filter(
                (SchoolModel.SchoolId.contains(search_query)) |
                (SchoolModel.SchoolName.contains(search_query)) |
                (SchoolModel.SchoolTelNo.contains(search_query))
            )
        offset = (page - 1) * page_size
        school_models = query.offset(offset).limit(page_size).all()
        session.close()
        return [School(school.SchoolId, school.SchoolName, school.SchoolTelNo) for school in school_models]
  
    def get_total_count(self, search_query: str = ""):
        """
        :param search_query:
        :return:
        """
        session = self._Session.getSession()
        query = session.query(SchoolModel)
        if search_query:
            query = query.filter(
                (SchoolModel.SchoolId.contains(search_query)) |
                (SchoolModel.SchoolName.contains(search_query)) |
                (SchoolModel.SchoolTelNo.contains(search_query))
            )
        count = query.count()
        session.close()
        return count

  

应用层(Application Layer)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# encoding: utf-8
# 版权所有 2025 ©涂聚文有限公司 ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2023.1 python 3.11
# OS        : Ubuntu 24.0
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  oracle 21c Neo4j
# Datetime  : 2025/2/20 20:04
# User      : geovindu
# Product   : PyCharm
# Project   : pyMySqlDDDOrmDemo
# File      : application/services/school.py
# explain   : 学习
  
from typing import List
from domain.entities.school import School
from domain.repositories.school import SchoolRepository
  
  
class SchoolService:
    """
    应用层(Application Layer)
    封装业务逻辑。
    """
    def __init__(self, repository: SchoolRepository):
        """
        :param repository:
        """
        self.repository = repository
  
    def add_school(self, school: School):
        """
        :param school:
        :return:
        """
        self.repository.add(school)
  
    def update_school(self, school: School):
        """
        :param school:
        :return:
        """
        self.repository.update(school)
  
    def delete_school(self, school_id: str):
        """
        :param school_id:
        :return:
        """
        self.repository.delete(school_id)
  
    def get_schoolall(self) -> List[School]:
        """
        所有
        :return:
        """
        return self.repository.get_schoolall()
  
  
    def get_schools(self, page: int, page_size: int, search_query: str = "") -> List[School]:
        """
        :param page:
        :param page_size:
        :param search_query:
        :return:
        """
        return self.repository.get_all(page, page_size, search_query)
  
    def get_total_school_count(self, search_query: str = "") -> int:
        """
        :param search_query:
        :return:
        """
        return self.repository.get_total_count(search_query)

  

表现层(Presentation Layer)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
# encoding: utf-8
# 版权所有 2025 ©涂聚文有限公司 ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2023.1 python 3.11
# OS        : Ubuntu 24.0
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  oracle 21c Neo4j
# Datetime  : 2025/2/20 20:47
# User      : geovindu
# Product   : PyCharm
# Project   : pyMySqlDDDOrmDemo
# File      : presentation/views/school.py
# explain   : 学习
  
  
import tkinter as tk
from tkinter import ttk
  
  
class SchoolView(object):
    """
    表现层(Presentation Layer)
    包含视图和控制器,处理用户界面和操作。
    """
  
    def __init__(self, parent):
        """
        :param parent:
        """
        self.frame = tk.Frame(parent)
  
        # 搜索框
        self.search_frame = ttk.Frame(self.frame)
        self.search_frame.pack(pady=10)
        self.search_entry = ttk.Entry(self.search_frame)
        self.search_entry.pack(side=tk.LEFT, padx=5)
        self.search_button = ttk.Button(self.search_frame, text="Search")
        self.search_button.pack(side=tk.LEFT)
  
        # Treeview
        self.tree = ttk.Treeview(self.frame, columns=('SchoolId', 'SchoolName', 'SchoolTelNo'), show='headings')
        self.tree.heading('SchoolId', text='School ID')
        self.tree.heading('SchoolName', text='School Name')
        self.tree.heading('SchoolTelNo', text='School Tel No')
        self.tree.pack(pady=10)
  
        # 操作按钮
        self.button_frame = ttk.Frame(self.frame)
        self.button_frame.pack(pady=10)
        self.add_button = ttk.Button(self.button_frame, text="Add")
        self.add_button.pack(side=tk.LEFT, padx=5)
        self.edit_button = ttk.Button(self.button_frame, text="Edit")
        self.edit_button.pack(side=tk.LEFT, padx=5)
        self.delete_button = ttk.Button(self.button_frame, text="Delete")
        self.delete_button.pack(side=tk.LEFT, padx=5)
  
        # 分页按钮
        self.pagination_frame = ttk.Frame(self.frame)
        self.pagination_frame.pack(pady=10)
        self.prev_button = ttk.Button(self.pagination_frame, text="Previous")
        self.prev_button.pack(side=tk.LEFT, padx=5)
        self.page_label = ttk.Label(self.pagination_frame, text="Page 1 of 1")
        self.page_label.pack(side=tk.LEFT, padx=5)
        self.next_button = ttk.Button(self.pagination_frame, text="Next")
        self.next_button.pack(side=tk.LEFT, padx=5)
  
    def clear_tree(self):
        """
        :return:
        """
        for item in self.tree.get_children():
            self.tree.delete(item)
  
    def populate_tree(self, schools):
        """
        :param schools:
        :return:
        """
        for school in schools:
            self.tree.insert('', 'end', values=(school.school_id, school.school_name, school.school_tel_no))
  
    def update_page_label(self, current_page, total_pages, tatol,pagesize):
        """
        :param current_page:
        :param total_pages:
        :param tatol
        :param pagesize
        :return:
        """
        self.page_label.config(text=f"Page {current_page} of {total_pages}  {pagesize}/total:{tatol}")
  
    def open_add_window(self, save_callback):
        """
        :param save_callback:
        :return:
        """
        top = tk.Toplevel(self.frame)
        top.title("Add School")
        top.iconbitmap("favicon.ico")
        ttk.Label(top, text="School ID:").grid(row=0, column=0, padx=5, pady=5)
        id_entry = ttk.Entry(top)
        id_entry.grid(row=0, column=1, padx=5, pady=5)
  
        ttk.Label(top, text="School Name:").grid(row=1, column=0, padx=5, pady=5)
        name_entry = ttk.Entry(top)
        name_entry.grid(row=1, column=1, padx=5, pady=5)
  
        ttk.Label(top, text="School Tel No:").grid(row=2, column=0, padx=5, pady=5)
        tel_entry = ttk.Entry(top)
        tel_entry.grid(row=2, column=1, padx=5, pady=5)
  
        def save_school():
            """
            :return:
            """
            school_id = id_entry.get()
            school_name = name_entry.get()
            school_tel_no = tel_entry.get()
            if school_id and school_name and school_tel_no:
                save_callback(school_id, school_name, school_tel_no)
                top.destroy()
  
        ttk.Button(top, text="Save", command=save_school).grid(row=3, column=0, columnspan=2, pady=10)
  
    def open_edit_window(self, school_id, school_name, school_tel_no, update_callback):
        """
        :param school_id:
        :param school_name:
        :param school_tel_no:
        :param update_callback:
        :return:
        """
        top = tk.Toplevel(self.frame)
        top.title("Edit School")
        #top.iconbitmap("favicon.ico")
        ttk.Label(top, text="School ID:").grid(row=0, column=0, padx=5, pady=5)
        id_entry = ttk.Entry(top)
        id_entry.insert(0, school_id)
        id_entry.config(state='readonly')
        id_entry.grid(row=0, column=1, padx=5, pady=5)
  
        ttk.Label(top, text="School Name:").grid(row=1, column=0, padx=5, pady=5)
        name_entry = ttk.Entry(top)
        name_entry.insert(0, school_name)
        name_entry.grid(row=1, column=1, padx=5, pady=5)
  
        ttk.Label(top, text="School Tel No:").grid(row=2, column=0, padx=5, pady=5)
        tel_entry = ttk.Entry(top)
        tel_entry.insert(0, school_tel_no)
        tel_entry.grid(row=2, column=1, padx=5, pady=5)
  
        def update_school():
            """
            :return:
            """
            new_school_name = name_entry.get()
            new_school_tel_no = tel_entry.get()
            if new_school_name and new_school_tel_no:
                update_callback(school_id, new_school_name, new_school_tel_no)
                top.destroy()
  
        ttk.Button(top, text="Update", command=update_school).grid(row=3, column=0, columnspan=2, pady=10)
  
  
# encoding: utf-8
# 版权所有 2025 ©涂聚文有限公司 ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2023.1 python 3.11
# OS        : Ubuntu 24.0
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  oracle 21c Neo4j
# Datetime  : 2025/2/20 20:47
# User      : geovindu
# Product   : PyCharm
# Project   : pyMySqlDDDOrmDemo
# File      : presentation/controllers/school.py
# explain   : 学习
  
import tkinter as tk
from application.services.school import SchoolService
from domain.entities.school import School
  
  
class SchoolController(object):
    """
    表现层(Presentation Layer)
    包含视图和控制器,处理用户界面和操作。
    """
    def __init__(self, service: SchoolService, view):
        """
        :param service:
        :param view:
        """
        self.service = service
        self.view = view
        self.current_page = 1
        self.page_size = 10
        self.search_query = ""
        self.total_pages = 1
  
        self.view.search_button.config(command=self.search)
        self.view.add_button.config(command=self.add)
        self.view.edit_button.config(command=self.edit)
        self.view.delete_button.config(command=self.delete)
        self.view.prev_button.config(command=self.prev_page)
        self.view.next_button.config(command=self.next_page)
  
        self.load_data()
  
    def load_data(self):
        """
        :return:
        """
        schools = self.service.get_schools(self.current_page, self.page_size, self.search_query)
        total_count = self.service.get_total_school_count(self.search_query)
        self.total_pages = (total_count + self.page_size - 1) // self.page_size
  
        self.view.clear_tree()
        self.view.populate_tree(schools)
        self.view.update_page_label(self.current_page, self.total_pages,total_count,self.page_size)
  
        self.view.prev_button.config(state=tk.NORMAL if self.current_page > 1 else tk.DISABLED)
        self.view.next_button.config(state=tk.NORMAL if self.current_page < self.total_pages else tk.DISABLED)
  
    def search(self):
        """
        :return:
        """
        self.search_query = self.view.search_entry.get()
        self.current_page = 1
        self.load_data()
  
    def add(self):
        """
        :return:
        """
  
        def save_callback(school_id, school_name, school_tel_no):
            new_school = School(school_id, school_name, school_tel_no)
            self.service.add_school(new_school)
            self.load_data()
  
        self.view.open_add_window(save_callback)
  
    def edit(self):
        """
        :return:
        """
  
        selected_item = self.view.tree.selection()
        if selected_item:
            values = self.view.tree.item(selected_item, 'values')
            school_id, school_name, school_tel_no = values
  
            def update_callback(school_id, new_school_name, new_school_tel_no):
                updated_school = School(school_id, new_school_name, new_school_tel_no)
                self.service.update_school(updated_school)
                self.load_data()
  
            self.view.open_edit_window(school_id, school_name, school_tel_no, update_callback)
  
    def delete(self):
        """
        :return:
        """
        selected_item = self.view.tree.selection()
        if selected_item:
            school_id = self.view.tree.item(selected_item, 'values')[0]
            self.service.delete_school(school_id)
            self.load_data()
  
    def prev_page(self):
        """
        :return:
        """
        if self.current_page > 1:
            self.current_page -= 1
            self.load_data()
  
    def next_page(self):
        """
        :return:
        """
        if self.current_page < self.total_pages:
            self.current_page += 1
            self.load_data()

 调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# encoding: utf-8
# 版权所有 2025 ©涂聚文有限公司 ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:先安装: python.exe -m pip install --upgrade pip
#  pip install pymysql
#  pip install sqlalchemy
#  sudo apt install python3-tk
#  pip install pillow
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : PyCharm 2023.1 python 3.11
# OS        : Ubuntu 24.0
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  oracle 21c Neo4j
# Datetime  : 2025/2/20 20:21
# User      : geovindu
# Product   : PyCharm
# Project   : pyMySqlDDDOrmDemo
# File      : main.py
# explain   : 学习
'''
DDD
定义业务实体和存储库接口
domain
    --entities
    --repositories
基础设施层(Infrastructure)
实现存储库接口,与数据库交互。
infrastructure
    --database
    --model
    --repositories
应用层(Application)
封装业务逻辑。
application
    --services
表现层(Presentation)
包含视图和控制器,处理用户界面和操作。
presentation
    --views
    --controllers
'''
  
  
import tkinter as tk
from infrastructure.repositories import SchoolRepository,TeacherRepository    # init 必须配置,才可以这样引用
from application.services import SchoolService, TeacherService
from presentation.views import SchoolView, TeacherView
from presentation.controllers import SchoolController, TeacherController
  
  
if __name__ == '__main__':
    """   
    主程序输出
    """
    root = tk.Tk()
    root.title("学校老师管理系统")
  
    # 创建数据库存储库实例
    school_repository = SchoolRepository()
    teacher_repository = TeacherRepository()
  
    # 创建服务实例
    school_service = SchoolService(school_repository)
    teacher_service = TeacherService(teacher_repository)
  
    # 创建视图实例
    school_view = SchoolView(root)
    teacher_view = TeacherView(root)
    school_view.frame.pack_forget()
    teacher_view.frame.pack_forget()
  
    # 创建控制器实例
    school_controller = SchoolController(school_service, school_view)
    # 需要加上学校的务服实例。便于选择学校
    teacher_controller = TeacherController(teacher_service, school_service, teacher_view)
  
  
  
    # 创建主菜单
    menubar = tk.Menu(root)
    root.config(menu=menubar)
  
    # 创建主菜单下的子菜单
    main_menu = tk.Menu(menubar, tearoff=0)
    menubar.add_cascade(label="管理菜单", menu=main_menu)
  
    # 学校管理子菜单
    school_menu = tk.Menu(main_menu, tearoff=0)
    main_menu.add_cascade(label="学校管理", menu=school_menu)
    school_menu.add_command(label="查看学校信息", command=lambda: (
        school_view.frame.pack(),
        teacher_view.frame.pack_forget()  # 隐藏
    ))
  
    # 老师管理子菜单
    teacher_menu = tk.Menu(main_menu, tearoff=0)
    main_menu.add_cascade(label="老师管理", menu=teacher_menu)
    teacher_menu.add_command(label="查看老师信息", command=lambda: (
        teacher_view.frame.pack(),
        school_view.frame.pack_forget()   # 隐藏
    ))
    #root.iconbitmap(delattr="favicon.ico")
    #root.tk.call('wm', 'iconphoto', root._w, tk.PhotoImage(file='favicon.ico'))
    root.mainloop()
    print('PyCharm,geovindu,Geovin Du,涂聚文!')

  

输出:

 

 

 

posted @   ®Geovin Du Dream Park™  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
历史上的今天:
2023-02-21 CSharp: Select.Pdf Free Html To Pdf Converter for .NET
2014-02-21 sql and csharp: Split Function
2014-02-21 Colorbox - a jQuery lightbox
2012-02-21 csharp 在万年历中计算显示农历日子出错
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示