Creating a Simple Pastebin Service in Python and Flask
Tags: python, flask
Published: 2024-07-08 04:40:02

---
title: Creating a Simple Pastebin Service in Python and Flask
published: true
description: Learn how to build a functional pastebin service using Python and Flask. This tutorial covers web development basics, file handling, and syntax highlighting.
tags: python,flask
---

In this blog post, we will be building a simple Pastebin service using Python and Flask. Pastebin is a popular web application used to store plain text or code snippets for a certain period of time. We'll create a basic version that allows users to paste text, select the programming language, and get a URL to share the paste. I have also created a YouTube video about this, which you can view [here](https://youtu.be/s2RQfUxOuco).



## Getting Starting

Before begin creating our application lets setup our environment and in order to setup your environment follow these steps:

1. First, Let's create a virtual environment in the project directory.

```shell
python -m venv venv
```
2. Now, once we have created the virtual environment, let's activate it and install all the required libraries that are going to be used by this project.

```shell
pip install Flask shortuuid pygments
```
We'll also use `shortuuid` for generating unique IDs for each paste and `pygments` for syntax highlighting.

3. Now that we have installed all the required libraries, let's create the necessary files and folders. 

```shell
mkdir -p pastes templates static && touch index.py templates/index.html static/styles.css
```
This is how your folder structure should look:

```shell
pastebin/
│
├── app.py
├── pastes/
├── templates/
│   └── index.html
└── static/
    └── styles.css

```
The `pastes` directory will store the text files for each paste. The templates directory contains our HTML templates, and the static directory contains CSS for styling.

Now that we have set up the environment, it's time to code.

## Writing Code

Let's dive into the code. Create a file named `index.py` and add the following code:

```python
from flask import Flask, request, render_template, abort
import shortuuid
import os
from pygments import highlight
from pygments.lexers import get_lexer_by_name, get_all_lexers
from pygments.formatters import HtmlFormatter

app = Flask(__name__)

# Directory to store paste files
PASTE_DIR = 'pastes'
if not os.path.exists(PASTE_DIR):
    os.makedirs(PASTE_DIR)

# Function to get available programming languages for syntax highlighting
def get_language_options():
    return sorted([(lexer[1][0], lexer[0]) for lexer in get_all_lexers() if lexer[1]])

# Route for the main page
@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        # Get content and language from the form
        content = request.form['content']
        language = request.form['language']
        # Generate a unique ID for the paste
        paste_id = shortuuid.uuid()
        # Create the file path for the paste
        file_path = os.path.join(PASTE_DIR, paste_id)

        # Save the paste content to a file
        with open(file_path, 'w') as f:
            f.write(f"{language}\n{content}")

        # Generate the URL for the new paste
        paste_url = request.url_root + paste_id
        return render_template('index.html', paste_url=paste_url, languages=get_language_options())

    # Render the form with available languages
    return render_template('index.html', languages=get_language_options())

# Route to view a specific paste by its ID
@app.route('/<paste_id>')
def view_paste(paste_id):
    # Create the file path for the paste
    file_path = os.path.join(PASTE_DIR, paste_id)
    if not os.path.exists(file_path):
        abort(404)  # Return a 404 error if the paste does not exist

    # Read the paste file
    with open(file_path, 'r') as f:
        language = f.readline().strip()  # First line is the language
        content = f.read()  # Remaining content is the paste

    # Get the appropriate lexer for syntax highlighting
    lexer = get_lexer_by_name(language, stripall=True)
    # Create a formatter for HTML output
    formatter = HtmlFormatter(linenos=True, cssclass="source")
    # Highlight the content
    highlighted_content = highlight(content, lexer, formatter)
    # Get the CSS for the highlighted content
    highlight_css = formatter.get_style_defs('.source')

    # Render the paste with syntax highlighting
    return render_template('index.html', paste_content=highlighted_content, highlight_css=highlight_css)

if __name__ == '__main__':
    app.run(debug=True)
```

Once you have created the flask now let's create html template in `templates/index.html` and `style.css` in `static/style.css`

