Building scalable and maintainable models often requires a modular approach, especially when handling shared behaviors or common column types across multiple models. In this blog, we'll walk through how we can modularize models using SQLAlchemy's mixins and annotations.
Why Modularize?
When working on projects, we frequently encounter repetitive tasks such as adding created_at and updated_at timestamps to models or defining common column types like UUID primary keys. Modularizing these concerns into separate components has several benefits:
1. Reusability: Shared behaviors and column definitions can be used across multiple models.
2. Maintainability: Changes in one place propagate to all dependent models.
3. Readability: Clear separation of concerns makes the code easier to understand.
Creating a Timestamp Mixin
Mixins provide reusable logic or fields for models. Let's define a TimestampMixin that automatically adds created_at and updated_at fields to any model that inherits from it.
File: timestamp_mixin.py
from datetime import datetime from sqlalchemy import Column, DateTime from sqlalchemy.ext.declarative import declared_attr class TimestampMixin: @declared_attr def created_at(cls): return Column(DateTime, default=datetime.utcnow, nullable=False) @declared_attr def updated_at(cls): return Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
Explanation
- @declared_attr: Ensures that the attributes are dynamically added to the inheriting models.
- default and onupdate: Automatically set timestamps for creation and updates.
Defining Common Annotations
SQLAlchemy’s Annotated types, available via Python’s typing.Annotated, let you define reusable column properties. For example, you can define a UUID primary key or a String column with specific constraints.
File: common_annotations.py
from typing import Annotated from uuid import uuid4 from sqlalchemy import String from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import mapped_column uuid4pk = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid4, nullable=False) ] name = Annotated[ str, mapped_column(String(30), nullable=False) ]
Explanation
- UUID Primary Key: The uuid4pk annotation defines a universally unique identifier for primary keys.
- Name Column: The name annotation ensures a String column with a maximum length of 30 characters and no NULL values.
Building Models with Mixins and Annotations
Using the mixins and annotations, we can define models that inherit shared behavior and properties while keeping the implementation concise and readable.
File: user.py
from datetime import datetime from sqlalchemy import Column, DateTime from sqlalchemy.ext.declarative import declared_attr class TimestampMixin: @declared_attr def created_at(cls): return Column(DateTime, default=datetime.utcnow, nullable=False) @declared_attr def updated_at(cls): return Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False)
Explanation
- Declarative Base: The Base serves as the foundation for all SQLAlchemy models.
Benefits of This Approach
1. Clear Separation of Concerns
- timestamp_mixin.py: Contains reusable logic (e.g., timestamps).
- common_annotations.py: Defines common column properties (e.g., UUIDs, strings).
- user.py: Combines these building blocks into concrete models.
2. Ease of Maintenance
- If it is needed to change how timestamps work or update column constraints, it is only needed to modify the timestamp_mixin.py or common_annotations.py files. The changes automatically reflect across all dependent models.
3. Scalability
- As project grows, this structure makes it easier to add new behaviors or field types without introducing redundancy.
Final Thoughts
Modularizing models with SQLAlchemy's mixins and annotations is a good strategy for handling shared functionality and properties. This approach not only reduces duplication but also aligns with best practices for clean, maintainable code.
The above is the detailed content of Modularizing SQLAlchemy Models with Mixins and Annotations. For more information, please follow other related articles on the PHP Chinese website!

Create multi-dimensional arrays with NumPy can be achieved through the following steps: 1) Use the numpy.array() function to create an array, such as np.array([[1,2,3],[4,5,6]]) to create a 2D array; 2) Use np.zeros(), np.ones(), np.random.random() and other functions to create an array filled with specific values; 3) Understand the shape and size properties of the array to ensure that the length of the sub-array is consistent and avoid errors; 4) Use the np.reshape() function to change the shape of the array; 5) Pay attention to memory usage to ensure that the code is clear and efficient.

BroadcastinginNumPyisamethodtoperformoperationsonarraysofdifferentshapesbyautomaticallyaligningthem.Itsimplifiescode,enhancesreadability,andboostsperformance.Here'showitworks:1)Smallerarraysarepaddedwithonestomatchdimensions.2)Compatibledimensionsare

ForPythondatastorage,chooselistsforflexibilitywithmixeddatatypes,array.arrayformemory-efficienthomogeneousnumericaldata,andNumPyarraysforadvancednumericalcomputing.Listsareversatilebutlessefficientforlargenumericaldatasets;array.arrayoffersamiddlegro

Pythonlistsarebetterthanarraysformanagingdiversedatatypes.1)Listscanholdelementsofdifferenttypes,2)theyaredynamic,allowingeasyadditionsandremovals,3)theyofferintuitiveoperationslikeslicing,but4)theyarelessmemory-efficientandslowerforlargedatasets.

ToaccesselementsinaPythonarray,useindexing:my_array[2]accessesthethirdelement,returning3.Pythonuseszero-basedindexing.1)Usepositiveandnegativeindexing:my_list[0]forthefirstelement,my_list[-1]forthelast.2)Useslicingforarange:my_list[1:5]extractselemen

Article discusses impossibility of tuple comprehension in Python due to syntax ambiguity. Alternatives like using tuple() with generator expressions are suggested for creating tuples efficiently.(159 characters)

The article explains modules and packages in Python, their differences, and usage. Modules are single files, while packages are directories with an __init__.py file, organizing related modules hierarchically.

Article discusses docstrings in Python, their usage, and benefits. Main issue: importance of docstrings for code documentation and accessibility.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

WebStorm Mac version
Useful JavaScript development tools

mPDF
mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

SublimeText3 English version
Recommended: Win version, supports code prompts!

SecLists
SecLists is the ultimate security tester's companion. It is a collection of various types of lists that are frequently used during security assessments, all in one place. SecLists helps make security testing more efficient and productive by conveniently providing all the lists a security tester might need. List types include usernames, passwords, URLs, fuzzing payloads, sensitive data patterns, web shells, and more. The tester can simply pull this repository onto a new test machine and he will have access to every type of list he needs.

Notepad++7.3.1
Easy-to-use and free code editor
