or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

aggregations-helpers.mdattributes-relationships.mddata-types.mddatabase-entities.mddebugging-utilities.mdexception-handling.mdframework-integrations.mdindex.mdquery-operations.mdsecurity-permissions.mdsession-management.md

framework-integrations.mddocs/

0

# Framework Integrations

1

2

Integrations with popular Python web frameworks for automatic session management and simplified database operations in web applications. These integrations handle session lifecycle automatically, reducing boilerplate code and preventing common session management errors.

3

4

## Capabilities

5

6

### Flask Integration

7

8

Flask extension for automatic database session management that integrates with Flask's request lifecycle.

9

10

```python { .api }

11

class Pony:

12

def __init__(self, app=None):

13

"""Initialize Pony Flask extension.

14

15

Args:

16

app: Flask application instance (optional for factory pattern)

17

"""

18

19

def init_app(self, app):

20

"""Initialize extension with Flask application.

21

22

Args:

23

app: Flask application instance

24

25

Sets up before_request and teardown_request handlers for automatic

26

db_session management throughout request lifecycle.

27

"""

28

```

29

30

## Usage Examples

31

32

### Basic Flask Integration

33

34

```python

35

from flask import Flask

36

from pony.flask import Pony

37

from pony.orm import *

38

39

# Create Flask app

40

app = Flask(__name__)

41

42

# Set up database

43

db = Database()

44

45

class User(db.Entity):

46

name = Required(str)

47

email = Required(str, unique=True)

48

49

db.bind('sqlite', filename='app.db')

50

db.generate_mapping(create_tables=True)

51

52

# Initialize Pony extension

53

pony = Pony(app)

54

55

# Now all Flask routes automatically run in db_session context

56

@app.route('/users')

57

def list_users():

58

# No need for @db_session decorator or with db_session:

59

users = select(u for u in User)[:]

60

return {'users': [{'name': u.name, 'email': u.email} for u in users]}

61

62

@app.route('/users', methods=['POST'])

63

def create_user():

64

from flask import request

65

data = request.get_json()

66

67

# Automatic session management - changes committed at request end

68

user = User(name=data['name'], email=data['email'])

69

return {'id': user.id, 'name': user.name, 'email': user.email}

70

71

if __name__ == '__main__':

72

app.run(debug=True)

73

```

74

75

### Flask Factory Pattern

76

77

```python

78

from flask import Flask

79

from pony.flask import Pony

80

from pony.orm import Database

81

82

# Global instances

83

db = Database()

84

pony = Pony()

85

86

def create_app(config=None):

87

"""Application factory pattern with Pony integration."""

88

app = Flask(__name__)

89

90

# Configure app

91

if config:

92

app.config.update(config)

93

94

# Initialize database

95

db.bind('sqlite', filename=app.config.get('DATABASE_URL', 'app.db'))

96

97

# Initialize Pony extension

98

pony.init_app(app)

99

100

# Register blueprints after Pony initialization

101

from .routes import api_bp

102

app.register_blueprint(api_bp)

103

104

return app

105

106

# In routes.py

107

from flask import Blueprint, request, jsonify

108

from .models import User, db

109

110

api_bp = Blueprint('api', __name__)

111

112

@api_bp.route('/users/<int:user_id>')

113

def get_user(user_id):

114

# Automatic db_session context

115

try:

116

user = User[user_id]

117

return jsonify({'id': user.id, 'name': user.name})

118

except ObjectNotFound:

119

return jsonify({'error': 'User not found'}), 404

120

121

@api_bp.route('/users/<int:user_id>', methods=['PUT'])

122

def update_user(user_id):

123

try:

124

user = User[user_id]

125

data = request.get_json()

126

127

if 'name' in data:

128

user.name = data['name']

129

if 'email' in data:

130

user.email = data['email']

131

132

# Changes automatically committed at request end

133

return jsonify({'id': user.id, 'name': user.name, 'email': user.email})

134

135

except ObjectNotFound:

136

return jsonify({'error': 'User not found'}), 404

137

except IntegrityError:

138

return jsonify({'error': 'Email already exists'}), 400

139

```

140

141

### Advanced Flask Integration with Error Handling

142

143

