- Learning Flask Framework
- Matt Copperwaite Charles Leifer
- 1655字
- 2021-07-30 10:18:35
Creating the Entry model
A model is the data representation of a table of data that we want to store in the database. These models have attributes called columns that represent the data items in the data. So, if we were creating a Person
model, we might have columns for storing the first and last name, date of birth, home address, hair color, and so on. Since we are interested in creating a model to represent blog entries, we will have columns for things like the title and body content.
Note
Note that we don't say a People
model or Entries
model – models are singular even though they commonly represent many different objects.
With SQLAlchemy, creating a model is as easy as defining a class and specifying a number of attributes assigned to that class. Let's start with a very basic model for our blog entries. Create a new file named models.py
in the blog project's app/
directory and enter the following code:
import datetime, re from app import db def slugify(s): return re.sub('[^\w]+', '-', s).lower() class Entry(db.Model): id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(100)) slug = db.Column(db.String(100), unique=True) body = db.Column(db.Text) created_timestamp = db.Column(db.DateTime, default=datetime.datetime.now) modified_timestamp = db.Column( db.DateTime, default=datetime.datetime.now, onupdate=datetime.datetime.now) def __init__(self, *args, **kwargs): super(Entry, self).__init__(*args, **kwargs) # Call parent constructor. self.generate_slug() def generate_slug(self): self.slug = '' if self.title: self.slug = slugify(self.title) def __repr__(self): return '<Entry: %s>' % self.title
There is a lot going on, so let's start with the imports and work our way down. We begin by importing the standard library datetime
and re
modules. We will be using datetime
to get the current date and time, and re
to do some string manipulation. The next import statement brings in the db
object that we created in app.py
. As you recall, the db
object is an instance of the SQLAlchemy
class, which is a part of the Flask-SQLAlchemy extension. The db
object provides access to the classes that we need to construct our Entry
model, which is just a few lines ahead.
Before the Entry
model, we define a helper function slugify
, which we will use to give our blog entries some nice URLs (used in Chapter 3, Templates and Views). The slugify
function takes a string such as A post about Flask and uses a regular expression to turn a string that is human-readable in to a URL, and so returns a-post-about-flask.
Next is the Entry
model. Our Entry
model is a normal class that extends db.Model
. By extending db.Model
, our Entry
class will inherit a variety of helpers that we'll use to query the database.
The attributes of the Entry
model, are a simple mapping of the names and data that we wish to store in the database and are listed as follows:
id
: This is the primary key for our database table. This value is set for us automatically by the database when we create a new blog entry, usually an auto-incrementing number for each new entry. While we will not explicitly set this value, a primary key comes in handy when you want to refer one model to another, as you'll see later in the chapter.title
: The title for a blog entry, stored as aString
column with a maximum length of 100.slug
: The URL-friendly representation of the title, stored as aString
column with a maximum length of 100. This column also specifiesunique=True
, so that no two entries can share the same slug.body
: The actual content of the post, stored in aText
column. This differs from theString
type of theTitle
andSlug
as you can store as much text as you like in this field.created_timestamp
: The time a blog entry was created, stored in aDateTime
column. We instruct SQLAlchemy to automatically populate this column with the current time by default when an entry is first saved.modified_timestamp
: The time a blog entry was last updated. SQLAlchemy will automatically update this column with the current time whenever we save an entry.
Note
For short strings such as titles or names of things, the String
column is appropriate, but when the text may be especially long it is better to use a Text
column, as we did for the entry body.
We've overridden the constructor for the class (__init__
) so that, when a new model is created, it automatically sets the slug for us based on the title.
The last piece is the __repr__
method that is used to generate a helpful representation of instances of our Entry
class. The specific meaning of __repr__
is not important but allows you to reference the object that the program is working with, when debugging.
A final bit of code needs to be added to main.py, the entry-point to our application, to ensure that the models are imported. Add the highlighted changes to main.py as follows:
from app import app, db import models import views if __name__ == '__main__': app.run()
Creating the Entry table
In order to start working with the Entry
model, we first need to create a table for it in our database. Luckily, Flask-SQLAlchemy comes with a nice helper for doing just this. Create a new sub-folder named scripts
in the blog project's app
directory. Then create a file named create_db.py
:
(blog) $ cd app/ (blog) $ mkdir scripts (blog) $ touch scripts/create_db.py
Add the following code to the create_db.py
module. This function will automatically look at all the code that we have written and create a new table in our database for the Entry
model based on our models:
import os, sys sys.path.append(os.getcwd()) from main import db if __name__ == '__main__': db.create_all()
Execute the script from inside the app/
directory. Make sure the virtualenv is active. If everything goes successfully, you should see no output.
(blog) $ python create_db.py (blog) $
Note
If you encounter errors while creating the database tables, make sure you are in the app directory, with the virtualenv activated, when you run the script. Next, ensure that there are no typos in your SQLALCHEMY_DATABASE_URI
setting.
Working with the Entry model
Let's experiment with our new Entry
model by saving a few blog entries. We will be doing this from the Python interactive shell. At this stage let's install IPython, a sophisticated shell with features such as tab-completion (that the default Python shell lacks).
(blog) $ pip install ipython
Now check whether we are in the app
directory and let's start the shell and create a couple of entries as follows:
(blog) $ ipython In []: from models import * # First things first, import our Entry model and db object. In []: db # What is db? Out[]: <SQLAlchemy engine='sqlite:////home/charles/projects/blog/app/blog.db'>
Note
If you are familiar with the normal Python shell but not IPython, things may look a little different at first. The main thing to be aware of is that In[]
refers to the code you type in, and Out[]
is the output of the commands you put into the shell.
IPython has a neat feature that allows you to print detailed information about an object. This is done by typing in the object's name followed by a question-mark (?). Introspecting the Entry
model provides a bit of information, including the argument signature and the string representing that object (known as the docstring
) of the constructor.
In []: Entry? # What is Entry and how do we create it? Type: _BoundDeclarativeMeta String Form:<class 'models.Entry'> File: /home/charles/projects/blog/app/models.py Docstring: <no docstring> Constructor information: Definition:Entry(self, *args, **kwargs)
We can create Entry
objects by passing column values in as the keyword-arguments. In the preceding example, it uses **kwargs
; this is a shortcut for taking a dict
object and using it as the values for defining the object, as shown next:
In []: first_entry = Entry(title='First entry', body='This is the body of my first entry.')
In order to save our first entry, we will to add it to the database session. The session is simply an object that represents our actions on the database. Even after adding it to the session, it will not be saved to the database yet. In order to save the entry to the database, we need to commit our session:
In []: db.session.add(first_entry) In []: first_entry.id is None # No primary key, the entry has not been saved. Out[]: True In []: db.session.commit() In []: first_entry.id Out[]: 1 In []: first_entry.created_timestamp Out[]: datetime.datetime(2014, 1, 25, 9, 49, 53, 1337)
As you can see from the preceding code examples, once we commit the session, a unique id will be assigned to our first entry and the created_timestamp
will be set to the current time. Congratulations, you've created your first blog entry!
Try adding a few more on your own. You can add multiple entry objects to the same session before committing, so give that a try as well.
Note
At any point while you are experimenting, feel free to delete the blog.db
file and re-run the create_db.py
script to start over with a fresh database.
Making changes to an existing entry
In order to make changes to an existing Entry
, simply make your edits and then commit. Let's retrieve our Entry
using the id that was returned to us earlier, make some changes, and commit it. SQLAlchemy will know that it needs to be updated. Here is how you might make edits to the first entry:
In []: first_entry = Entry.query.get(1) In []: first_entry.body = 'This is the first entry, and I have made some edits.' In []: db.session.commit()
And just like that your changes are saved.
Deleting an entry
Deleting an entry is just as easy as creating one. Instead of calling db.session.add
, we will call db.session.delete
and pass in the Entry
instance that we wish to remove.
In []: bad_entry = Entry(title='bad entry', body='This is a lousy entry.') In []: db.session.add(bad_entry) In []: db.session.commit() # Save the bad entry to the database. In []: db.session.delete(bad_entry) In []: db.session.commit() # The bad entry is now deleted from the database.
- Modular Programming with Python
- ThinkPHP 5實戰
- 軟件界面交互設計基礎
- PHP程序設計(慕課版)
- MATLAB應用與實驗教程
- Learning Neo4j 3.x(Second Edition)
- Drupal 8 Configuration Management
- Drupal 8 Module Development
- Windows內核編程
- Couchbase Essentials
- 單片機原理及應用技術
- SSH框架企業級應用實戰
- Learning C++ by Creating Games with UE4
- 小學生C++趣味編程從入門到精通
- Node.js Web Development