Files
g11-m3/g11-m3-4/README.md
2026-01-27 15:15:54 +03:00

8.3 KiB

Flask Authentication Application

A complete full-stack web application with user authentication built with Flask and SQLite.

📁 Project Structure

flask_app/ ├── app.py ├── database.py ├── users.py ├── users.db ├── requirements.txt ├── venv/ └── templates/ ├── base.html ├── home.html ├── login.html └── register.html

text

🚀 Quick Start

1. Create Project Scaffold (One Command!)

# Create all empty files and folders with one command:
mkdir -p flask_app/templates && cd flask_app && touch app.py database.py users.py users.db requirements.txt && mkdir -p venv && touch templates/base.html templates/home.html templates/login.html templates/register.html && cd .. && echo "✅ All empty files created in 'flask_app/':" && find flask_app/ -type f | sort
2. Setup Virtual Environment
bash
cd flask_app

# Create virtual environment
python -m venv venv

# Activate virtual environment (Windows PowerShell)
venv\Scripts\Activate.ps1

# If you get an error:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
venv\Scripts\Activate.ps1

# Activate virtual environment (Mac/Linux)
# source venv/bin/activate
3. Install Dependencies
bash
pip install flask werkzeug flask-wtf
pip freeze > requirements.txt
4. Fill Files with Code
Now fill the empty files with the code below:

app.py - Main Flask application:

python
from flask import Flask, render_template, request, redirect, url_for, session, flash
import database
import users

app = Flask(__name__)
app.secret_key = 'your-secret-key-change-this-in-production'

database.init_db()

@app.route('/')
def home():
    return render_template('home.html')

@app.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        username = request.form['username']
        email = request.form['email']
        password = request.form['password']
        
        success, message = users.register_user(username, email, password)
        
        if success:
            flash('Registration successful! Please login.', 'success')
            return redirect(url_for('login'))
        else:
            flash(message, 'error')
    
    return render_template('register.html')

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        
        success, result = users.login_user(username, password)
        
        if success:
            session['user_id'] = result['id']
            session['username'] = result['username']
            flash('Login successful!', 'success')
            return redirect(url_for('home'))
        else:
            flash(result, 'error')
    
    return render_template('login.html')

@app.route('/logout')
def logout():
    session.clear()
    flash('You have been logged out.', 'success')
    return redirect(url_for('home'))

if __name__ == '__main__':
    app.run(debug=True)
database.py - Database operations:

python
import sqlite3

def init_db():
    conn = sqlite3.connect('users.db')
    cursor = conn.cursor()
    
    cursor.execute('''
        CREATE TABLE IF NOT EXISTS users (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            username TEXT UNIQUE NOT NULL,
            email TEXT UNIQUE NOT NULL,
            password TEXT NOT NULL,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        )
    ''')
    
    conn.commit()
    conn.close()

def get_db_connection():
    conn = sqlite3.connect('users.db')
    conn.row_factory = sqlite3.Row
    return conn
users.py - User authentication:

python
from werkzeug.security import generate_password_hash, check_password_hash
import database

def register_user(username, email, password):
    hashed_password = generate_password_hash(password, method='sha256')
    
    try:
        conn = database.get_db_connection()
        conn.execute('INSERT INTO users (username, email, password) VALUES (?, ?, ?)',
                    (username, email, hashed_password))
        conn.commit()
        conn.close()
        return True, None
    except sqlite3.IntegrityError as e:
        return False, 'Username or email already exists!'

def login_user(username, password):
    conn = database.get_db_connection()
    user = conn.execute('SELECT * FROM users WHERE username = ?', (username,)).fetchone()
    conn.close()
    
    if user and check_password_hash(user['password'], password):
        return True, user
    else:
        return False, 'Invalid username or password!'
5. Fill HTML Templates
templates/base.html:

html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{% block title %}Flask Auth App{% endblock %}</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 500px; margin: 50px auto; padding: 20px; }
        .alert { padding: 10px; margin: 10px 0; border-radius: 5px; }
        .success { background: #d4edda; color: #155724; }
        .error { background: #f8d7da; color: #721c24; }
        form { display: flex; flex-direction: column; gap: 10px; }
        input, button { padding: 10px; margin: 5px 0; }
        .nav { margin-bottom: 20px; }
        .nav a { margin-right: 15px; text-decoration: none; color: #007bff; }
    </style>
</head>
<body>
    <div class="nav">
        <a href="{{ url_for('home') }}">Home</a>
        {% if session.get('user_id') %}
            <a href="{{ url_for('logout') }}">Logout</a>
        {% else %}
            <a href="{{ url_for('login') }}">Login</a>
            <a href="{{ url_for('register') }}">Register</a>
        {% endif %}
    </div>
    
    {% with messages = get_flashed_messages(with_categories=true) %}
        {% if messages %}
            {% for category, message in messages %}
                <div class="alert {{ category }}">{{ message }}</div>
            {% endfor %}
        {% endif %}
    {% endwith %}
    
    {% block content %}{% endblock %}
</body>
</html>
templates/home.html:

html
{% extends "base.html" %}

{% block title %}Home{% endblock %}

{% block content %}
<h1>Welcome to Flask Auth App</h1>
{% if session.get('user_id') %}
    <h2>Hello, {{ session.get('username') }}!</h2>
    <p>You are logged in.</p>
    <p>This is your dashboard.</p>
{% else %}
    <p>Please <a href="{{ url_for('login') }}">login</a> or <a href="{{ url_for('register') }}">register</a>.</p>
{% endif %}
{% endblock %}
templates/register.html:

html
{% extends "base.html" %}

{% block title %}Register{% endblock %}

{% block content %}
<h2>Register</h2>
<form method="POST" action="{{ url_for('register') }}">
    <input type="text" name="username" placeholder="Username" required>
    <input type="email" name="email" placeholder="Email" required>
    <input type="password" name="password" placeholder="Password" required>
    <button type="submit">Register</button>
</form>
<p>Already have an account? <a href="{{ url_for('login') }}">Login here</a></p>
{% endblock %}
templates/login.html:

html
{% extends "base.html" %}

{% block title %}Login{% endblock %}

{% block content %}
<h2>Login</h2>
<form method="POST" action="{{ url_for('login') }}">
    <input type="text" name="username" placeholder="Username" required>
    <input type="password" name="password" placeholder="Password" required>
    <button type="submit">Login</button>
</form>
<p>Don't have an account? <a href="{{ url_for('register') }}">Register here</a></p>
{% endblock %}
6. Run the Application
bash
python app.py
Visit: http://127.0.0.1:5000

📋 File Purpose
File	Purpose	Contains
app.py	Main Flask application	Routes, request handling, session management
database.py	Database operations	Connection functions, table creation, SQL queries
users.py	User authentication	Register, login, password hashing functions
templates/	HTML templates	Base template and page-specific templates
requirements.txt	Dependencies	List of Python packages needed
users.db	Database file	SQLite database with user data
🔒 Security Notes
This is a learning example, not production-ready

Passwords are hashed using Werkzeug

Never store plain text passwords

Use stronger secret keys in production

🚀 Next Steps
Add password reset functionality

Implement email verification

Add user profile pages

Create a simple blog system

Deploy to Heroku or Render

📚 Resources
Flask Documentation

SQLite Documentation

Jinja2 Template Documentation