```python

144

from flask import Flask, request, jsonify, g

145

from pony.flask import Pony

146

from pony.orm import *

147

import logging

148

149

app = Flask(__name__)

150

pony = Pony(app)

151

152

# Database setup

153

db = Database()

154

155

class User(db.Entity):

156

name = Required(str)

157

email = Required(str, unique=True)

158

created_at = Required(datetime, default=datetime.now)

159

160

db.bind('sqlite', filename='app.db')

161

db.generate_mapping(create_tables=True)

162

163

# Custom error handlers that work with Pony sessions

164

@app.errorhandler(ObjectNotFound)

165

def handle_not_found(e):

166

return jsonify({'error': 'Resource not found'}), 404

167

168

@app.errorhandler(MultipleObjectsFoundError)

169

def handle_multiple_found(e):

170

return jsonify({'error': 'Multiple resources found'}), 500

171

172

@app.errorhandler(IntegrityError)

173

def handle_integrity_error(e):

174

return jsonify({'error': 'Data integrity violation'}), 400

175

176

@app.errorhandler(TransactionError)

177

def handle_transaction_error(e):

178

logging.error(f"Transaction error: {e}")

179

return jsonify({'error': 'Transaction failed'}), 500

180

181

# Routes with automatic session management

182

@app.route('/users', methods=['GET'])

183

def list_users():

184

# Query parameters for filtering

185

name_filter = request.args.get('name')

186

187

if name_filter:

188

users = select(u for u in User if name_filter in u.name)[:]

189

else:

190

users = User.select()[:]

191

192

return jsonify({

193

'users': [

194

{'id': u.id, 'name': u.name, 'email': u.email, 'created_at': u.created_at.isoformat()}

195

for u in users

196

]

197

})

198

199

@app.route('/users', methods=['POST'])

200

def create_user():

201

data = request.get_json()

202

203

if not data or 'name' not in data or 'email' not in data:

204

return jsonify({'error': 'Name and email required'}), 400

205

206

# Validation

207

if User.exists(email=data['email']):

208

return jsonify({'error': 'Email already exists'}), 400

209

210

user = User(name=data['name'], email=data['email'])

211

212

return jsonify({

213

'id': user.id,

214

'name': user.name,

215

'email': user.email,

216

'created_at': user.created_at.isoformat()

217

}), 201

218

219

@app.route('/users/<int:user_id>', methods=['DELETE'])

220

def delete_user(user_id):

221

user = User[user_id] # Raises ObjectNotFound if not found

222

user.delete()

223

return '', 204

224

225

# Request middleware for additional session configuration

226

@app.before_request

227

def before_request():

228

# Access to request-specific session configuration

229

if request.endpoint and request.endpoint.startswith('admin'):

230

# Enable SQL debugging for admin routes

231

set_sql_debug(True)

232

233

@app.teardown_request

234

def teardown_request(exception):

235

# Custom cleanup if needed

236

if exception:

237

logging.error(f"Request failed with exception: {exception}")

238

239

if __name__ == '__main__':

240

app.run(debug=True)

241

```

242

243

### Flask with Multiple Databases

244

245

```python

246

from flask import Flask

247

from pony.flask import Pony

248

from pony.orm import Database

249

250

app = Flask(__name__)

251

252

# Multiple database instances

253

user_db = Database()

254

log_db = Database()

255

256

# User models

257

class User(user_db.Entity):

258

name = Required(str)

259

email = Required(str, unique=True)

260

261

# Logging models

262

class AccessLog(log_db.Entity):

263

user_id = Optional(int)

264

endpoint = Required(str)

265

timestamp = Required(datetime, default=datetime.now)

266

267

# Bind databases

268

user_db.bind('postgresql', host='localhost', user='app', password='secret', database='users')

269

log_db.bind('sqlite', filename='logs.db')

270

271

user_db.generate_mapping(create_tables=True)

272

log_db.generate_mapping(create_tables=True)

273

274

# Initialize Pony for main database

275

pony = Pony(app)

276

277

@app.route('/users/<int:user_id>')

278

def get_user(user_id):

279

# Main database session handled automatically

280

user = User[user_id]

281

282

# Manual session for logging database

283

with log_db.db_session:

284

AccessLog(user_id=user_id, endpoint=request.endpoint)

285

286

return jsonify({'id': user.id, 'name': user.name})

287

```

288

289

### Testing with Flask Integration

290

291

```python

292

import pytest

293

from flask import Flask

294

from pony.flask import Pony

295

from pony.orm import *

296

297

def create_test_app():

298

"""Create Flask app for testing."""

299

app = Flask(__name__)

300

app.config['TESTING'] = True

301

302

# Use in-memory SQLite for tests

303

db = Database()

304

305

class User(db.Entity):

306

name = Required(str)

307

email = Required(str, unique=True)

308

309

db.bind('sqlite', ':memory:')

310

db.generate_mapping(create_tables=True)

311

312

pony = Pony(app)

313

314

@app.route('/users', methods=['POST'])

315

def create_user():

316

from flask import request

317

data = request.get_json()

318

user = User(name=data['name'], email=data['email'])

319

return {'id': user.id}

320

321

return app, db

322

323

@pytest.fixture

324

def app():

325

app, db = create_test_app()

326

yield app

327

328

@pytest.fixture

329

def client(app):

330

return app.test_client()

331

332

def test_user_creation(client):

333

"""Test user creation through Flask integration."""

334

response = client.post('/users',

335

json={'name': 'Test User', 'email': 'test@example.com'})

336

337

assert response.status_code == 200

338

data = response.get_json()

339

assert 'id' in data

340

assert data['id'] > 0

341

342

def test_automatic_rollback_on_error(client):

343

"""Test that errors trigger automatic rollback."""

344

# First request should succeed

345

response1 = client.post('/users',

346

json={'name': 'User1', 'email': 'user1@example.com'})

347

assert response1.status_code == 200

348

349

# Second request with same email should fail and rollback

350

response2 = client.post('/users',

351

json={'name': 'User2', 'email': 'user1@example.com'})

352

assert response2.status_code != 200

353

354

# Database should remain consistent

355

# (Additional verification would require access to db instance)

356

```