Files
g11-m3/g11-m3-4/README.md
2026-01-29 17:29:20 +03:00

300 lines
8.8 KiB
Markdown

# 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!)
```bash
# 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
for windows
mkdir -Force flask_app\templates; cd flask_app; ni app.py, database.py, users.py, users.db, requirements.txt; mkdir -Force venv; ni templates\base.html, templates\home.html, templates\login.html, templates\register.html; cd ..; Write-Host "✅ All empty files created in 'flask_app/':" -ForegroundColor Green; Get-ChildItem -Path flask_app -File -Recurse | Sort-Object FullName | Select-Object -ExpandProperty FullName
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