========== Quickstart ========== This tutorial will guide you through creating your first Tet application from scratch. Installation ============ First, install Tet using pip:: pip install tet You'll also want to install Pyramid and other common dependencies:: pip install pyramid pyramid_di sqlalchemy Creating Your First Application =============================== Let's create a simple web application using Tet's enhanced features. Basic Application Structure --------------------------- You *can* keep an entire Tet application in a single module -- it is the quickest way to get a feel for the framework, and this tutorial does exactly that to keep each step short. A single file is perfectly fine for spikes, examples, and very small services. For anything you intend to maintain, though, organise the application as a Python **package** instead of a single file or one growing module. A package gives you a place for each concern (models, views, services, templates, migrations, tests) and makes ``config.scan()`` and asset specifications such as ``"myapp:templates/home.tk"`` resolve cleanly. A typical layout looks like: .. code-block:: text myapp/ myapp/ __init__.py # main() application factory models.py # or a models/ package views.py # or a views/ package services.py templates/ home.tk static/ development.ini pyproject.toml tests/ The examples below use a flat ``app.py``/``models.py`` for brevity; when you move to a package, the same code lives in ``myapp/__init__.py``, ``myapp/models.py`` and so on, and you start the app through the ``.ini`` file with ``pserve`` rather than a ``__main__`` block. Create a new directory for your project and add the following files: **app.py** .. code-block:: python from tet.config import application_factory, ALL_FEATURES from pyramid.response import Response def hello_world(request): return Response("Hello, Tet!") def json_api(request): return { "message": "Hello from Tet API!", "features": ["CSRF Protection", "Safe JSON", "Enhanced Auth"], } @application_factory(included_features=ALL_FEATURES) def main(config): """Tet application factory.""" # Add routes config.add_route("home", "/") config.add_route("api", "/api") # Add views config.add_view(hello_world, route_name="home") config.add_view(json_api, route_name="api", renderer="json") if __name__ == "__main__": from wsgiref.simple_server import make_server app = main({}) # Empty global_config server = make_server("0.0.0.0", 6543, app) print("Server running on http://localhost:6543") server.serve_forever() Run your application:: python app.py Visit http://localhost:6543 to see your application running! Adding Database Support ======================= Let's enhance our application with database support using SQLAlchemy. **models.py** .. code-block:: python from sqlalchemy import Column, Integer, String, DateTime, create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker from datetime import datetime, timezone Base = declarative_base() class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True) name = Column(String(50), nullable=False) email = Column(String(100), unique=True, nullable=False) created = Column(DateTime, default=lambda: datetime.now(timezone.utc)) def __json__(self, request): """JSON serialization for Tet's JSON renderer.""" return { "id": self.id, "name": self.name, "email": self.email, "created": self.created, # Automatically converted by Tet } # Database setup engine = create_engine("sqlite:///tutorial.db", echo=True) Base.metadata.create_all(engine) Session = sessionmaker(bind=engine) **Enhanced app.py** .. code-block:: python from tet.config import application_factory, ALL_FEATURES from pyramid.response import Response from pyramid_di import autowired from sqlalchemy.orm import Session from models import User def hello_world(request): return Response("Hello, Tet!") class UserViews: """User management views.""" # Database session automatically injected via pyramid_di dbsession: Session = autowired() def create_user(self, request): # Use the autowired database session # Transaction managed automatically by pyramid_tm # Create a new user user = User(name="John Doe", email="john@example.com") self.dbsession.add(user) # No need to commit - pyramid_tm handles transactions automatically return {"message": "User created", "user": user} def list_users(self, request): # Use the autowired database session users = self.dbsession.query(User).all() return {"users": users} @application_factory(included_features=ALL_FEATURES) def main(config): """Tet application factory with database support.""" # Setup SQLAlchemy with automatic session management config.include("tet.sqlalchemy.simple") config.setup_sqlalchemy() # Routes config.add_route("home", "/") config.add_route("create_user", "/users/create") config.add_route("list_users", "/users") # Views config.add_view(hello_world, route_name="home") # Register class-based views user_views = UserViews() config.add_view( user_views.create_user, route_name="create_user", request_method="POST", renderer="json", ) config.add_view(user_views.list_users, route_name="list_users", renderer="json") if __name__ == "__main__": from wsgiref.simple_server import make_server app = main({}) server = make_server("0.0.0.0", 6543, app) print("Server running on http://localhost:6543") server.serve_forever() Adding Security Features ======================== Let's add some security features to our application. **Enhanced Views with CSRF Protection** .. code-block:: python from pyramid.httpexceptions import HTTPForbidden from pyramid.csrf import check_csrf_token def secure_create_user(request): # CSRF protection is automatically enabled # This view will require CSRF token for POST requests try: # Validate CSRF token (optional explicit check) check_csrf_token(request) except HTTPForbidden: return {"error": "CSRF token missing or invalid"} session = request.find_service(name="dbsession") # Get data from request name = request.json_body.get("name") email = request.json_body.get("email") if not name or not email: return {"error": "Name and email are required"} # Create user user = User(name=name, email=email) session.add(user) session.commit() return {"message": "User created successfully", "user": user} **Safe JSON for Frontend** Create a template that safely embeds JSON: **templates/users.tk** (Tonnikala template) .. code-block:: html