forked from talkpython/100daysofcode-with-python-course
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path6.txt
More file actions
executable file
·166 lines (166 loc) · 7.37 KB
/
6.txt
File metadata and controls
executable file
·166 lines (166 loc) · 7.37 KB
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
00:00 Now SQLAlchemy is powerful because it can connect
00:02 to any type of database that is relational.
00:06 Oracle, SQLServer, SQLite, MySQL,
00:09 you name it.
00:10 But that means we have to tell SQLAlchemy
00:13 where the database is, what is the connection string,
00:16 how do we get to it?
00:18 So we're going to to real quick things to get started here.
00:20 We're going to create a quick directory.
00:24 In here, we're going to do a little trick
00:25 just to find this folder super, super easy.
00:27 Call this db folder.
00:30 We'll define one function, get_db_path.
00:34 And it's going to take a base file name
00:36 and this'll be like rps.bin or something like that.
00:39 And from that, we need the full path.
00:41 So we're going to use a cool little trick here, using os.
00:44 And we'll say base folder is os.path.dirname
00:49 of this particular file.
00:51 So what folder is this file located in?
00:55 It's in here, and we want our database to also be created
00:58 in that same folder.
00:59 So we're just going to say return os.path.join,
01:02 base folder, base file.
01:04 So not a whole lot going on here,
01:06 but this is going to make it nice and easy for us to create,
01:08 we're create just a SQLite file that's going to live here.
01:13 And we'll create a data access bit here.
01:16 And let's add a new part here, say,
01:19 create this to be a session factory.
01:21 These are not the models that we're modeling the data on,
01:24 these are the sort of connection,
01:26 low level infrastructure type things.
01:28 So we're going to create the session factory thing
01:30 and its job is going to be
01:32 to create what's called a unit of work.
01:33 And SQLAlchemy, the way it works,
01:35 is you create this session,
01:36 you do queries, inserts, updates, deletes.
01:39 And you can either commit those changes
01:41 or throw them away.
01:42 So the job of this is to set up the connection
01:45 and create these sessions
01:46 that we can do the rest of our work with.
01:49 So we're going to need a few things here.
01:50 We're going to need the ORM,
01:52 this is the object relational mapper,
01:53 this is really interesting.
01:55 We're going to need the db folder.
01:57 We're going to need our model base,
01:59 we'll work with that.
02:00 Now there's one final thing that's a little bit weird
02:03 but we're going to need it.
02:04 Now at this stage in the program's life cycle,
02:08 it may not have interacted with these files,
02:11 the move, the player and the role.
02:13 For what's about to happen,
02:15 SQLAlchemy has to have seen and loaded into memory
02:19 all of these things.
02:20 And if that hasn't happened yet,
02:22 we're going to miss some things.
02:23 Like maybe one of the tables won't get created
02:25 or something weird like that.
02:26 So we can make sure that this is not a problem here
02:29 by just importing everything we need.
02:32 So move import, move player role.
02:36 Whew, so that's a lot of imports that we're going to need
02:38 but we are all ready.
02:40 Now we're going to create a thing called a factory.
02:43 And it's going to be nothing in the beginning.
02:45 So we need to do is write a function
02:46 that will get called one time and initialize everything.
02:50 So we'll say def.
02:52 It's going to work with this factory
02:53 so we'll say global factory so it can change this
02:56 from outside without,
02:58 and overwrite it with a local variable bit.
03:00 We want to change this, one and only factory,
03:02 there should be one of these in the entire process
03:04 per database, not a bunch.
03:06 So let's use our little db folder thing to get the path,
03:11 and let's call this rock_paper_scissors.bin.
03:15 Extension doesn't matter,
03:16 just something I like to stick with,
03:18 or actually let's change it to sqlite, how's that?
03:21 Even more clear what it's supposed to be.
03:22 And we can create our connections string,
03:24 this you saw already,
03:25 is going to be sqlite:///.
03:29 So this tells SQLAlchemy what kind of database
03:32 it's talking to.
03:33 Is it SQLServer, is it SQLite, is it Oracle?
03:35 And then for SQLite the connection string
03:37 is just the file name.
03:38 So this is nice and straightforward.
03:40 The next thing we're going to do,
03:41 is we need what's called an engine.
03:43 This manages all the connections and the connection pooling
03:45 and stuff like that.
03:46 And just like the factory, there's one of these
03:48 per database connection.
03:52 So we say create_engine,
03:54 and then all we have to do is give it the connection string.
03:57 And you can also, if you wanted to debug this,
03:59 you could say echo equals True.
04:01 I'm going to say false, so we can see what's going on,
04:03 but if you switch this to true,
04:04 you'll see every command issued to the database
04:07 by SQLAlchemy in SQL form.
04:10 So that's really nice.
04:11 Now the next thing we need to do
04:13 is actually create the structure.
04:15 If the database doesn't exist,
04:16 like right now, there's no database file here,
04:18 we would like to have SQLAlchemy get it up and running
04:21 and get everything connected.
04:22 So we can say model_base.metadata.create_all,
04:27 and we'll have to give it the engine.
04:29 So this is going to run
04:30 and actually look at all of these classes up here,
04:32 and it's going to create the related tables
04:35 that we told it about.
04:36 And finally, after all of that,
04:37 we're ready to create our factory.
04:39 So we'll say sqlalchemy.orm.sessionmaker.
04:45 And the session needs to talk to the database.
04:46 So the way that happens is we bind the engine
04:49 to the session factory, therefore all created sessions
04:53 know how to get back to the database.
04:54 Whew, okay, and that is that.
04:57 The other thing we're going to need to do,
04:58 just from making this work a little nicer,
05:01 is we want to be able to safely create these sessions.
05:04 We could directly work with that but it's problematic.
05:07 What if we forget to call this,
05:08 how do we check that, and so on.
05:09 So let's do a little create_session function here.
05:12 Instead of forcing other people to call that
05:15 we can just check, do we need this to be called.
05:17 So we'll say global, we'll say if factory is none,
05:22 like it hasn't been created yet,
05:23 then we'll call global in it.
05:26 Otherwise, this is super easy.
05:27 We'll just say factory, and again, you call it,
05:30 it's a session factory, when you call it,
05:32 it creates a session.
05:34 Okay so, that's all we got to do.
05:35 The last thing I would like to do here
05:37 well, maybe two things.
05:38 One is, PyCharm thinks we're not using these,
05:40 but they're important that they're here,
05:43 so let's go over here and say suppress that.
05:45 That's good.
05:47 Great, okay so no more complaints up there,
05:49 everybody's happy.
05:50 The other thing to do, is when we import the session factory
05:54 and hit dot, we'll see factory, we'll see create_session,
05:57 and global in that, what I'd kind of like to do
05:59 is make this not accessible from the outside
06:02 so we can do that by refactoring it to a double underscore
06:06 and then it'll be hidden by Python from the outside.
06:09 That's kind of a private variable for this module.
06:12 Our database is all configured, our models are built,
06:15 now all we have left to do
06:17 is just use this database access layer
06:19 to actually create some history in our game.