InterSystems IRIS Flask Blog application
Tags: python, programming, sql, flask
Published: 2023-10-22 17:52:00

![main](https://github.com/mwaseem75/IRIS-FlaskBlog/assets/18219467/9cd462a5-920f-4d0d-9c8f-604468ca8244)  
 

 

Hi Community  
  
In this article, I will introduce my application <a href="https://openexchange.intersystems.com/package/IRIS-FlaskBlog" rel="nofollow"><strong>IRIS-FlaskBlog</strong></a>.  
  
IRIS-FlaskBlog Application is a real-world application that leverages the functionality of Flask web framework, SQLALchemy ORM, and InterSystems IRIS. The application contains user registration and authentication with the help of Flask-Login python library, a responsive user interface to create and edit posts.  
 

## Application Features

  * User registration and authentication
  * Creation of a data structure with SQLALcemy model classes
  * Responsive user interface to create, edit, and delete posts
  * Like and add comments to the post
  * Search based on the user and based on the tags

##  
Used Technologies

  * **Flask**: A micro web framework for Python that allows you to build web applications quickly and efficiently.Conduit
  * **SQLAlchemy**: An Object-Relational Mapping (ORM) library that provides a high-level, Pythonic interface for interacting with databases.
  * **InterSystems IRIS**: A high-performance, data platform that combines a powerful database with integration, analytics, and AI capabilities.

##  
Installation

  1. Clone/git pull the repo into any local directory

<pre class="codeblock-container" idlang="12" lang="Shell Session" tabsize="4"><code class="language-shell hljs">git clone https://github.com/mwaseem75/IRIS-FlaskBlog.git</code></pre>

  1. Open a Docker terminal in this directory and run:

<pre class="codeblock-container" idlang="12" lang="Shell Session" tabsize="4"><code class="language-shell hljs">docker-compose build</code></pre>

  1. Run the IRIS container:

<pre class="codeblock-container" idlang="0" lang="ObjectScript" tabsize="4"><code class="language-cls hljs cos">docker-compose up -<span class="hljs-keyword">d</span></code></pre>

##  
Application Flow

In the docker, ENTRYPOINT [ "python", "app.py" ] is defined which will initiate the application  (The ENTRYPOINT instruction is used to configure the executables that will always run after the container is initiated)

<pre class="codeblock-container" idlang="2" lang="Python" tabsize="4"><code class="language-python hljs"><span class="hljs-comment"># app.py</span>
<span class="hljs-comment"># import create_app from website package</span>
<span class="hljs-keyword">from</span> website <span class="hljs-keyword">import</span> create_app
<span class="hljs-comment"># import configuration parameters</span>
<span class="hljs-keyword">from</span> website.myconfig <span class="hljs-keyword">import</span> *

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    <span class="hljs-comment"># Get db parameters and creating to create_app in order to create DB</span>
    database_uri = <span class="hljs-string">f'iris://<span class="hljs-subst">{DB_USER}</span>:<span class="hljs-subst">{DB_PASS}</span>@<span class="hljs-subst">{DB_URL}</span>:<span class="hljs-subst">{DB_PORT}</span>/<span class="hljs-subst">{DB_NAMESPACE}</span>'</span>
    app = create_app(database_uri)
    app.run(<span class="hljs-string">'0.0.0.0'</span>, port=<span class="hljs-string">"4040"</span>, debug=<span class="hljs-keyword">False</span>)</code></pre>

The above code invokes create_app() function and then runs the application on port 4040  
  
create\_app() function is defined in \\_\_init\_\_.py file

<pre class="codeblock-container" idlang="2" lang="Python" tabsize="4"><code class="language-python hljs"><span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Flask
<span class="hljs-keyword">from</span> flask_sqlalchemy <span class="hljs-keyword">import</span> SQLAlchemy
<span class="hljs-keyword">from</span> flask_login <span class="hljs-keyword">import</span> LoginManager
<span class="hljs-keyword">from</span> .myconfig <span class="hljs-keyword">import</span> *

db = SQLAlchemy()

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">create_app</span><span class="hljs-params">(database_uri)</span>:</span>
    <span class="hljs-comment">#Import flask application</span>
    app = Flask(__name__)
    app.config[<span class="hljs-string">'SECRET_KEY'</span>] = <span class="hljs-string">"iris-FlaskBlogKey"</span>
    <span class="hljs-comment"># assigning db parameters</span>
    app.config[<span class="hljs-string">'SQLALCHEMY_DATABASE_URI'</span>] = database_uri
    <span class="hljs-comment">#create and push an application context onto the application context stack</span>
    app.app_context().push()

    <span class="hljs-keyword">from</span> .views <span class="hljs-keyword">import</span> views
    <span class="hljs-keyword">from</span> .auth <span class="hljs-keyword">import</span> auth
    <span class="hljs-keyword">from</span> .models <span class="hljs-keyword">import</span> User
    app.register_blueprint(views, url_prefix=<span class="hljs-string">"/"</span>)
    app.register_blueprint(auth, url_prefix=<span class="hljs-string">"/"</span>)

    db.init_app(app)

    <span class="hljs-keyword">with</span> app.app_context():
        <span class="hljs-comment">#Create database</span>
        db.create_all()

    <span class="hljs-comment"># Assign Login View</span>
    login_manager = LoginManager()
    login_manager.login_view = <span class="hljs-string">"auth.login"</span>
    login_manager.init_app(app)
    
<span class="hljs-meta">    @login_manager.user_loader</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">load_user</span><span class="hljs-params">(id)</span>:</span>
        <span class="hljs-keyword">return</span> User.query.get(int(id))

    <span class="hljs-keyword">return</span> app</code></pre>

The above code creates the database by invoking SQLAlchemy create_all() function which will create the database structure defined in the models.py file

<pre class="codeblock-container" idlang="2" lang="Python" tabsize="4"><code class="language-python hljs"><span class="hljs-keyword">from</span> . <span class="hljs-keyword">import</span> db
<span class="hljs-keyword">from</span> flask_login <span class="hljs-keyword">import</span> UserMixin
<span class="hljs-keyword">from</span> sqlalchemy.sql <span class="hljs-keyword">import</span> func

<span class="hljs-comment">#creates tags_accosication table</span>
tags_table = db.Table(
    <span class="hljs-string">'tags_association'</span>,
    db.Column(<span class="hljs-string">'post_id'</span>, db.ForeignKey(<span class="hljs-string">'post.id'</span>), primary_key=<span class="hljs-keyword">True</span>),
    db.Column(<span class="hljs-string">'tag_id'</span>, db.ForeignKey(<span class="hljs-string">'tag.id'</span>), primary_key=<span class="hljs-keyword">True</span>),
)

<span class="hljs-comment">#Users table</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span><span class="hljs-params">(db.Model, UserMixin)</span>:</span>
    id = db.Column(db.Integer, primary_key=<span class="hljs-keyword">True</span>)
    email = db.Column(db.String(<span class="hljs-number">150</span>), unique=<span class="hljs-keyword">True</span>)
    username = db.Column(db.String(<span class="hljs-number">150</span>), unique=<span class="hljs-keyword">True</span>)
    password = db.Column(db.String(<span class="hljs-number">150</span>))
    date_created = db.Column(db.DateTime(timezone=<span class="hljs-keyword">True</span>), default=func.now())
    posts = db.relationship(<span class="hljs-string">'Post'</span>, backref=<span class="hljs-string">'user'</span>, passive_deletes=<span class="hljs-keyword">True</span>)
    comments = db.relationship(<span class="hljs-string">'Comment'</span>, backref=<span class="hljs-string">'user'</span>, passive_deletes=<span class="hljs-keyword">True</span>)
    likes = db.relationship(<span class="hljs-string">'Like'</span>, backref=<span class="hljs-string">'user'</span>, passive_deletes=<span class="hljs-keyword">True</span>)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__repr__</span><span class="hljs-params">(self)</span>:</span>
        <span class="hljs-keyword">return</span> <span class="hljs-string">f'<span class="hljs-subst">{self.username}</span>'</span>
<span class="hljs-comment">#Posts Table</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Post</span><span class="hljs-params">(db.Model)</span>:</span>
    id = db.Column(db.Integer, primary_key=<span class="hljs-keyword">True</span>)
    title = db.Column(db.String(<span class="hljs-number">250</span>))
    content = db.Column(db.Text)
    date_created = db.Column(db.DateTime(timezone=<span class="hljs-keyword">True</span>), default=func.now())
    author = db.Column(db.Integer, db.ForeignKey(
        <span class="hljs-string">'user.id'</span>, ondelete=<span class="hljs-string">"CASCADE"</span>), nullable=<span class="hljs-keyword">False</span>)
    comments = db.relationship(<span class="hljs-string">'Comment'</span>, backref=<span class="hljs-string">'post'</span>, passive_deletes=<span class="hljs-keyword">True</span>)
    likes = db.relationship(<span class="hljs-string">'Like'</span>, backref=<span class="hljs-string">'post'</span>, passive_deletes=<span class="hljs-keyword">True</span>)
    tags = db.relationship(<span class="hljs-string">'Tag'</span>, secondary=tags_table,
                           backref=db.backref(<span class="hljs-string">'posts'</span>, lazy=<span class="hljs-string">'dynamic'</span>))


    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__repr__</span><span class="hljs-params">(self)</span>:</span>
        user = User.query.filter_by(id=self.author).first()
        <span class="hljs-keyword">return</span> <span class="hljs-string">f'<span class="hljs-subst">{user.username}</span>'</span>
<span class="hljs-comment">#Tags table</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Tag</span><span class="hljs-params">(db.Model)</span>:</span>
    id = db.Column(db.Integer, primary_key=<span class="hljs-keyword">True</span>)
    name = db.Column(db.String(<span class="hljs-number">150</span>))

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__repr__</span><span class="hljs-params">(self)</span>:</span>
        <span class="hljs-keyword">return</span> <span class="hljs-string">f'<span class="hljs-subst">{self.name}</span>'</span>
<span class="hljs-comment">#Comments table</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Comment</span><span class="hljs-params">(db.Model)&</span>:</span>
    id = db.Column(db.Integer, primary_key=<span class="hljs-keyword">True</span>)
    text = db.Column(db.String(<span class="hljs-number">500</span>), nullable=<span class="hljs-keyword">False</span>)
    date_created = db.Column(db.DateTime(timezone=<span class="hljs-keyword">True</span>), default=func.now())
    author = db.Column(db.Integer, db.ForeignKey(
        <span class="hljs-string">'user.id'&</span>, ondelete=&<span class="hljs-string">"CASCADE"</span>), nullable=<span class="hljs-keyword">False</span>)
    post_id = db.Column(db.Integer, db.ForeignKey(
        <span class="hljs-string">'post.id'</span>, ondelete=<span class="hljs-string">"CASCADE"</span>), nullable=<span class="hljs-keyword">False</span>)

<span class="hljs-comment">#Like table</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Like</span><span class="hljs-params">(db.Model)</span>:</span>
    id = db.Column(db.Integer, primary_key=<span class="hljs-keyword">True&</span>)
    date_created = db.Column(db.DateTime(timezone=<span class="hljs-keyword">True</span>), default=func.now())
    author = db.Column(db.Integer, db.ForeignKey(
        <span class="hljs-string">'user.id'</span>, ondelete=<span class="hljs-string">"CASCADE"</span>), nullable=<span class="hljs-keyword">False&</span>)
    post_id = db.Column(db.Integer, db.ForeignKey(
        <span class="hljs-string">'post.id'</span>, ondelete=<span class="hljs-string">"CASCADE"</span>), nullable=<span class="hljs-keyword">False</span>)
</code></pre>

## Application Database

SQLALchemy will create below tables:

  * **user**: To store User information
  * **post**: To store Posts related data
  * **tags**: To store Tags against the post
  * **tags_association**: To store links between Posts and Tags
  * **comments**: To save post comments by users
  * **like**: To store likes details by users

To view table details, navigate to [**http://localhost:52775/csp/sys/exp/%25CSP.UI.Portal.SQL.Home.zen?$NAMESPACE=USER#**](http://localhost:52775/csp/sys/exp/%25CSP.UI.Portal.SQL.Home.zen?%24NAMESPACE=USER#)  
![image](https://github.com/mwaseem75/IRIS-FlaskBlog/assets/18219467/de303374-af23-40cc-874b-cad560ca1a87) 

For more details please visit <a href="https://openexchange.intersystems.com/package/IRIS-FlaskBlog" rel="nofollow"><strong>IRIS-FlaskBlog</strong></a> application page  
{% embed https://www.youtube.com/watch?v=AjK5Bv1zq-Q&t=4s %}
Thanks