{"id":7068,"library":"casbin-sqlalchemy-adapter","title":"SQLAlchemy Adapter for PyCasbin","description":"SQLAlchemy Adapter is the SQLAlchemy adapter for PyCasbin. With this library, Casbin can load policy from SQLAlchemy supported database or save policy to it. It supports various databases like PostgreSQL, MySQL, SQLite, Oracle, Microsoft SQL Server, Firebird, and Sybase. The library is currently at version 1.4.0 and releases are frequent, often including new features and compatibility updates.","status":"active","version":"1.4.0","language":"en","source_language":"en","source_url":"https://github.com/pycasbin/sqlalchemy-adapter","tags":["casbin","sqlalchemy","authorization","rbac","access-control","adapter","permission"],"install":[{"cmd":"pip install casbin-sqlalchemy-adapter","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"Core authorization library; this package is an adapter for it. PyCasbin requires Python >=3.8.","package":"pycasbin","optional":false},{"reason":"ORM used for database interaction. Ensure compatibility with your SQLAlchemy version (1.x vs 2.x).","package":"SQLAlchemy","optional":false}],"imports":[{"note":"The package name for installation is `casbin-sqlalchemy-adapter`, but the top-level import is `casbin_sqlalchemy_adapter` (note the underscore) or simply `Adapter` from it. Some older examples might show `sqlalchemy_adapter`.","wrong":"from sqlalchemy_adapter import Adapter","symbol":"Adapter","correct":"from casbin_sqlalchemy_adapter import Adapter"}],"quickstart":{"code":"import casbin\nfrom casbin_sqlalchemy_adapter import Adapter\nimport os\n\n# Define paths for your Casbin model and policy files\n# For a real application, these would be proper paths to .conf and .csv files\n# Example model.conf content:\n# [request_definition]\n# r = sub, obj, act\n# [policy_definition]\n# p = sub, obj, act\n# [policy_effect]\n# e = some(where (p.eft == allow))\n# [matchers]\n# m = r.sub == p.sub && r.obj == p.obj && r.act == p.act\n#\n# Example policy.csv content:\n# p, alice, data1, read\n# p, bob, data2, write\n\nmodel_conf_path = os.path.join(os.path.dirname(__file__), \"model.conf\")\npolicy_csv_path = os.path.join(os.path.dirname(__file__), \"policy.csv\")\n\n# Create dummy model and policy files for demonstration if they don't exist\nif not os.path.exists(model_conf_path):\n    with open(model_conf_path, 'w') as f:\n        f.write(\"\"\"\n[request_definition]\nr = sub, obj, act\n[policy_definition]\np = sub, obj, act\n[policy_effect]\ne = some(where (p.eft == allow))\n[matchers]\nm = r.sub == p.sub && r.obj == p.obj && r.act == p.act\n\"\"\")\n\nif not os.path.exists(policy_csv_path):\n    with open(policy_csv_path, 'w') as f:\n        f.write(\"\"\"\np, alice, data1, read\np, bob, data2, write\n\"\"\")\n\n# Initialize the SQLAlchemy adapter with a SQLite database\n# Replace 'sqlite:///test.db' with your database connection string (e.g., 'mysql+pymysql://user:password@host/dbname')\nadapter = Adapter('sqlite:///test.db') #\n\n# Initialize the Casbin Enforcer\n# The enforcer will load the model from model.conf and policies from the adapter\ne = casbin.Enforcer(model_conf_path, adapter) #\n\n# Add a policy via the Enforcer (this will be saved to the database)\n# Note: policies added directly via the Enforcer API are automatically saved if Auto-Save is enabled (default).\nif e.add_policy(\"charlie\", \"data3\", \"edit\"):\n    print(\"Policy 'charlie, data3, edit' added.\")\n\n# Enforce a policy\nsub = \"alice\"\nobj = \"data1\"\nact = \"read\"\n\nif e.enforce(sub, obj, act):\n    print(f\"{sub} is permitted to {act} {obj}.\")\nelse:\n    print(f\"{sub} is denied to {act} {obj}.\")\n\nsub = \"bob\"\nobj = \"data1\"\nact = \"read\"\n\nif e.enforce(sub, obj, act):\n    print(f\"{sub} is permitted to {act} {obj}.\")\nelse:\n    print(f\"{sub} is denied to {act} {obj}.\")\n\nsub = \"charlie\"\nobj = \"data3\"\nact = \"edit\"\n\nif e.enforce(sub, obj, act):\n    print(f\"{sub} is permitted to {act} {obj}.\")\nelse:\n    print(f\"{sub} is denied to {act} {obj}.\")\n\n# Remove a policy\nif e.remove_policy(\"charlie\", \"data3\", \"edit\"):\n    print(\"Policy 'charlie, data3, edit' removed.\")\n\n# Check again after removal\nif not e.enforce(\"charlie\", \"data3\", \"edit\"):\n    print(\"Charlie is now denied to edit data3 as expected.\")\n","lang":"python","description":"This quickstart demonstrates how to initialize the SQLAlchemy adapter with a database (SQLite in this example), create a Casbin Enforcer, and then add, enforce, and remove policies. The policies are persisted in the configured database. Ensure you have Casbin model (`.conf`) and policy (`.csv`) files defined for the Enforcer to load initially, or manage all policies programmatically after initializing with an empty model."},"warnings":[{"fix":"Review the official GitHub releases and PyCasbin documentation for any changes related to model definitions or adapter instantiation. Ensure your Python version meets the `pycasbin` requirement of `>=3.8`.","message":"Version 1.0.0 introduced breaking changes, largely due to internal upgrades and potentially higher Python/dependency version requirements. While specific API changes weren't detailed in the changelog, a major version bump indicates non-backward compatible changes.","severity":"breaking","affected_versions":">=1.0.0"},{"fix":"Upgrade to the latest `casbin-sqlalchemy-adapter` version (>=1.1.0) for SQLAlchemy 2.0 compatibility fixes. If maintaining an older SQLAlchemy version, ensure your adapter version is compatible or pin SQLAlchemy to 1.x if necessary and check specific adapter version requirements.","message":"The library has undergone updates to ensure compatibility with SQLAlchemy 2.0. Older applications using SQLAlchemy 1.x might face issues, especially with declarative base imports (e.g., `declarative_base` vs `DeclarativeBase`).","severity":"gotcha","affected_versions":"<1.1.0"},{"fix":"To prevent automatic table creation, pass `create_table=False` when initializing the adapter: `adapter = Adapter('sqlite:///test.db', create_table=False)`.","message":"By default, the adapter automatically creates the necessary `casbin_rule` database table during initialization. This might conflict with applications managing schema migrations (e.g., via Alembic).","severity":"gotcha","affected_versions":"All versions"},{"fix":"When using soft deletion, define a custom `CasbinRule` model with a boolean soft delete attribute (e.g., `is_deleted`) and initialize the adapter with `db_class=MyCustomCasbinRuleModel` and `db_class_softdelete_attribute=MyCustomCasbinRuleModel.is_deleted`.","message":"Soft deletion for Casbin rules is supported, but requires providing a custom Casbin rule model and explicitly passing the `db_class_softdelete_attribute` during adapter initialization.","severity":"gotcha","affected_versions":">=1.4.0"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Ensure the package is installed using `pip install casbin-sqlalchemy-adapter`. Verify the import statement is `from casbin_sqlalchemy_adapter import Adapter`.","cause":"The package was either not installed, or there's a typo in the import statement.","error":"ModuleNotFoundError: No module named 'casbin_sqlalchemy_adapter'"},{"fix":"Upgrade `casbin-sqlalchemy-adapter` to its latest version (`>=1.1.0`) which includes fixes for SQLAlchemy 2.0's `DeclarativeBase`. If still encountering issues, ensure your application's SQLAlchemy usage aligns with 2.0 conventions.","cause":"Incompatibility between the adapter version and your SQLAlchemy version, specifically related to the `declarative_base` import style which changed in SQLAlchemy 2.0.","error":"TypeError: 'declarative_base' object is not callable or similar SQLAlchemy 2.0 migration errors."},{"fix":"Ensure `create_table` is `True` (default) or that your migration system creates the `casbin_rule` table. For programmatic policy changes, confirm that auto-save is enabled (default behavior) or explicitly call `e.save_policy()` after modifications if you are managing policies manually or with an older adapter/enforcer.","cause":"The `casbin_rule` table was not created, or policies are not being saved. This can happen if `create_table=False` was set, or if an older adapter version without auto-save is used and `e.save_policy()` is not called.","error":"Table 'casbin_rule' not found or Policy changes not persisting to database."},{"fix":"Upgrade to `casbin-sqlalchemy-adapter` version 1.2.0 or newer, which includes a fix for nested session deadlocks.","cause":"Older versions of the adapter had issues with nested database sessions leading to deadlocks.","error":"Database deadlock or concurrency issues when using sessions."}]}