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

attributes-relationships.mddocs/

0

# Entity Attributes and Relationships

1

2

Attribute types for defining entity properties, primary keys, and relationships between entities. These classes define the schema structure, constraints, and relational mappings that form the foundation of the ORM.

3

4

## Capabilities

5

6

### Core Attribute Types

7

8

Basic attribute types for defining entity properties with various constraints and database column configurations.

9

10

```python { .api }

11

class Required:

12

def __init__(self, py_type, *args, **kwargs):

13

"""Define required (non-nullable) attribute.

14

15

Args:

16

py_type: Python type (str, int, float, datetime, etc.)

17

*args: Additional constraints or default value

18

**kwargs: Attribute options

19

max_len: Maximum length for strings

20

min: Minimum value for numbers

21

max: Maximum value for numbers

22

unique: Unique constraint

23

index: Create database index

24

default: Default value or callable

25

sql_type: Override SQL column type

26

column: Custom database column name

27

"""

28

29

class Optional:

30

def __init__(self, py_type, *args, **kwargs):

31

"""Define optional (nullable) attribute.

32

33

Args:

34

py_type: Python type (str, int, float, datetime, etc.)

35

*args: Additional constraints or default value

36

**kwargs: Same options as Required

37

"""

38

39

class PrimaryKey:

40

def __init__(self, py_type, *args, **kwargs):

41

"""Define primary key attribute.

42

43

Args:

44

py_type: Python type (usually int)

45

*args: Additional constraints

46

**kwargs: Attribute options

47

auto: Auto-increment for integer keys (default True)

48

size: Size for integer keys (32 or 64 bit)

49

"""

50

51

class Discriminator:

52

def __init__(self, py_type, *args, **kwargs):

53

"""Define discriminator column for entity inheritance.

54

55

Args:

56

py_type: Python type (usually str or int)

57

*args: Additional constraints

58

**kwargs: Attribute options

59

"""

60

```

61

62

### Relationship Attributes

63

64

Relationship types for defining connections between entities, supporting one-to-one, one-to-many, and many-to-many relationships.

65

66

```python { .api }

67

class Set:

68

def __init__(self, py_type, *args, **kwargs):

69

"""Define collection relationship (one-to-many or many-to-many).

70

71

Args:

72

py_type: Related entity class or string name

73

*args: Additional relationship constraints

74

**kwargs: Relationship options

75

reverse: Name of reverse relationship attribute

76

cascade_delete: Delete related objects when this is deleted

77

lazy: Lazy loading behavior

78

table: Join table name for many-to-many

79

column: Foreign key column name

80

reverse_column: Reverse foreign key column name

81

"""

82

83

def add(self, item):

84

"""Add item to collection."""

85

86

def remove(self, item):

87

"""Remove item from collection."""

88

89

def clear(self):

90

"""Remove all items from collection."""

91

92

def count(self):

93

"""Get count of items in collection."""

94

95

def is_empty(self):

96

"""Check if collection is empty."""

97

98

def select(self, lambda_expr=None):

99

"""Select items from collection matching criteria."""

100

101

def filter(self, lambda_expr):

102

"""Filter collection items."""

103

104

def order_by(self, *args):

105

"""Order collection items."""

106

107

def random(self, limit):

108

"""Get random items from collection."""

109

110

class Reference:

111

def __init__(self, py_type, *args, **kwargs):

112

"""Define reference to single related entity (one-to-one or many-to-one).

113

114

Args:

115

py_type: Related entity class or string name

116

*args: Additional constraints

117

**kwargs: Reference options

118

reverse: Name of reverse relationship attribute

119

cascade_delete: Delete behavior

120

lazy: Lazy loading behavior

121

column: Foreign key column name

122

"""

123

```

124

125

### Composite Keys and Indexes

126

127

Functions for defining composite primary keys and database indexes across multiple attributes.

128

129

```python { .api }

130

def composite_key(*attrs):

131

"""Define composite primary key from multiple attributes.

132

133

Args:

134

*attrs: Attribute instances to include in composite key

135

136

Usage:

137

class Person(db.Entity):

138

first_name = Required(str)

139

last_name = Required(str)

140

birth_date = Required(date)

141

composite_key(first_name, last_name, birth_date)

142

"""

143

144

def composite_index(*attrs, **kwargs):

145

"""Define composite database index across multiple attributes.

146

147

Args:

148

*attrs: Attribute instances to include in index

149

**kwargs: Index options

150

unique: Create unique index

151

name: Custom index name

152

153

Usage:

154

class Person(db.Entity):

155

first_name = Required(str)

156

last_name = Required(str)

157

email = Required(str)

158

composite_index(first_name, last_name)

159

composite_index(email, unique=True)

160

"""

161

```