- `templates/index.html`

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Pastebin Service</title>
    <link rel="stylesheet" href="{{ url_for(\'static\', filename=\'styles.css\') }}">
    {% if highlight_css %}
    <style>
        {{ highlight_css|safe }}
    </style>
    {% endif %}
</head>
<body>
    <h1>Pastebin Service</h1>
    {% if paste_url %}
        <p>Your paste URL: <a href="{{ paste_url }}">{{ paste_url }}</a></p>
    {% endif %}
    {% if paste_content %}
        <div class="highlight">
            {{ paste_content|safe }}
        </div>
    {% endif %}
    <form method="post">
        <textarea name="content" rows="10" cols="50" placeholder="Paste your text here..."></textarea><br>
        <select name="language">
            {% for code, name in languages %}
                <option value="{{ code }}">{{ name }}</option>
            {% endfor %}
        </select><br>
        <button type="submit">Submit</button>
    </form>
</body>
</html>
```

- `static/style.css`

```css
body {
    font-family: Arial, sans-serif;
    margin: 20px;
}
 
h1 {
    color: #333;
}
 
textarea {
    width: 100%;
    margin-top: 10px;
}
 
select, button {
    margin-top: 10px;
}
 
.highlight {
    background-color: #f5f5f5;
    padding: 10px;
    border: 1px solid #ccc;
    margin-top: 20px;
}
```

Now that we have created our application, before we run it, let's try to understand how it works by breaking down the code.

### Code Breakdown

1. First, we import the necessary libraries and modules. `Flask` is our web framework, `shortuuid` is used for generating unique IDs, and `Pygments` is for syntax highlighting. We also set up a directory to store our `pastes/`.

```python
from flask import Flask, request, render_template, abort
import shortuuid
import os
from pygments import highlight
from pygments.lexers import get_lexer_by_name, get_all_lexers
from pygments.formatters import HtmlFormatter

app = Flask(__name__)

PASTE_DIR = 'pastes'
if not os.path.exists(PASTE_DIR):
    os.makedirs(PASTE_DIR)
```

2. Then we write a function that retrieves all available programming languages supported by Pygments for syntax highlighting and returns them as a sorted list of tuples.

```python
def get_language_options():
    return sorted([(lexer[1][0], lexer[0]) for lexer in get_all_lexers() if lexer[1]])
```

3. Then we write the main route for our application. If the request method is POST (i.e., when the user submits a form), it saves the content and language to a new file with a unique ID. The URL for the new paste is generated and displayed to the user. If the request method is GET, it simply renders the form.

```python
@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        content = request.form['content']
        language = request.form['language']
        paste_id = shortuuid.uuid()
        file_path = os.path.join(PASTE_DIR, paste_id)

        with open(file_path, 'w') as f:
            f.write(f"{language}\n{content}")

        paste_url = request.url_root + paste_id
        return render_template('index.html', paste_url=paste_url, languages=get_language_options())

    return render_template('index.html', languages=get_language_options())

```

This route handles viewing a specific paste. It reads the paste file, applies syntax highlighting using pygments, and renders the highlighted content.

```python
@app.route('/<paste_id>')
def view_paste(paste_id):
    file_path = os.path.join(PASTE_DIR, paste_id)
    if not os.path.exists(file_path):
        abort(404)

    with open(file_path, 'r') as f:
        language = f.readline().strip()
        content = f.read()

    lexer = get_lexer_by_name(language, stripall=True)
    formatter = HtmlFormatter(linenos=True, cssclass="source")
    highlighted_content = highlight(content, lexer, formatter)
    highlight_css = formatter.get_style_defs('.source')

    return render_template('index.html', paste_content=highlighted_content, highlight_css=highlight_css)

```


Now once we understand how everything works, now you can simply run the application using this command
`python index.py`

## Conclusion

You've built a simple Pastebin service using Python and Flask! This service allows users to paste text, select a programming language, and share the paste via a unique URL. You can expand this project by adding features like expiration times for pastes, user authentication, or even a database to store pastes more efficiently.

If you have any feedback, please feel free to leave a comment below. If you prefer not to comment publicly, you can always send me an [email](mailto:muhammadraza0047@gmail.com).


**ORIGINALLY POSTED [HERE](https://muhammadraza.me/2024/Simple-Pastebin-In-Python/)**