Category: Uncategorized

  • Python Django Custom User Model Guide

    Building a robust authentication system is one of the first challenges you’ll face when developing a Django application. While Django’s default User model works for many simple projects, real‑world apps often require extra fields, alternative login mechanisms, or custom validation rules. That’s where a custom user model shines. In this comprehensive guide we’ll walk you through every step of creating, configuring, and maintaining a custom user model in Python Django, ensuring your project stays scalable, secure, and SEO‑friendly.

    Why Use a Custom User Model?

    Before diving into the code, it’s worth understanding the benefits that a custom user model brings to a Django project:

    • Flexibility: Add fields such as phone_number, profile_picture, or date_of_birth without resorting to messy one‑to‑one extensions.
    • Future‑proofing: Changing the user model after the first migration is extremely difficult. Starting with a custom model from day one prevents painful refactors later.
    • Alternative authentication: Use email, phone number, or a third‑party identifier as the primary login credential.
    • Better integration: Align the user schema with your business logic, analytics, and GDPR compliance requirements.

    Step‑by‑Step Guide to Creating a Custom User Model

    1. Plan Your Model Structure

    Identify the data you need for each user. Common additions include:

    email (as username)
    first_name, last_name
    is_active, is_staff, is_superuser
    date_joined
    profile_picture
    phone_number
    

    Make a quick sketch or a table to avoid missing fields later.

    2. Set Up a New Django Project (If Needed)

    If you’re starting fresh, run the following commands:

    django-admin startproject myproject
    cd myproject
    python -m venv venv
    source venv/bin/activate
    pip install django
    django-admin startapp accounts
    

    We’ll keep the custom user model inside the accounts app.

    3. Define the Custom User Model

    Create accounts/models.py and subclass AbstractBaseUser together with PermissionsMixin. This gives you full control over authentication while still supporting Django’s permission framework.

    from django.contrib.auth.base_user import AbstractBaseUser
    from django.contrib.auth.models import PermissionsMixin, BaseUserManager
    from django.db import models
    from django.utils import timezone
    
    class CustomUserManager(BaseUserManager):
        def create_user(self, email, password=None, **extra_fields):
            if not email:
                raise ValueError('The Email field must be set')
            email = self.normalize_email(email)
            user = self.model(email=email, **extra_fields)
            user.set_password(password)
            user.save(using=self._db)
            return user
    
        def create_superuser(self, email, password, **extra_fields):
            extra_fields.setdefault('is_staff', True)
            extra_fields.setdefault('is_superuser', True)
            extra_fields.setdefault('is_active', True)
    
            if extra_fields.get('is_staff') is not True:
                raise ValueError('Superuser must have is_staff=True.')
            if extra_fields.get('is_superuser') is not True:
                raise ValueError('Superuser must have is_superuser=True.')
    
            return self.create_user(email, password, **extra_fields)
    
    class CustomUser(AbstractBaseUser, PermissionsMixin):
        email = models.EmailField('email address', unique=True)
        first_name = models.CharField(max_length=30, blank=True)
        last_name = models.CharField(max_length=30, blank=True)
        phone_number = models.CharField(max_length=20, blank=True)
        profile_picture = models.ImageField(upload_to='profiles/', blank=True, null=True)
        is_staff = models.BooleanField(default=False)
        is_active = models.BooleanField(default=True)
        date_joined = models.DateTimeField(default=timezone.now)
    
        objects = CustomUserManager()
    
        USERNAME_FIELD = 'email'
        REQUIRED_FIELDS = []  # Email & password are required by default
    
        class Meta:
            verbose_name = 'user'
            verbose_name_plural = 'users'
    
        def __str__(self):
            return self.email
    

    4. Register the Model in settings.py

    Tell Django to use your new model for authentication:

    # myproject/settings.py
    INSTALLED_APPS = [
        # …
        'accounts',
        # …
    ]
    
    AUTH_USER_MODEL = 'accounts.CustomUser'
    

    5. Create and Apply Migrations

    Run the migration commands. Because the custom model replaces the built‑in User, you must do this before creating any other apps that reference the default model.

    python manage.py makemigrations accounts
    python manage.py migrate
    

    6. Update Admin Interface

    Without admin registration, you won’t be able to manage users from the Django admin. Add a custom UserAdmin class to handle the new fields.

    # accounts/admin.py
    from django.contrib import admin
    from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
    from .models import CustomUser
    
    class CustomUserAdmin(BaseUserAdmin):
        list_display = ('email', 'first_name', 'last_name', 'is_staff')
        list_filter = ('is_staff', 'is_active', 'is_superuser')
        fieldsets = (
            (None, {'fields': ('email', 'password')}),
            ('Personal info', {'fields': ('first_name', 'last_name', 'phone_number', 'profile_picture')}),
            ('Permissions', {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')}),
            ('Important dates', {'fields': ('last_login', 'date_joined')}),
        )
        add_fieldsets = (
            (None, {
                'classes': ('wide',),
                'fields': ('email', 'password1', 'password2', 'is_staff', 'is_active')}
            ),
        )
        search_fields = ('email', 'first_name', 'last_name')
        ordering = ('email',)
    
    admin.site.register(CustomUser, CustomUserAdmin)
    

    7. Adjust Forms and Authentication Views

    If you rely on Django’s built‑in auth views (e.g., PasswordResetView), they already work with AUTH_USER_MODEL. However, custom registration forms need to reference the new model:

    # accounts/forms.py
    from django import forms
    from django.contrib.auth.forms import UserCreationForm, UserChangeForm
    from .models import CustomUser
    
    class CustomUserCreationForm(UserCreationForm):
        class Meta(UserCreationForm.Meta):
            model = CustomUser
            fields = ('email', 'first_name', 'last_name', 'phone_number')
    
    class CustomUserChangeForm(UserChangeForm):
        class Meta:
            model = CustomUser
            fields = ('email', 'first_name', 'last_name', 'phone_number', 'profile_picture')
    

    8. Wire Up URLs and Views

    Below is a minimal example using Django’s generic class‑based views for registration and profile editing.

    # accounts/views.py
    from django.urls import reverse_lazy
    from django.views import generic
    from .forms import CustomUserCreationForm, CustomUserChangeForm
    
    class SignUpView(generic.CreateView):
        form_class = CustomUserCreationForm
        success_url = reverse_lazy('login')
        template_name = 'registration/signup.html'
    
    class ProfileUpdateView(generic.UpdateView):
        form_class = CustomUserChangeForm
        success_url = reverse_lazy('profile')
        template_name = 'registration/profile.html'
    
        def get_object(self):
            return self.request.user
    

    Then add the routes:

    # accounts/urls.py
    from django.urls import path
    from . import views
    
    urlpatterns = [
        path('signup/', views.SignUpView.as_view(), name='signup'),
        path('profile/', views.ProfileUpdateView.as_view(), name='profile'),
    ]
    

    Best Practices for Maintaining a Custom User Model

    Never Change AUTH_USER_MODEL After Migration

    Switching the user model after you have data is a massive undertaking. If you anticipate a future change, consider using a proxy model or adding a OneToOneField profile instead of replacing the core model.

    Keep Business Logic Out of the Model

    Models should store data and provide simple helpers. Complex validation, email sending, or third‑party API calls belong in services, signals, or form clean methods. This keeps migrations fast and the codebase maintainable.

    Use Signals Sparingly

    While Django signals (e.g., post_save) can automate profile creation, they add hidden coupling. If you need a guaranteed side effect, prefer overriding save() or using explicit service calls.

    Write Unit Tests Early

    Testing authentication flows prevents regressions. A minimal test suite might look like:

    # accounts/tests.py
    from django.test import TestCase
    from django.urls import reverse
    from .models import CustomUser
    
    class UserModelTests(TestCase):
        def test_create_user(self):
            user = CustomUser.objects.create_user(email='test@example.com', password='pass123')
            self.assertEqual(user.email, 'test@example.com')
            self.assertTrue(user.check_password('pass123'))
    
        def test_login_with_email(self):
            CustomUser.objects.create_user(email='login@example.com', password='secret')
            response = self.client.post(reverse('login'), {
                'username': 'login@example.com',
                'password': 'secret'
            })
            self.assertRedirects(response, '/')
    

    Leverage Django’s Built‑In Password Validators

    In settings.py enable validators to enforce strong passwords:

    AUTH_PASSWORD_VALIDATORS = [
    {'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator'},
    {'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', '

  • Python Django Rest Framework Drf Tutorial

    Looking to turn your Django web app into a powerful, scalable API? The Django REST Framework (DRF) makes it effortless to build RESTful services with Python, offering a clean, modular approach that blends perfectly with Django’s “batteries‑included” philosophy. In this comprehensive tutorial we’ll walk through everything you need to know— from setting up the environment to deploying a production‑ready API—so you can start delivering data to web, mobile, and IoT clients in no time.

    What Is Django REST Framework?

    Django REST Framework (often abbreviated as DRF) is an open‑source library that extends Django’s core capabilities to create web APIs. It provides:

    • Powerful Serializer classes for converting complex data types (models, querysets) to JSON, XML, or other formats.
    • Flexible ViewSet and Router abstractions that reduce boilerplate code.
    • Built‑in support for authentication (Token, JWT, OAuth), permissions, throttling, and pagination.
    • Browsable API documentation that helps developers test endpoints directly from the browser.

    Because DRF is built on top of Django, you can reuse your existing models, middleware, and settings while gaining a full‑featured API layer.

    Setting Up the Development Environment

    Before diving into code, make sure your workstation is ready. Follow these steps:

    1. Install Python 3.11+ – most modern Django projects require a recent Python version.
    2. Create a virtual environment to isolate dependencies:
      python -m venv venv
      source venv/bin/activate   # Linux/macOS
      venv\Scripts\activate      # Windows
    3. Upgrade pip and install Django and DRF:
      pip install --upgrade pip
      pip install django djangorestframework
    4. Optional but recommended: install django-filter for advanced query filtering and drf-yasg for Swagger/OpenAPI docs.
      pip install django-filter drf-yasg

    Creating a New Django Project

    With the environment ready, start a fresh Django project:

    django-admin startproject myapi
    cd myapi

    Then create a reusable app where the API lives:

    python manage.py startapp books

    Don’t forget to add the new app and DRF to INSTALLED_APPS in myapi/settings.py:

    INSTALLED_APPS = [
        # default Django apps...
        'rest_framework',
        'books',
    ]

    Building Your First API with DRF

    We’ll build a simple “Bookstore” API that lets clients list, create, retrieve, update, and delete books. First, define a model in books/models.py:

    from django.db import models
    
    class Book(models.Model):
        title = models.CharField(max_length=200)
        author = models.CharField(max_length=100)
        published_date = models.DateField()
        isbn = models.CharField(max_length=13, unique=True)
    
        def __str__(self):
            return f"{self.title} by {self.author}"

    Run migrations:

    python manage.py makemigrations
    python manage.py migrate

    Serializers Explained

    Serializers translate model instances into JSON and validate incoming data. Create books/serializers.py:

    from rest_framework import serializers
    from .models import Book
    
    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model = Book
            fields = ['id', 'title', 'author', 'published_date', 'isbn']

    The ModelSerializer automatically generates fields based on the model, saving you time.

    ViewSets and Routers

    Instead of writing separate view functions for each CRUD operation, DRF’s ViewSet bundles them together. Add books/views.py:

    from rest_framework import viewsets
    from .models import Book
    from .serializers import BookSerializer
    
    class BookViewSet(viewsets.ModelViewSet):
        queryset = Book.objects.all()
        serializer_class = BookSerializer

    Now wire the viewset to URLs using a router. In books/urls.py:

    from django.urls import path, include
    from rest_framework.routers import DefaultRouter
    from .views import BookViewSet
    
    router = DefaultRouter()
    router.register(r'books', BookViewSet, basename='book')
    
    urlpatterns = [
        path('', include(router.urls)),
    ]

    Finally, include the app’s URLs in the project’s myapi/urls.py:

    from django.contrib import admin
    from django.urls import path, include
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('api/', include('books.urls')),
    ]

    Authentication and Permissions

    APIs rarely stay open to the world. DRF provides several authentication schemes out of the box. For a quick start, enable token authentication:

    pip install djangorestframework-simplejwt

    Update myapi/settings.py with the authentication classes:

    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework_simplejwt.authentication.JWTAuthentication',
        ),
        'DEFAULT_PERMISSION_CLASSES': (
            'rest_framework.permissions.IsAuthenticated',
        ),
    }

    Generate JWT tokens via the provided endpoints (you’ll add them later) and protect the BookViewSet by inheriting from IsAuthenticatedOrReadOnly if you want public read access but restricted writes:

    from rest_framework.permissions import IsAuthenticatedOrReadOnly
    
    class BookViewSet(viewsets.ModelViewSet):
        queryset = Book.objects.all()
        serializer_class = BookSerializer
        permission_classes = [IsAuthenticatedOrReadOnly]

    Testing Your API

    Automated tests ensure your API behaves as expected. DRF ships with an API test client that extends Django’s Client. Example in books/tests.py:

    from rest_framework.test import APITestCase
    from django.urls import reverse
    from .models import Book
    
    class BookAPITest(APITestCase):
        def setUp(self):
            self.book = Book.objects.create(
                title='Django for APIs',
                author='John Doe',
                published_date='2023-01-01',
                isbn='1234567890123'
            )
            self.list_url = reverse('book-list')
    
        def test_list_books(self):
            response = self.client.get(self.list_url)
            self.assertEqual(response.status_code, 200)
            self.assertEqual(len(response.data), 1)
    
        def test_create_book_unauthenticated(self):
            data = {
                'title': 'New Book',
                'author': 'Jane Smith',
                'published_date': '2024-05-10',
                'isbn': '9876543210987'
            }
            response = self.client.post(self.list_url, data, format='json')
            self.assertEqual(response.status_code, 401)  # Unauthorized

    Best Practices and Performance Tips

    • Use Select Related / Prefetch Related in viewsets to avoid N+1 query problems.
    • Limit Fields with fields Query Parameter for large objects—DRF’s DynamicFieldsModelSerializer pattern helps.
    • Implement Pagination (PageNumber, LimitOffset, or Cursor) to keep responses lightweight.
    • Cache Frequently Accessed Endpoints using Django’s cache framework or third‑party solutions like Redis.
    • Document Your API with Swagger/OpenAPI via drf-yasg or drf-spectacular for developer-friendly docs.
    • Version Your API from day one (e.g., /api/v1/) to simplify future upgrades.

    Deploying the DRF Application

    When you’re ready to go live, follow these production steps:

    1. Switch DEBUG = False and configure ALLOWED_HOSTS.
    2. Set up a robust database (PostgreSQL is the de‑facto standard).
    3. Use gunicorn or uvicorn as the WSGI/ASGI server.
    4. Serve static files with whitenoise or a dedicated CDN.
    5. Secure the API with HTTPS (Let’s Encrypt provides free certificates).
    6. Consider containerizing with Docker for consistent deployments.

    Conclusion

    Whether you’re building a simple mobile backend or a complex micro‑service architecture, Django REST Framework gives you the tools to deliver fast, secure, and maintainable APIs with minimal code. By mastering serializers, viewsets, routers, and authentication, you’ll be able to expose your Django models as clean

  • Python Flask E-Commerce Cart Management

    Running a successful e‑commerce site with Python Flask starts with a smooth, reliable shopping cart experience. From adding the first product to the checkout page, users expect instant feedback, accurate totals, and the ability to edit their selections on the fly. In this guide we’ll explore the core concepts, best practices, and step‑by‑step code you need to build a robust cart management system in Flask—perfect for startups, hobby projects, and scalable online stores alike.

    Why Flask Is Ideal for E‑Commerce Cart Management

    Flask’s lightweight nature gives you full control over every layer of the cart workflow:

    • Flexibility: Choose your own database, session store, and front‑end framework without being locked into a monolithic architecture.
    • Extensibility: Plug in extensions like Flask‑Login, Flask‑SQLAlchemy, or Flask‑Session to add authentication, ORM, and server‑side sessions in minutes.
    • Performance: Minimal overhead means faster response times—crucial when users are adding items and expecting real‑time price updates.

    Key Components of a Flask Shopping Cart

    1. Session‑Based Storage vs. Database Persistence

    For most small‑to‑medium stores, storing the cart in a signed Flask session is the simplest approach. It keeps the cart data on the client side (encrypted in a cookie) and requires no extra tables. However, if you need persistent carts across devices, wish to track abandoned carts, or handle large inventories, a dedicated CartItem model in your database is the better choice.

    2. Product Catalog Integration

    The cart must reference the same product records used throughout the site. This ensures price consistency, stock validation, and easy promotion handling. Typically you’ll query the Product model with SQLAlchemy, then store only the product_id, quantity, and a snapshot of the price in the cart.

    3. Cart Operations API

    Expose clear endpoints for common actions:

    1. POST /cart/add – Add a product or increase quantity.
    2. POST /cart/update – Change quantity or apply a discount code.
    3. POST /cart/remove – Delete an item.
    4. GET /cart – Retrieve the current cart state for rendering.

    Using JSON responses and AJAX calls on the front end keeps the user experience seamless.

    Implementing a Session‑Based Cart

    Below is a minimal yet production‑ready implementation that stores cart data in flask.session. It includes validation, price calculation, and a helper function for rendering the cart.

    from flask import Flask, session, request, jsonify, abort
    from flask_sqlalchemy import SQLAlchemy
    from decimal import Decimal
    
    app = Flask(__name__)
    app.config['SECRET_KEY'] = 'your‑strong‑secret‑key'
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///store.db'
    db = SQLAlchemy(app)
    
    class Product(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(120), nullable=False)
        price = db.Column(db.Numeric(10, 2), nullable=False)
        stock = db.Column(db.Integer, default=0)
    
    def _init_cart():
        if 'cart' not in session:
            session['cart'] = {}
    
    def _save_cart():
        session.modified = True
    
    def _calculate_totals():
        total = Decimal('0.00')
        for pid, item in session['cart'].items():
            total += Decimal(item['price']) * item['quantity']
        return total
    
    @app.route('/cart/add', methods=['POST'])
    def add_to_cart():
        _init_cart()
        data = request.get_json()
        product_id = str(data.get('product_id'))
        qty = int(data.get('quantity', 1))
    
        product = Product.query.get_or_404(product_id)
        if product.stock < qty:
            abort(400, description='Insufficient stock.')
    
        cart = session['cart']
        if product_id in cart:
            cart[product_id]['quantity'] += qty
        else:
            cart[product_id] = {
                'name': product.name,
                'price': str(product.price),  # store as string for JSON safety
                'quantity': qty
            }
        _save_cart()
        return jsonify({'message': 'Item added', 'cart': session['cart']})
    

    Repeat similar logic for /cart/update and /cart/remove routes, always re‑calculating totals and checking stock levels.

    Persisting Carts with a Database Model

    When you need carts to survive user logins, device changes, or abandoned‑cart emails, create a dedicated model. Below is a concise schema and service layer.

    class Cart(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
        created_at = db.Column(db.DateTime, default=db.func.now())
    
    class CartItem(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        cart_id = db.Column(db.Integer, db.ForeignKey('cart.id'), nullable=False)
        product_id = db.Column(db.Integer, db.ForeignKey('product.id'), nullable=False)
        quantity = db.Column(db.Integer, nullable=False, default=1)
        price_at_add = db.Column(db.Numeric(10, 2), nullable=False)  # snapshot
    
    def add_item(user_id, product_id, qty=1):
        cart = Cart.query.filter_by(user_id=user_id).first()
        if not cart:
            cart = Cart(user_id=user_id)
            db.session.add(cart)
            db.session.flush()  # get cart.id
    
        product = Product.query.get_or_404(product_id)
        if product.stock < qty:
            raise ValueError('Insufficient stock')
    
        item = CartItem.query.filter_by(cart_id=cart.id, product_id=product_id).first()
        if item:
            item.quantity += qty
        else:
            item = CartItem(
                cart_id=cart.id,
                product_id=product.id,
                quantity=qty,
                price_at_add=product.price
            )
            db.session.add(item)
    
        db.session.commit()
        return cart
    

    Link the cart to Flask‑Login so that each authenticated user automatically loads their persisted cart on login.

    Handling Discounts, Taxes, and Shipping

    Real‑world carts rarely consist of just product totals. Extend the calculation routine to incorporate:

    • Coupon codes: Validate against a Coupon table, apply percentage or fixed discounts.
    • Tax rates: Use a service like taxjar or store state‑based rates in a TaxRule model.
    • Shipping fees: Calculate based on weight, destination, or carrier APIs (e.g., Shippo, EasyPost).

    Keep each component modular; a function apply_cart_modifiers(cart) can chain the calculations and return a detailed breakdown for the front end.

    Front‑End Integration with AJAX

    To provide a frictionless experience, update the cart without full page reloads. Here’s a lightweight jQuery example that posts a new item and refreshes the cart summary.

    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script>
    function addToCart(productId, qty) {
        $.ajax({
            url: '/cart/add',
            type: 'POST',
            contentType: 'application/json',
            data: JSON.stringify({product_id: productId, quantity: qty}),
            success: function(response) {
                $('#cart-count').text(Object.keys(response.cart).length);
                $('#cart-total').text('$' + response.cartTotal);
            },
            error: function(xhr) {
                alert('Error: ' + xhr.responseJSON.description);
            }
        });
    }
    </script>
    

    Combine this script with a responsive <div id="cart-summary"> that displays line items, allowing users to edit quantities inline.

    Best Practices for Secure and Scalable Cart Management

    • Never trust client data: Always re‑fetch product prices from the database before finalizing an order.
    • Use signed cookies or server‑side sessions: Prevent tampering by enabling SESSION_COOKIE_HTTPONLY and SESSION_COOKIE_SECURE in production.
    • Implement optimistic locking: When reducing stock, use a version column or SELECT … FOR UPDATE to avoid race conditions.
    • Limit cart size: Cap the number of distinct items (e.g., 100) to protect against DoS attacks.
    • Log cart activity: Store events like “add”, “remove”, and “checkout” for analytics and fraud detection.

    Testing Your Cart Logic

    Automated tests catch edge cases early. Use pytest with Flask’s test client to simulate cart actions:

    def test_add_to_cart(client, init_database):
    # Arrange
    product = Product(name='Test T‑Shirt', price=Decimal('19.99'), stock=10)
    db.session.add(product)
    db.session.commit()

    # Act
    response

  • Python Flask Real-Time Chat With Socketio

    Building a real‑time chat application is one of the most exciting ways to showcase the power of Python Flask combined with SocketIO. Whether you’re a seasoned developer looking to add live messaging to a web app or a beginner eager to see Flask in action, this guide walks you through every step—from setting up the environment to deploying a production‑ready chat server. By the end, you’ll have a fully functional, responsive chat room that updates instantly for every connected user, all while keeping your code clean, maintainable, and SEO‑friendly.

    Why Choose Flask and SocketIO for Real‑Time Chat?

    Flask is a lightweight, micro‑framework that gives you the flexibility to structure your project exactly the way you want. When paired with SocketIO, you gain a powerful, event‑driven communication layer that abstracts the complexities of WebSockets, long‑polling, and fallback transports. This combination offers:

    • Fast development cycles—Flask’s simple routing and templating let you prototype quickly.
    • Bi‑directional communication—SocketIO enables instant message delivery from server to client and vice‑versa.
    • Scalability—Both Flask and SocketIO can be scaled horizontally with message brokers like Redis.
    • Cross‑browser support—SocketIO automatically selects the best transport method for each client.

    Prerequisites and Environment Setup

    System Requirements

    Before you dive into code, make sure you have the following installed:

    1. Python 3.8 or newer
    2. pip (Python package manager)
    3. Virtualenv (optional but recommended)

    Installing Required Packages

    Open a terminal and run the commands below. They install Flask, Flask‑SocketIO, and a development server based on eventlet (or gevent if you prefer).

    python -m venv venv
    source venv/bin/activate   # On Windows use `venv\Scripts\activate`
    pip install Flask Flask-SocketIO eventlet
    

    These packages provide the core functionality you’ll need to handle HTTP routes, WebSocket connections, and asynchronous event loops.

    Creating the Flask Application

    Project Structure

    A clean project layout makes maintenance easier. Below is a minimal yet organized structure:

    my_chat_app/
    │
    ├─ app.py               # Main Flask & SocketIO entry point
    ├─ templates/
    │   └─ index.html       # Chat UI
    └─ static/
        └─ js/
            └─ chat.js      # Client‑side SocketIO logic
    

    Writing app.py

    The following snippet sets up a Flask app, initializes SocketIO, and defines the essential events for joining a room and sending messages.

    from flask import Flask, render_template, request
    from flask_socketio import SocketIO, join_room, leave_room, emit
    
    app = Flask(__name__)
    app.config['SECRET_KEY'] = 'replace-with-a-secure-key'
    socketio = SocketIO(app, async_mode='eventlet')
    
    @app.route('/')
    def index():
        return render_template('index.html')
    
    @socketio.on('join')
    def handle_join(data):
        username = data['username']
        room = data['room']
        join_room(room)
        emit('status', {'msg': f'{username} has entered the room.'}, room=room)
    
    @socketio.on('message')
    def handle_message(data):
        room = data['room']
        emit('message', data, room=room)
    
    @socketio.on('leave')
    def handle_leave(data):
        username = data['username']
        room = data['room']
        leave_room(room)
        emit('status', {'msg': f'{username} has left the room.'}, room=room)
    
    if __name__ == '__main__':
        socketio.run(app, debug=True)
    

    Key points to note:

    • async_mode='eventlet' tells Flask‑SocketIO to use the highly efficient Eventlet server.
    • Each event (join, message, leave) broadcasts to the specified room, keeping conversations isolated.
    • The SECRET_KEY should be replaced with a strong, random value in production.

    Designing the Front‑End Chat Interface

    HTML Template (templates/index.html)

    This template provides a simple UI with a username field, a room selector, and a message input. It also loads the SocketIO client library from a CDN.

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Flask SocketIO Real‑Time Chat</title>
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/milligram/1.4.1/milligram.min.css">
        <style>
            #chat { height: 400px; overflow-y: scroll; border: 1px solid #ddd; padding: 10px; }
            .status { color: #777; font-style: italic; }
        </style>
    </head>
    <body>
        <div class="container">
            <h2>Flask‑SocketIO Real‑Time Chat</h2>
            <div id="login">
                <input type="text" id="username" placeholder="Enter your name">
                <input type="text" id="room" placeholder="Room name">
                <button id="joinBtn">Join Chat</button>
            </div>
            <div id="chatSection" style="display:none;">
                <div id="chat"></div>
                <input type="text" id="msgInput" placeholder="Type a message">
                <button id="sendBtn">Send</button>
                <button id="leaveBtn">Leave</button>
            </div>
        </div>
        <script src="https://cdn.socket.io/4.7.2/socket.io.min.js"></script>
        <script src="{{ url_for('static', filename='js/chat.js') }}"></script>
    </body>
    </html>
    

    Client‑Side JavaScript (static/js/chat.js)

    The script handles UI interactions, emits events to the server, and updates the chat window when new messages arrive.

    document.addEventListener('DOMContentLoaded', () => {
        const socket = io();
    
        const loginDiv   = document.getElementById('login');
        const chatDiv    = document.getElementById('chatSection');
        const chatBox    = document.getElementById('chat');
        const usernameEl = document.getElementById('username');
        const roomEl     = document.getElementById('room');
        const msgInput   = document.getElementById('msgInput');
    
        // Join a chat room
        document.getElementById('joinBtn').onclick = () => {
            const username = usernameEl.value.trim();
            const room = roomEl.value.trim();
            if (!username || !room) return alert('Both fields are required.');
            socket.emit('join', {username, room});
            loginDiv.style.display = 'none';
            chatDiv.style.display = 'block';
        };
    
        // Send a message
        document.getElementById('sendBtn').onclick = () => {
            const msg = msgInput.value.trim();
            const room = roomEl.value.trim();
            const username = usernameEl.value.trim();
            if (msg) {
                socket.emit('message', {username, room, msg});
                msgInput.value = '';
            }
        };
    
        // Leave the room
        document.getElementById('leaveBtn').onclick = () => {
            const username = usernameEl.value.trim();
            const room = roomEl.value.trim();
            socket.emit('leave', {username, room});
            chatDiv.style.display = 'none';
            loginDiv.style.display = 'block';
            chatBox.innerHTML = '';
        };
    
        // Receive a normal message
        socket.on('message', data => {
            const el = document.createElement('p');
            el.innerHTML = `${data.username}: ${data.msg}`;
            chatBox.appendChild(el);
            chatBox.scrollTop = chatBox.scrollHeight;
        });
    
        // Receive status updates (join/leave)
        socket.on('status', data => {
            const el = document.createElement('p');
            el.className = 'status';
            el.textContent = data.msg;
            chatBox.appendChild(el);
            chatBox.scrollTop = chatBox.scrollHeight;
        });
    });
    

    Adding Advanced Features

  • Python Flask Microservices Architecture

    In today’s fast‑paced software landscape, building scalable, maintainable, and resilient applications is no longer a luxury—it’s a necessity. Python Flask microservices architecture has emerged as a powerful approach that combines Flask’s lightweight simplicity with the flexibility of microservices. In this guide, we’ll explore why Flask is a natural fit for microservices, walk through the core components of a robust architecture, and provide practical code examples to help you design, develop, and deploy production‑ready services.

    Why Choose Flask for Microservices?

    Flask is often described as a “micro‑framework” because it provides just enough tools to get a web application up and running without imposing heavy conventions. This minimalism translates into several advantages when you adopt a microservices mindset:

    • Low overhead: Each service can stay lightweight, reducing memory and CPU consumption.
    • Easy to containerize: Small codebases fit neatly into Docker images, speeding up build and deployment cycles.
    • Flexible routing: Flask’s routing system lets you expose RESTful endpoints exactly the way you need them.
    • Extensible ecosystem: Extensions such as Flask‑SQLAlchemy, Flask‑JWT‑Extended, and Flask‑RESTful add database, security, and API capabilities without bloating the core.
    • Python familiarity: Teams already proficient in Python can leverage existing knowledge, shortening the learning curve.

    Core Principles of a Flask‑Based Microservices Architecture

    1. Single Responsibility per Service

    Each microservice should own a distinct business capability—e.g., user management, order processing, or inventory tracking. This isolation simplifies testing, scaling, and independent deployment.

    2. Statelessness

    Stateless services can be replicated horizontally without complex session synchronization. Store session data in external caches like Redis or use JWTs for authentication.

    3. API‑First Design

    Define clear contracts using OpenAPI (Swagger) specifications. This enables automatic client generation, documentation, and contract testing.

    4. Decentralized Data Management

    Each service owns its database schema. Avoid sharing a monolithic database across services; instead, use patterns like Database per Service or Shared‑Nothing to maintain independence.

    5. Asynchronous Communication

    While synchronous HTTP calls are simple, integrating a message broker (e.g., RabbitMQ, Apache Kafka) allows services to react to events without blocking, improving resilience and throughput.

    Setting Up a Basic Flask Microservice

    Below is a minimal yet production‑ready Flask service that demonstrates routing, error handling, and JWT‑based authentication.

    # app.py
    from flask import Flask, jsonify, request
    from flask_jwt_extended import (
        JWTManager, create_access_token, jwt_required, get_jwt_identity
    )
    
    app = Flask(__name__)
    app.config['JWT_SECRET_KEY'] = 'super‑secret-key'  # Replace with env var in prod
    jwt = JWTManager(app)
    
    # In‑memory user store (replace with DB in real apps)
    USERS = {
        "alice": "password123",
        "bob": "securepwd"
    }
    
    @app.route('/login', methods=['POST'])
    def login():
        data = request.get_json()
        username = data.get('username')
        password = data.get('password')
        if USERS.get(username) == password:
            access_token = create_access_token(identity=username)
            return jsonify(access_token=access_token), 200
        return jsonify(msg='Invalid credentials'), 401
    
    @app.route('/hello', methods=['GET'])
    @jwt_required()
    def hello():
        current_user = get_jwt_identity()
        return jsonify(msg=f'Hello, {current_user}!'), 200
    
    @app.errorhandler(404)
    def not_found(e):
        return jsonify(error='Resource not found'), 404
    
    if __name__ == '__main__':
        app.run(host='0.0.0.0', port=5000)
    

    Key takeaways from the snippet:

    • Use flask_jwt_extended for stateless authentication.
    • Separate error handling improves API consistency.
    • Running on 0.0.0.0 makes the container accessible from the host.

    Containerizing the Service with Docker

    Docker standardizes the runtime environment, ensuring that the same code runs locally, in CI pipelines, and in production.

    # Dockerfile
    FROM python:3.11-slim
    
    # Set working directory
    WORKDIR /app
    
    # Install dependencies
    COPY requirements.txt .
    RUN pip install --no-cache-dir -r requirements.txt
    
    # Copy source code
    COPY . .
    
    # Expose Flask default port
    EXPOSE 5000
    
    # Use a non‑root user for security
    RUN useradd -m appuser
    USER appuser
    
    # Start the service
    CMD ["python", "app.py"]
    

    Build and run the container:

    docker build -t user‑service:latest .
    docker run -d -p 5000:5000 --name user-service user‑service:latest
    

    Orchestrating Multiple Services with Docker Compose

    When you have several microservices—e.g., user-service, order-service, and inventory-service—Docker Compose provides a simple way to spin them up together.

    # docker-compose.yml
    version: '3.9'
    
    services:
      user:
        build: ./user-service
        ports:
          - "5000:5000"
        environment:
          - JWT_SECRET_KEY=${JWT_SECRET_KEY}
        networks:
          - backend
    
      order:
        build: ./order-service
        ports:
          - "5001:5000"
        depends_on:
          - user
        networks:
          - backend
    
      inventory:
        build: ./inventory-service
        ports:
          - "5002:5000"
        depends_on:
          - order
        networks:
          - backend
    
    networks:
      backend:
        driver: bridge
    

    This file defines three isolated services that share a private backend network, allowing them to communicate via service names (e.g., http://user:5000).

    Inter‑Service Communication Patterns

    Synchronous HTTP Calls

    For simple request‑response interactions, use requests or httpx inside each Flask service.

    # order_service.py (excerpt)
    import requests
    
    USER_SERVICE_URL = "http://user:5000"
    
    def validate_user(token):
        headers = {"Authorization": f"Bearer {token}"}
        resp = requests.get(f"{USER_SERVICE_URL}/hello", headers=headers)
        return resp.status_code == 200
    

    Asynchronous Messaging with RabbitMQ

    When you need eventual consistency or want to decouple services, publish events to a message broker.

    # publisher.py
    import pika
    import json
    
    connection = pika.BlockingConnection(pika.URLParameters('amqp://guest:guest@rabbitmq:5672/'))
    channel = connection.channel()
    channel.exchange_declare(exchange='orders', exchange_type='topic')
    
    def publish_order_created(order_id, payload):
        message = json.dumps({"order_id": order_id, "data": payload})
        channel.basic_publish(
            exchange='orders',
            routing_key='order.created',
            body=message
        )
    

    Consumers in other services subscribe to the order.created topic and process the payload independently.

    Service Discovery and Load Balancing

    In a dynamic environment where containers can scale up or down, hard‑coding service URLs becomes fragile. Two common solutions are:

    1. Docker Swarm / Kubernetes DNS: Each service registers a DNS entry (e.g., user), and the orchestrator automatically updates the address list.
    2. Consul or etcd: External service‑registry tools provide health‑checking and key‑value storage for service locations.

    When using Kubernetes, you can expose each Flask microservice with a ClusterIP service and let an Ingress controller (like Nginx) handle external traffic and TLS termination.

    Observability: Logging, Metrics, and Tracing

    Microservices thrive on visibility. Integrate the following tools to gain insight into your Flask ecosystem:

    • Logging: Use structlog or loguru to emit JSON‑structured logs that can be shipped to ELK or Loki.
    • Metrics: Export Prometheus metrics via prometheus_flask_exporter and visualize them in Grafana.
    • Distributed Tracing: Instrument Flask with OpenTelemetry and send traces to Jaeger or Zipkin.

    Example of adding a Prometheus endpoint:

    # metrics.py
    from prometheus_flask_exporter import PrometheusMetrics
    from flask import Flask
    
    app = Flask(__name__)
    metrics = PrometheusMetrics(app)  # automatically registers /metrics
    
    @app.route('/health')
    def health():
        return 'OK', 200
    

    Testing Strategies for Flask Microservices

    Reliable testing pipelines are essential for microservice reliability. Focus on three layers:

    Unit Tests

    Mock external calls (e.g., database, HTTP requests) using unittest.mock or pytest‑mock. Keep tests fast and isolated.

    Integration Tests

    Spin up dependent services with

  • Python Flask Role-Based Access Control

    Python Flask role-based access control (RBAC) is the cornerstone of building secure, multi‑tenant web applications that serve different user groups with distinct permissions. Whether you’re developing an internal dashboard, a SaaS platform, or an e‑commerce site, implementing RBAC correctly prevents unauthorized actions, reduces the attack surface, and improves maintainability. In this guide we’ll walk through the core concepts of RBAC, explore popular Flask extensions, and provide a step‑by‑step code example that you can copy‑paste into your own project.

    Understanding Role‑Based Access Control in Flask

    Before diving into code, it’s essential to grasp what RBAC actually means and why it fits naturally with Flask’s lightweight design.

    What is RBAC?

    • Roles: Named collections of permissions (e.g., admin, editor, viewer).
    • Permissions: Specific actions a user can perform, such as create_post or delete_user.
    • Assignments: Users are linked to one or more roles, inheriting all associated permissions.

    Why Choose RBAC over Simple Authentication?

    • Scalability – Adding a new permission only requires updating the role definition, not every user record.
    • Clarity – Business stakeholders can reason about “who can do what” using familiar role names.
    • Security – Centralized permission checks reduce the risk of forgotten or duplicated logic.

    Key Flask Extensions for RBAC

    Flask’s ecosystem offers several extensions that simplify RBAC implementation. The most popular choices are:

    • Flask‑Login: Handles user session management (login, logout, remember‑me).
    • Flask‑Principal: Provides a flexible identity and permission system that works well with Flask‑Login.
    • Flask‑User or Flask‑Security‑Too: All‑in‑one solutions that bundle authentication, role management, and password recovery.

    For this tutorial we’ll combine Flask‑Login and Flask‑Principal because they give fine‑grained control while staying lightweight.

    Step‑by‑Step Implementation

    1. Project Setup

    mkdir flask_rbac_demo
    cd flask_rbac_demo
    python -m venv venv
    source venv/bin/activate   # Windows: venv\Scripts\activate
    pip install Flask Flask-Login Flask-Principal Flask-SQLAlchemy
    

    2. Define the Data Model

    We’ll use SQLAlchemy to store users, roles, and the many‑to‑many relationship between them.

    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    from flask_login import UserMixin
    
    app = Flask(__name__)
    app.config['SECRET_KEY'] = 'replace‑with‑strong‑secret'
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///rbac.db'
    db = SQLAlchemy(app)
    
    # Association table linking users and roles
    user_roles = db.Table('user_roles',
        db.Column('user_id', db.Integer, db.ForeignKey('user.id')),
        db.Column('role_id', db.Integer, db.ForeignKey('role.id'))
    )
    
    class Role(db.Model):
        id   = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(64), unique=True, nullable=False)
    
        def __repr__(self):
            return f''
    
    class User(UserMixin, db.Model):
        id       = db.Column(db.Integer, primary_key=True)
        username = db.Column(db.String(64), unique=True, nullable=False)
        password = db.Column(db.String(128), nullable=False)  # hashed
        roles    = db.relationship('Role', secondary=user_roles,
                                   backref=db.backref('users', lazy='dynamic'))
    
        def has_role(self, role_name):
            return any(role.name == role_name for role in self.roles)
    
        def __repr__(self):
            return f''
    

    3. Initialize Flask‑Login

    from flask_login import LoginManager, login_user, logout_user, current_user, login_required
    
    login_manager = LoginManager(app)
    login_manager.login_view = 'login'   # redirect unauthenticated users
    
    @login_manager.user_loader
    def load_user(user_id):
        return User.query.get(int(user_id))
    

    4. Set Up Flask‑Principal

    Flask‑Principal works with Identity objects that carry a set of Need objects (roles, permissions, etc.).

    from flask_principal import Principal, Identity, AnonymousIdentity, \
        identity_changed, identity_loaded, RoleNeed, UserNeed
    
    principal = Principal(app)
    
    # When a user logs in, we push an Identity containing their roles
    @app.route('/login', methods=['GET', 'POST'])
    def login():
        # (Simplified: replace with proper form validation & password hashing)
        if request.method == 'POST':
            user = User.query.filter_by(username=request.form['username']).first()
            if user and user.password == request.form['password']:
                login_user(user)
                # Notify Flask‑Principal of the identity change
                identity_changed.send(app, identity=Identity(user.id))
                return redirect(url_for('index'))
        return render_template('login.html')
    
    # Logout clears the identity
    @app.route('/logout')
    @login_required
    def logout():
        logout_user()
        identity_changed.send(app, identity=AnonymousIdentity())
        return redirect(url_for('index'))
    
    # Load the user’s roles into the Identity
    @identity_loaded.connect_via(app)
    def on_identity_loaded(sender, identity):
        # Set the identity user object
        identity.user = current_user
    
        # Add the UserNeed (unique identifier)
        if hasattr(current_user, 'id'):
            identity.provides.add(UserNeed(current_user.id))
    
        # Add each role as a RoleNeed
        if hasattr(current_user, 'roles'):
            for role in current_user.roles:
                identity.provides.add(RoleNeed(role.name))
    

    5. Create a Permission Decorator

    Flask‑Principal ships with Permission objects that can be used as decorators.

    from flask_principal import Permission, RoleNeed
    
    admin_permission   = Permission(RoleNeed('admin'))
    editor_permission  = Permission(RoleNeed('editor'))
    viewer_permission  = Permission(RoleNeed('viewer'))
    
    def permission_required(permission):
        def decorator(f):
            @wraps(f)
            def decorated_function(*args, **kwargs):
                if permission.can():
                    return f(*args, **kwargs)
                return abort(403)   # Forbidden
            return decorated_function
        return decorator
    

    6. Protect Routes with RBAC

    @app.route('/admin')
    @login_required
    @permission_required(admin_permission)
    def admin_dashboard():
        return render_template('admin.html')
    
    @app.route('/edit')
    @login_required
    @permission_required(editor_permission)
    def edit_page():
        return render_template('edit.html')
    
    @app.route('/view')
    @login_required
    @permission_required(viewer_permission)
    def view_page():
        return render_template('view.html')
    

    7. Seed the Database with Sample Data

    def seed():
        db.create_all()
        # Create roles
        admin = Role(name='admin')
        editor = Role(name='editor')
        viewer = Role(name='viewer')
        db.session.add_all([admin, editor, viewer])
        db.session.commit()
    
        # Create users
        alice = User(username='alice', password='alicepwd')
        bob   = User(username='bob',   password='bobpwd')
        carol = User(username='carol', password='carolpwd')
    
        # Assign roles
        alice.roles.append(admin)   # Alice is an admin
        bob.roles.append(editor)    # Bob can edit
        carol.roles.append(viewer)  # Carol can only view
    
        db.session.add_all([alice, bob, carol])
        db.session.commit()
    
    if __name__ == '__main__':
        seed()
        app.run(debug=True)
    

    Best Practices for Flask RBAC

    • Never hard‑code passwords. Use werkzeug.security.generate_password_hash and check_password_hash for storage and verification.
    • Prefer role names over numeric IDs. Human‑readable names make audits and logs easier to understand.
    • Separate permission logic from view code. Keep the Permission objects in a dedicated permissions.py module.
    • Cache role lookups. For high‑traffic apps, store a user’s role list in Redis or the session to avoid repeated DB hits.
    • Log authorization failures. Recording a 403 event with the user ID and requested endpoint helps detect malicious probing.

    Testing Your RBAC Implementation

    Automated tests ensure that role changes behave as expected. Below is a minimal pytest example using Flask’s test client.

    import pytest
    from app import app, db, User, Role

    @pytest.fixture
    def client():
    app.config['TESTING'] = True
    with app.test_client() as client:
    with app.app_context():
    db.create_all()
    # Setup roles and a test user
    admin_role = Role(name='admin')
    db.session.add(admin_role)
    test_user = User(username='tester', password='test')
    test_user.roles.append(admin_role)
    db.session.add(test_user)
    db.session.commit()
    yield client
    db.drop_all()

    def login(client, username, password):
    return client.post('/login', data=dict(username=username, password=password), follow_redirects=True)

    def test_admin_access(client):
    login(client, 'tester', 'test')
    response = client.get('/admin')
    assert response.status_code == 200 #

  • Python Flask Portfolio Website Project

    Building a Python Flask portfolio website is a fantastic way to showcase your projects, demonstrate your web development skills, and create a personal brand that stands out to recruiters and clients. In this step‑by‑step guide you’ll learn how to set up a clean, responsive portfolio using Flask, organize your code for scalability, and optimize the site for search engines—all while keeping the project beginner‑friendly and highly customizable.

    Why Choose Flask for a Portfolio Site?

    Flask is a lightweight micro‑framework that gives you full control over the structure of your application. Unlike heavyweight CMS platforms, Flask lets you:

    • Write clean Python code without the overhead of a full‑stack framework.
    • Integrate Jinja2 templates for dynamic HTML rendering.
    • Easily add extensions such as Flask‑SQLAlchemy or Flask‑Mail when you need more features.
    • Deploy to any platform that supports WSGI, from Heroku to Render or your own VPS.

    Project Overview

    Our portfolio will consist of three main parts:

    1. A home page that introduces you and highlights key skills.
    2. A projects page that pulls data from a JSON file (or a database) and displays each project with images, descriptions, and links.
    3. A contact form that sends messages directly to your email using Flask‑Mail.

    All pages will be responsive, SEO‑friendly, and easy to extend.

    Step 1: Setting Up the Development Environment

    First, make sure you have Python 3.9+ installed. Then create a virtual environment and install Flask.

    python -m venv venv
    source venv/bin/activate   # On Windows use: venv\Scripts\activate
    pip install Flask Flask-Mail
    

    Optional extensions for future growth:

    pip install Flask-SQLAlchemy Flask-WTF python-dotenv
    

    Step 2: Project Folder Structure

    A well‑organized directory makes maintenance painless. Below is a recommended layout:

    portfolio/
    │
    ├─ app/
    │   ├─ __init__.py          # Application factory
    │   ├─ routes.py            # View functions
    │   ├─ models.py            # (optional) Database models
    │   ├─ static/
    │   │   ├─ css/
    │   │   │   └─ style.css
    │   │   ├─ img/
    │   │   │   └─ profile.jpg
    │   │   └─ js/
    │   │       └─ main.js
    │   └─ templates/
    │       ├─ base.html
    │       ├─ index.html
    │       ├─ projects.html
    │       └─ contact.html
    │
    ├─ data/
    │   └─ projects.json        # Project metadata
    │
    ├─ .env                     # Environment variables
    ├─ config.py                # Configuration settings
    └─ run.py                   # Entry point
    

    Step 3: Creating the Flask Application Factory

    Using an application factory keeps the code testable and allows multiple instances (e.g., for testing).

    # app/__init__.py
    from flask import Flask
    from flask_mail import Mail
    from config import Config
    
    mail = Mail()
    
    def create_app():
        app = Flask(__name__)
        app.config.from_object(Config)
    
        mail.init_app(app)
    
        from . import routes
        app.register_blueprint(routes.main_bp)
    
        return app
    

    Step 4: Defining Routes and Views

    All page logic lives in routes.py. We’ll use a Blueprint for clean separation.

    # app/routes.py
    from flask import Blueprint, render_template, request, flash, redirect, url_for, current_app
    from flask_mail import Message
    import json, os
    
    main_bp = Blueprint('main', __name__)
    
    @main_bp.route('/')
    def home():
        return render_template('index.html')
    
    @main_bp.route('/projects')
    def projects():
        # Load project data from JSON
        data_path = os.path.join(current_app.root_path, '..', 'data', 'projects.json')
        with open(data_path) as f:
            projects = json.load(f)
        return render_template('projects.html', projects=projects)
    
    @main_bp.route('/contact', methods=['GET', 'POST'])
    def contact():
        if request.method == 'POST':
            name = request.form['name']
            email = request.form['email']
            message = request.form['message']
    
            msg = Message(subject=f'Portfolio Contact from {name}',
                          sender=current_app.config['MAIL_DEFAULT_SENDER'],
                          recipients=[current_app.config['MAIL_USERNAME']],
                          body=f'Name: {name}\\nEmail: {email}\\n\\n{message}')
            mail.send(msg)
            flash('Your message has been sent!', 'success')
            return redirect(url_for('main.contact'))
    
        return render_template('contact.html')
    

    Step 5: Building SEO‑Friendly Templates

    Each template inherits from base.html, which contains meta tags, Open Graph data, and a clean navigation bar.

    
    
    
    
        
        {% block title %}My Flask Portfolio{% endblock %}
        
        
        
        
        
        
        
    
    
        
    
        
    {% block content %}{% endblock %}

    © {{ current_year }} Your Name. All rights reserved.

    Home Page (index.html)

    
    {% extends "base.html" %}
    {% block title %}Home | My Flask Portfolio{% endblock %}
    {% block content %}
    

    Hello, I’m Your Name

    Full‑stack developer specializing in Python, Flask, and modern JavaScript frameworks.

    View My Work
    {% endblock %}

    Projects Page (projects.html)

    
    {% extends "base.html" %}
    {% block title %}Projects | My Flask Portfolio{% endblock %}
    {% block content %}
    

    Featured Projects

    {% for project in projects %} {% endfor %}
    {% endblock %}

    Contact Page (contact.html)

    
    {% extends "base.html" %}
    {% block title %}Contact | My Flask Portfolio{% endblock %}
    {% block content %}
    

    Get In Touch

    {% with messages = get_flashed_messages(with_categories=true) %} {% if messages %} {% for category, message in messages %}
    {{ message }}
    {% endfor %} {% endif %} {% endwith %}
    {% endblock %}

    Step 6: Managing Project Data with JSON

    Storing project details in a JSON file keeps the site static‑friendly and avoids a full database for a simple portfolio.

    # data/projects.json
    [
      {
        "title": "Flask Blog",
        "description": "A multi‑user blog built with Flask, SQLAlchemy, and Bootstrap.",
        "image": "flask_blog.png",
        "link": "https://example.com/flask-blog",
        "repo": "https://github.com/username/flask-blog"
      },
      {
        "title": "REST API Service",
        "description": "A JSON‑based REST API for managing tasks, secured with JWT.",
        "image": "rest_api.png",
        "link": "https://example.com/rest-api",
        "repo": "https://github.com/username/rest-api"
      }
    ]
    

    Step 7: Configuring Environment Variables and Mail Settings

    Never hard‑code credentials. Use a .env file and load it with python-dotenv.

  • Python Flask File Upload Security Guide

    Uploading files is a core feature for many Flask applications, from profile picture galleries to document management systems. However, a careless implementation can open the door to severe security breaches, including remote code execution, data leakage, and server compromise. This guide walks you through the most effective strategies to secure file uploads in Python Flask, offering practical code examples, best‑practice checklists, and SEO‑friendly tips that will keep both your users and your code safe.

    Why File Uploads Are a Prime Attack Vector

    Attackers love file uploads because they provide a direct pathway to inject malicious content into a trusted environment. Common threats include:

    • Executable payloads disguised as images or documents.
    • Path traversal attacks that overwrite critical files.
    • Denial‑of‑service through oversized payloads.
    • Cross‑site scripting (XSS) when untrusted content is rendered in browsers.

    Understanding these risks is the first step toward building a Python Flask file upload security strategy that defends against them.

    Common Vulnerabilities in Flask File Uploads

    1. Unrestricted File Types

    Accepting any file extension (e.g., .jpg, .png, .exe) without validation allows attackers to upload scripts that the server may execute.

    2. Insecure Filenames

    Using the original filename directly can lead to directory traversal (e.g., ../../etc/passwd) or overwrite existing files.

    3. Storing Files in Public Directories

    Placing uploads inside static/ or other web‑accessible folders can expose them to the internet, making it easier for malicious content to be served.

    4. Missing Size Limits

    Without a maximum file size, attackers can exhaust server resources, causing a denial‑of‑service.

    Best Practices for Secure Flask File Uploads

    Validate File Type Rigorously

    Never rely solely on the file extension. Use MIME type checking and, when possible, inspect the file header (magic numbers).

    import imghdr
    
    def allowed_file(filename, file_stream):
        allowed_extensions = {'png', 'jpg', 'jpeg', 'gif'}
        ext = filename.rsplit('.', 1)[1].lower() if '.' in filename else ''
        if ext not in allowed_extensions:
            return False
        # Verify the actual content
        header = file_stream.read(512)
        file_stream.seek(0)  # Reset pointer after reading
        return imghdr.what(None, header) in allowed_extensions
    

    Sanitize and Randomize Filenames

    Replace the user‑provided name with a secure, random identifier. Flask’s werkzeug.utils.secure_filename removes dangerous characters, but adding a UUID guarantees uniqueness.

    import uuid
    from werkzeug.utils import secure_filename
    
    def generate_secure_filename(filename):
        ext = filename.rsplit('.', 1)[1].lower()
        random_name = uuid.uuid4().hex
        return f"{random_name}.{ext}"
    

    Store Files Outside the Web Root

    Save uploads in a directory that isn’t directly served by Flask. Serve them through a controlled route that checks permissions before sending the file.

    UPLOAD_FOLDER = '/var/www/app/uploads'  # Not under /static
    
    @app.route('/download/<file_id>')
    def download(file_id):
        # Verify user rights here
        return send_from_directory(UPLOAD_FOLDER, file_id, as_attachment=True)
    

    Enforce Strict Size Limits

    Configure Flask’s request size limit and double‑check on the server side.

    # In config
    MAX_CONTENT_LENGTH = 5 * 1024 * 1024  # 5 MB
    
    # Additional check in view
    if request.content_length > app.config['MAX_CONTENT_LENGTH']:
        abort(413)  # Payload Too Large
    

    Scan Uploaded Files for Malware

    Integrate a scanning tool such as ClamAV or an online API. Even with type validation, sophisticated attackers can embed malicious payloads in seemingly harmless files.

    import subprocess
    
    def scan_file(path):
        result = subprocess.run(['clamscan', '--no-summary', path],
                                stdout=subprocess.PIPE, text=True)
        return 'OK' in result.stdout
    

    Apply Content Security Policy (CSP)

    When serving uploaded content, use CSP headers to restrict how browsers may execute scripts or load resources from the uploaded file.

    @app.after_request
    def set_csp(response):
        response.headers['Content‑Security‑Policy'] = (
            "default-src 'self'; img-src 'self' data:; script-src 'none';"
        )
        return response
    

    Step‑by‑Step Implementation in Flask

    1. Configure the application. Set UPLOAD_FOLDER, MAX_CONTENT_LENGTH, and allowed extensions in app.config.
    2. Create the upload form. Use enctype="multipart/form-data" and a hidden CSRF token.
    3. Handle the POST request. Validate the file, generate a secure name, scan for malware, and save outside the web root.
    4. Serve files safely. Use a dedicated route that checks authentication and applies CSP.

    Below is a compact example that ties these steps together:

    from flask import Flask, request, abort, send_from_directory, render_template_string
    from werkzeug.utils import secure_filename
    import uuid, os, imghdr, subprocess
    
    app = Flask(__name__)
    app.config.update(
        UPLOAD_FOLDER='/var/www/app/uploads',
        MAX_CONTENT_LENGTH=5 * 1024 * 1024,
        ALLOWED_EXTENSIONS={'png', 'jpg', 'jpeg', 'gif'}
    )
    
    def allowed_file(filename, stream):
        ext = filename.rsplit('.', 1)[1].lower()
        if ext not in app.config['ALLOWED_EXTENSIONS']:
            return False
        header = stream.read(512)
        stream.seek(0)
        return imghdr.what(None, header) in app.config['ALLOWED_EXTENSIONS']
    
    def generate_secure_filename(filename):
        ext = filename.rsplit('.', 1)[1].lower()
        return f"{uuid.uuid4().hex}.{ext}"
    
    def scan_file(path):
        result = subprocess.run(['clamscan', '--no-summary', path],
                                stdout=subprocess.PIPE, text=True)
        return 'OK' in result.stdout
    
    @app.route('/', methods=['GET', 'POST'])
    def upload():
        if request.method == 'POST':
            if 'file' not in request.files:
                abort(400, 'No file part')
            file = request.files['file']
            if file.filename == '' or not allowed_file(file.filename, file.stream):
                abort(400, 'Invalid file')
            filename = generate_secure_filename(file.filename)
            save_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
            file.save(save_path)
            if not scan_file(save_path):
                os.remove(save_path)
                abort(400, 'Malware detected')
            return f'File uploaded successfully: {filename}'
        # Simple upload form
        return render_template_string('''
            
    ''') @app.route('/files/<filename>') def download(filename): # Add your auth checks here return send_from_directory(app.config['UPLOAD_FOLDER'], filename) @app.after_request def set_csp(response): response.headers['Content‑Security‑Policy'] = ( "default-src 'self'; img-src 'self' data:; script-src 'none';" ) return response if __name__ == '__main__': app.run(debug=True)

    Testing and Ongoing Monitoring

    Security is not a one‑time configuration. Incorporate these practices into your development lifecycle:

    • Automated tests that attempt to upload disallowed file types and oversized payloads.
    • Static analysis tools that flag unsafe file handling functions.
    • Log monitoring for repeated upload failures, which may indicate probing attempts.
    • Regular updates of your scanning engine (e.g., ClamAV signatures) and Flask dependencies.

    Additional Tools and Resources

    Conclusion

    Implementing a secure file upload system in Python Flask requires a layered

  • Python Flask Blog Application Tutorial

    Welcome to the ultimate Python Flask blog application tutorial! Whether you’re a seasoned developer looking to add a personal blog to your portfolio or a beginner eager to see a real‑world Flask project in action, this guide walks you through every step—from setting up your environment to deploying a SEO‑friendly blog that scales. By the end of this article, you’ll have a fully functional Flask blog, complete with CRUD (Create, Read, Update, Delete) operations, a SQLite database, and a responsive design powered by Bootstrap.

    Why Choose Flask for a Blog?

    Flask is a lightweight, micro‑framework that gives you the flexibility to build exactly what you need without the bloat of larger frameworks. Here are a few reasons Flask shines for blogging platforms:

    • Simple routing: Define URLs with just a decorator.
    • Extensible: Add extensions like Flask‑SQLAlchemy or Flask‑Login as your project grows.
    • Great for SEO: Full control over HTML markup, meta tags, and URL structure.
    • Pythonic: Leverage Python’s readability and vast ecosystem.

    Prerequisites

    Before diving in, make sure you have the following tools installed on your machine:

    1. Python 3.9 or newer
    2. pip (Python package manager)
    3. Virtualenv (optional but recommended)
    4. A code editor (VS Code, PyCharm, etc.)
    5. Basic knowledge of HTML, CSS, and Python

    Setting Up the Development Environment

    1. Create a Virtual Environment

    python -m venv venv
    source venv/bin/activate  # On Windows use: venv\Scripts\activate
    

    2. Install Flask and Required Extensions

    pip install Flask Flask‑SQLAlchemy Flask‑Migrate Flask‑Bootstrap
    

    3. Define Your Project Structure

    A clean folder layout makes the code easier to maintain and scale:

    flask_blog/
    │
    ├── app/
    │   ├── __init__.py
    │   ├── models.py
    │   ├── routes.py
    │   ├── templates/
    │   │   ├── base.html
    │   │   ├── index.html
    │   │   └── post.html
    │   └── static/
    │       └── css/
    │           └── style.css
    │
    ├── migrations/
    ├── config.py
    └── run.py
    

    Creating the Flask Application

    Initialize the App

    Open app/__init__.py and set up the core Flask instance along with the database:

    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    from flask_migrate import Migrate
    from flask_bootstrap import Bootstrap
    
    db = SQLAlchemy()
    migrate = Migrate()
    
    def create_app():
        app = Flask(__name__)
        app.config.from_object('config.Config')
    
        db.init_app(app)
        migrate.init_app(app, db)
        Bootstrap(app)
    
        with app.app_context():
            from . import routes, models
            db.create_all()
    
        return app
    

    Configuration File

    Store sensitive settings in config.py:

    import os
    
    class Config:
        SECRET_KEY = os.getenv('SECRET_KEY', 'dev_key')
        SQLALCHEMY_DATABASE_URI = os.getenv('DATABASE_URL',
            'sqlite:///blog.db')
        SQLALCHEMY_TRACK_MODIFICATIONS = False
    

    Defining the Data Model

    In app/models.py create a simple Post model to store blog entries:

    from . import db
    from datetime import datetime
    
    class Post(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        title = db.Column(db.String(150), nullable=False)
        slug = db.Column(db.String(150), unique=True, nullable=False)
        content = db.Column(db.Text, nullable=False)
        created_at = db.Column(db.DateTime, default=datetime.utcnow)
    
        def __repr__(self):
            return f"<Post {self.title}>"
    

    Building Routes and Templates

    Home Page – List of Posts

    from flask import render_template, request, redirect, url_for, flash
    from . import app, db
    from .models import Post
    from slugify import slugify
    
    @app.route('/')
    def index():
        posts = Post.query.order_by(Post.created_at.desc()).all()
        return render_template('index.html', posts=posts)
    

    Sample templates/index.html using Bootstrap cards:

    <{% extends "base.html" %}>
    <{% block content %}>
    <h2 class="mt-4">Latest Posts</h2>
    <div class="row">
        {% for post in posts %}
        <div class="col-md-6 mb-4">
            <div class="card">
                <div class="card-body">
                    <h5 class="card-title">{{ post.title }}</h5>
                    <p class="card-text">{{ post.content[:150] }}...</p>
                    <a href="{{ url_for('post_detail', slug=post.slug) }}" class="btn btn-primary">Read More</a>
                </div>
            </div>
        </div>
        {% endfor %}
    </div>
    <{% endblock %}>
    

    Post Detail Page

    @app.route('/post/<slug>')
    def post_detail(slug):
        post = Post.query.filter_by(slug=slug).first_or_404()
        return render_template('post.html', post=post)
    

    Implementing CRUD Operations

    Create a New Post

    @app.route('/admin/create', methods=['GET', 'POST'])
    def create_post():
        if request.method == 'POST':
            title = request.form['title']
            content = request.form['content']
            slug = slugify(title)
            new_post = Post(title=title, content=content, slug=slug)
            db.session.add(new_post)
            db.session.commit()
            flash('Post created successfully!', 'success')
            return redirect(url_for('index'))
        return render_template('create.html')
    

    Edit an Existing Post

    @app.route('/admin/edit/<int:id>', methods=['GET', 'POST'])
    def edit_post(id):
        post = Post.query.get_or_404(id)
        if request.method == 'POST':
            post.title = request.form['title']
            post.content = request.form['content']
            post.slug = slugify(post.title)
            db.session.commit()
            flash('Post updated!', 'info')
            return redirect(url_for('post_detail', slug=post.slug))
        return render_template('edit.html', post=post)
    

    Delete a Post

    @app.route('/admin/delete/<int:id>', methods=['POST'])
    def delete_post(id):
        post = Post.query.get_or_404(id)
        db.session.delete(post)
        db.session.commit()
        flash('Post removed.', 'warning')
        return redirect(url_for('index'))
    

    Styling the Blog with Bootstrap

    Flask‑Bootstrap automatically injects the latest Bootstrap CSS/JS. In templates/base.html you can add custom meta tags for SEO and a simple navigation bar:

    <
    
  • Python Flask User Authentication System

    Building a secure and scalable user authentication system is one of the first milestones for any Flask web application. Whether you’re creating a simple blog, a SaaS platform, or an internal dashboard, handling login, registration, password hashing, and session management correctly will protect your users and your reputation. In this guide we’ll walk through a complete, production‑ready authentication flow using Python Flask, covering everything from project setup to best‑practice security tips—so you can launch your app with confidence.

    Why Choose Flask for Authentication?

    Flask’s lightweight core and extensive ecosystem make it an ideal framework for custom authentication solutions. Unlike heavyweight frameworks that impose a rigid user model, Flask lets you:

    • Pick the exact libraries you need (e.g., Flask‑Login, Werkzeug security, Flask‑JWT‑Extended).
    • Design flexible database schemas that match your domain logic.
    • Integrate third‑party providers such as Google, GitHub, or Facebook with minimal friction.

    Project Structure Overview

    Before diving into code, let’s outline a clean project layout that separates concerns and scales well:

    my_flask_app/
    │
    ├── app/
    │   ├── __init__.py          # Application factory
    │   ├── models.py            # SQLAlchemy User model
    │   ├── auth/
    │   │   ├── __init__.py
    │   │   ├── routes.py        # Login, logout, register views
    │   │   └── forms.py         # WTForms for validation
    │   └── templates/
    │       └── auth/
    │           ├── login.html
    │           └── register.html
    │
    ├── migrations/              # Alembic migrations
    ├── config.py                # Config classes (Dev, Prod)
    └── run.py                   # Entry point
    

    Setting Up the Environment

    1. Install Required Packages

    Run the following command inside your virtual environment:

    pip install Flask Flask‑SQLAlchemy Flask‑Login Flask‑WTF email‑validator python‑dotenv

    2. Create the Application Factory

    The factory pattern allows you to configure the app differently for development, testing, and production.

    # app/__init__.py
    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    from flask_login import LoginManager
    from dotenv import load_dotenv
    import os
    
    db = SQLAlchemy()
    login_manager = LoginManager()
    login_manager.login_view = "auth.login"
    
    def create_app():
        load_dotenv()  # Load .env variables
        app = Flask(__name__)
        app.config.from_object('config.DevelopmentConfig')
    
        db.init_app(app)
        login_manager.init_app(app)
    
        from .auth.routes import auth_bp
        app.register_blueprint(auth_bp, url_prefix="/auth")
    
        return app
    

    Designing the User Model

    Use SQLAlchemy for ORM and Werkzeug for password hashing. The model should store a unique email, a hashed password, and optional fields such as is_active or role.

    # app/models.py
    from . import db, login_manager
    from werkzeug.security import generate_password_hash, check_password_hash
    from flask_login import UserMixin
    
    class User(UserMixin, db.Model):
        __tablename__ = "users"
        id = db.Column(db.Integer, primary_key=True)
        email = db.Column(db.String(120), unique=True, nullable=False)
        password_hash = db.Column(db.String(128), nullable=False)
        is_active = db.Column(db.Boolean, default=True)
        role = db.Column(db.String(20), default="user")
    
        def set_password(self, password):
            self.password_hash = generate_password_hash(password)
    
        def check_password(self, password):
            return check_password_hash(self.password_hash, password)
    
    @login_manager.user_loader
    def load_user(user_id):
        return User.query.get(int(user_id))
    

    Creating Secure Forms with WTForms

    WTForms combined with Flask‑WTF provides CSRF protection out of the box.

    # app/auth/forms.py
    from flask_wtf import FlaskForm
    from wtforms import StringField, PasswordField, SubmitField
    from wtforms.validators import DataRequired, Email, Length, EqualTo, ValidationError
    from ..models import User
    
    class RegistrationForm(FlaskForm):
        email = StringField('Email', validators=[DataRequired(), Email()])
        password = PasswordField('Password', validators=[
            DataRequired(),
            Length(min=8, message='Password must be at least 8 characters')
        ])
        confirm = PasswordField('Confirm Password', validators=[
            DataRequired(),
            EqualTo('password', message='Passwords must match')
        ])
        submit = SubmitField('Register')
    
        def validate_email(self, field):
            if User.query.filter_by(email=field.data).first():
                raise ValidationError('Email already registered.')
    
    class LoginForm(FlaskForm):
        email = StringField('Email', validators=[DataRequired(), Email()])
        password = PasswordField('Password', validators=[DataRequired()])
        submit = SubmitField('Log In')
    

    Authentication Routes

    All authentication endpoints live in a Blueprint to keep the main app tidy.

    # app/auth/routes.py
    from flask import Blueprint, render_template, redirect, url_for, flash, request
    from flask_login import login_user, logout_user, login_required, current_user
    from .. import db
    from ..models import User
    from .forms import RegistrationForm, LoginForm
    
    auth_bp = Blueprint('auth', __name__, template_folder='templates')
    
    @auth_bp.route('/register', methods=['GET', 'POST'])
    def register():
        if current_user.is_authenticated:
            return redirect(url_for('main.index'))
        form = RegistrationForm()
        if form.validate_on_submit():
            user = User(email=form.email.data)
            user.set_password(form.password.data)
            db.session.add(user)
            db.session.commit()
            flash('Registration successful. Please log in.', 'success')
            return redirect(url_for('auth.login'))
        return render_template('auth/register.html', form=form)
    
    @auth_bp.route('/login', methods=['GET', 'POST'])
    def login():
        if current_user.is_authenticated:
            return redirect(url_for('main.index'))
        form = LoginForm()
        if form.validate_on_submit():
            user = User.query.filter_by(email=form.email.data).first()
            if user and user.check_password(form.password.data):
                login_user(user, remember='remember' in request.form)
                flash('Logged in successfully.', 'success')
                next_page = request.args.get('next')
                return redirect(next_page or url_for('main.index'))
            flash('Invalid email or password.', 'danger')
        return render_template('auth/login.html', form=form)
    
    @auth_bp.route('/logout')
    @login_required
    def logout():
        logout_user()
        flash('You have been logged out.', 'info')
        return redirect(url_for('auth.login'))
    

    Protecting Routes with @login_required

    Any view that should be accessible only to authenticated users can be wrapped with Flask‑Login’s @login_required decorator.

    # app/main/routes.py
    from flask import Blueprint, render_template
    from flask_login import login_required, current_user
    
    main_bp = Blueprint('main', __name__)
    
    @main_bp.route('/')
    def index():
        return render_template('index.html')
    
    @main_bp.route('/dashboard')
    @login_required
    def dashboard():
        return render_template('dashboard.html', user=current_user)
    

    Enhancing Security: Best Practices

    • Use HTTPS everywhere. TLS encrypts credentials in transit; configure Flask behind a reverse proxy (NGINX, Apache) with a valid SSL certificate.
    • Store passwords with a strong hash. Werkzeug uses PBKDF2 by default; for even higher security consider argon2-cffi.
    • Enable CSRF protection. Flask‑WTF automatically adds a hidden token to every form.
    • Limit login attempts. Implement a simple rate limiter (e.g., Flask‑Limiting) to thwart brute‑force attacks.
    • Set secure cookie flags. In config.py add:
      SESSION_COOKIE_HTTPONLY = True
      SESSION_COOKIE_SECURE = True
      REMEMBER_COOKIE_HTTPONLY = True
      REMEMBER_COOKIE_SECURE = True
    • Validate email addresses. Use email-validator to ensure users provide real, correctly formatted emails.
    • Consider token‑based auth for APIs. If your app exposes a JSON API, use Flask‑JWT‑Extended to issue short‑lived access tokens.

    Testing the Authentication Flow

    Write unit tests with pytest and Flask’s test client to guarantee that registration, login, and logout work as expected.

    # tests/test_auth.py
    import pytest
    from app import create_app, db
    from app.models import User

    @pytest.fixture
    def client():
    app = create_app()
    app.config.update(TESTING=True, SQLALCHEMY_DATABASE_URI='sqlite:///:memory:')
    with app.test_client() as client:
    with app.app_context():
    db.create_all()
    yield client

    def test_register_and_login(client):
    # Register
    response = client.post('/auth/register', data={
    'email': 'test@example.com',
    'password': 'StrongPass123',
    'confirm': 'StrongPass123'
    }, follow_redirects=True)
    assert b'Registration successful' in response.data

    # Login
    response = client.post('/auth/login', data={
    'email': 'test@example.com',
    'password': 'StrongPass123'
    }, follow_redirects=True)
    assert b'Logged in successfully' in response.data

    # Access protected page
    response = client.get('/dashboard')
    assert b'Dashboard' in response.data

    # Logout
    response = client.get('/auth/logout', follow_redirects=True)
    assert b