162

163

## Usage Examples

164

165

### Basic Attributes

166

167

```python

168

from pony.orm import *

169

from datetime import datetime, date

170

171

db = Database()

172

173

class Person(db.Entity):

174

# Primary key (auto-increment by default)

175

id = PrimaryKey(int)

176

177

# Required attributes with constraints

178

name = Required(str, max_len=100)

179

email = Required(str, unique=True, max_len=255)

180

age = Required(int, min=0, max=150)

181

182

# Optional attributes

183

phone = Optional(str, max_len=20)

184

birth_date = Optional(date)

185

salary = Optional(float, min=0)

186

187

# Attribute with default value

188

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

189

is_active = Required(bool, default=True)

190

191

# Custom column name and SQL type

192

full_name = Optional(str, column='full_name_col', sql_type='VARCHAR(200)')

193

194

# Indexed attribute

195

department = Optional(str, index=True)

196

```

197

198

### Relationships

199

200

```python

201

class Company(db.Entity):

202

name = Required(str, unique=True)

203

founded = Optional(date)

204

employees = Set('Employee') # One-to-many

205

206

class Employee(db.Entity):

207

name = Required(str)

208

company = Required(Company) # Many-to-one (reverse of employees)

209

projects = Set('Project') # Many-to-many

210

manager = Optional('Employee') # Self-reference

211

subordinates = Set('Employee', reverse='manager') # Reverse self-reference

212

213

class Project(db.Entity):

214

name = Required(str)

215

employees = Set(Employee) # Many-to-many (reverse of projects)

216

deadline = Optional(date)

217

```

218

219

### Advanced Relationship Configuration

220

221

```python

222

class Author(db.Entity):

223

name = Required(str)

224

books = Set('Book', cascade_delete=True) # Delete books when author deleted

225

226

class Book(db.Entity):

227

title = Required(str)

228

isbn = Required(str, unique=True)

229

author = Required(Author)

230

tags = Set('Tag', table='book_tags',

231

column='book_id', reverse_column='tag_id') # Custom join table

232

233

class Tag(db.Entity):

234

name = Required(str, unique=True)

235

books = Set(Book)

236

237

# Entity inheritance with discriminator

238

class Vehicle(db.Entity):

239

make = Required(str)

240

model = Required(str)

241

year = Required(int)

242

vehicle_type = Discriminator(str) # Discriminator for inheritance

243

244

class Car(Vehicle):

245

doors = Required(int)

246

247

class Motorcycle(Vehicle):

248

engine_size = Required(int)

249

```

250

251

### Composite Keys and Indexes

252

253

```python

254

class OrderItem(db.Entity):

255

order_id = Required(int)

256

product_id = Required(int)

257

quantity = Required(int)

258

price = Required(float)

259

260

# Composite primary key

261

composite_key(order_id, product_id)

262

263

class Person(db.Entity):

264

first_name = Required(str)

265

last_name = Required(str)

266

email = Required(str)

267

birth_date = Optional(date)

268

269

# Composite indexes

270

composite_index(first_name, last_name) # For name searches

271

composite_index(email, unique=True) # Unique email index

272

composite_index(birth_date, last_name) # For birthday queries

273

```

274

275

### Working with Collections

276

277

```python

278

with db_session:

279

# Create entities with relationships

280

company = Company(name="Tech Corp", founded=date(2020, 1, 1))

281

282

# Add employees to company

283

alice = Employee(name="Alice", company=company)

284

bob = Employee(name="Bob", company=company)

285

286

# Working with Set collections

287

print(f"Company has {company.employees.count()} employees")

288

289

# Add to collection

290

company.employees.add(Employee(name="Charlie", company=company))

291

292

# Filter collection

293

senior_employees = company.employees.select(lambda e: e.salary > 80000)

294

295

# Order collection

296

ordered_employees = company.employees.order_by(Employee.name)

297

298

# Many-to-many relationships

299

project = Project(name="Website Redesign")

300

project.employees.add(alice)

301

project.employees.add(bob)

302

303

# Access reverse relationship

304

alice_projects = alice.projects # All projects Alice works on

305

```