Using MongoDB with Python

This page of the Bookshelf app tutorial shows how the sample app stores its persistent data, metadata for books,computer in a MongoDB database.

This page is part of a multipage tutorial. To start from the beginning and read the setup instructions, go to Python Bookshelf app.

Running MongoDB on Compute Engine

If you haven't set up a MongoDB instance, you can create a managed instance running on Google Cloud Platform (GCP) by using Atlas on GCP or mLab. If you'd rather use an unmanaged MongoDB instance running on Compute Engine, check out Bitnami's preconfigured click-to-deploy solution.

For best performance, make sure your MongoDB instance is hosted on GCP and located in the same region as your app.

By default, MongoDB uses port 27017 for communication. After setting up your MongoDB instance, you might need to configure the firewall rules to allow traffic to and from this port. For instances running on GCP, see Using firewall rules for instructions.

Configuring settings

This section uses code in the 2-structured-data directory. Edit the files and run commands in this directory.

  1. Open the config.py file for editing and replace the following values:
    • Set the value of [PROJECT_ID] to your project ID, which is visible in the GCP Console.
    • Set the value of [DATA_BACKEND] to mongodb.
    • Set the value of [MONGO_URI]. If you're using mLab, the URI is available from the control panel. If you deployed your own MongoDB cluster as described previously, set the URI to the external IP noted in that section. You can also find the external IP address by running gcloud compute instances list.
  2. Save and close the config.py file.

Installing dependencies

To create a virtual environment and install dependencies, use the following commands:

Linux/macOS

virtualenv -p python3 env
source env/bin/activate
pip install -r requirements.txt

Windows

virtualenv -p python3 env
env\scripts\activate
pip install -r requirements.txt

Running the app on your local machine

  1. Start a local web server:

    python main.py
    
  2. In your browser, enter the following address:

    http://localhost:8080
    
Now you can browse the app's web pages to add, edit, and delete books.

Press Control+C to exit the worker and then the local web server.

Deploying the app to the App Engine flexible environment

  1. Deploy the sample app:

    gcloud app deploy
    
  2. In your browser, enter the following address. Replace [YOUR_PROJECT_ID] with your GCP project ID:

    https://[YOUR_PROJECT_ID].appspot.com
    

If you update your app, you deploy the updated version by entering the same command that you used to deploy the app. The deployment creates a new version of your app and promotes it to the default version. The earlier versions of your app remain, as do their associated virtual machine (VM) instances. All of these app versions and VM instances are billable resources. To reduce costs, delete the non-default versions of your app.

To delete an app version:

  1. In the GCP Console, go to the Versions page for App Engine.

    Go to the Versions page

  2. Select the checkbox for the non-default app version you want to delete.
  3. Click Delete to delete the app version.

For more information about cleaning up billable resources, see the Cleaning up section in the final step of this tutorial.

App structure

Bookshelf app deployment process and structure

The app stores all persistent data in MongoDB.

Understanding the code

This section walks you through the app's code and explains how it works.

Handling user submissions with forms

The add/edit HTML form lets users add and edit book submissions in the app.

Image of add/edit Form

The HTML form is created using Flask's default template engine, Jinja2, which is a Python template engine. The following Jinja2 template specifies that the form include text input fields for Title, Author, Date Published, and Description:

{% extends "base.html" %}

{% block content %}
<h3>{{action}} book</h3>

<form method="POST" enctype="multipart/form-data">

  <div class="form-group">
    <label for="title">Title</label>
    <input type="text" name="title" id="title" value="{{book.title}}" class="form-control"/>
  </div>

  <div class="form-group">
    <label for="author">Author</label>
    <input type="text" name="author" id="author" value="{{book.author}}" class="form-control"/>
  </div>

  <div class="form-group">
    <label for="publishedDate">Date Published</label>
    <input type="text" name="publishedDate" id="publishedDate" value="{{book.publishedDate}}" class="form-control"/>
  </div>

  <div class="form-group">
    <label for="description">Description</label>
    <textarea name="description" id="description" class="form-control">{{book.description}}</textarea>
  </div>

  <button type="submit" class="btn btn-success">Save</button>
</form>

{% endblock %}

Handling form submissions

When a user clicks Add Book, the crud.add view displays the form. When the user fills out the Add book form and then clicks Save, the same view handles the form's HTTP POST action. This action initiates the process of sending the submitted data to MongoDB by passing the data to the get_model().create function.

@crud.route('/add', methods=['GET', 'POST'])
def add():
    if request.method == 'POST':
        data = request.form.to_dict(flat=True)

        book = get_model().create(data)

        return redirect(url_for('.view', id=book['id']))

    return render_template("form.html", action="Add", book={})

The bookshelf/model_mongodb.py file contains the code that performs CRUD functions for data stored in MongoDB. For example, the get_model().create statement calls the create function in bookshelf/model_mongodb.py, which sends the user's submitted data to the create function. Here is the create function that saves the user's submitted data to MongoDB.

def create(data):
    result = mongo.db.books.insert_one(data)
    return read(result.inserted_id)

When the user edits a book, the update function is used instead.

def update(data, id):
    mongo.db.books.replace_one({'_id': _id(id)}, data)
    return read(id)

The create and update functions both use read, which is also used when the user views a single book.

def read(id):
    result = mongo.db.books.find_one({'_id': _id(id)})
    return from_mongo(result)

The from_mongo helper function translates a MongoDB document's _id to an ID that can be used by the app.

def from_mongo(data):
    """
    Translates the MongoDB dictionary format into the format that's expected
    by the application.
    """
    if not data:
        return None

    data['id'] = str(data['_id'])
    return data

After users have added books, clicking the Books link navigates to the /books page, which lists all of the books currently stored in MongoDB. The model_mongodb.list function lists all of the books using data retrieved from MongoDB.

def list(limit=10, cursor=None):
    cursor = int(cursor) if cursor else 0

    results = mongo.db.books.find(skip=cursor, limit=10).sort('title')
    books = builtin_list(map(from_mongo, results))

    next_page = cursor + limit if len(books) == limit else None
    return (books, next_page)

This code queries MongoDB using mongo.db.books.find, gets all of the documents in the book collection, and then returns them, ordered by title. The code gets results one page at a time and returns a cursor to let the user load the next page of results.

Trang này có hữu ích không? Hãy cho chúng tôi biết đánh giá của bạn:

Gửi phản hồi về...