or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

django-integration.mdindex.mdspecification-matching.mdversion-operations.md

django-integration.mddocs/

0

# Django Integration

1

2

Django model fields for storing Version and specification objects in databases with automatic serialization/deserialization, validation, and migration support. Seamlessly integrate semantic versioning into Django applications.

3

4

## Capabilities

5

6

### Version Field

7

8

Store Version objects directly in Django models with automatic conversion between database strings and Version objects.

9

10

```python { .api }

11

class VersionField(models.CharField):

12

def __init__(self, partial: bool = False, coerce: bool = False, **kwargs):

13

"""

14

Django model field for storing Version objects.

15

16

Args:

17

partial: Allow partial versions (deprecated)

18

coerce: Automatically coerce invalid version strings to valid format

19

**kwargs: Standard CharField arguments (max_length defaults to 200)

20

21

Database Storage: Stored as VARCHAR string in SemVer format

22

Python Value: Returns Version object when accessed

23

"""

24

```

25

26

**Usage Examples:**

27

28

```python

29

from django.db import models

30

from semantic_version.django_fields import VersionField

31

32

class Package(models.Model):

33

name = models.CharField(max_length=100)

34

version = VersionField()

35

36

def __str__(self):

37

return f"{self.name} {self.version}"

38

39

# Usage in views/code

40

package = Package.objects.create(

41

name="my-package",

42

version=Version('1.2.3-alpha.1')

43

)

44

45

# Retrieved value is automatically a Version object

46

retrieved = Package.objects.get(id=package.id)

47

print(type(retrieved.version)) # <class 'semantic_version.base.Version'>

48

print(retrieved.version.major) # 1

49

print(retrieved.version.next_minor()) # Version('1.3.0')

50

```

51

52

### Specification Field

53

54

Store specification objects for version requirements with support for different specification syntaxes.

55

56

```python { .api }

57

class SpecField(models.CharField):

58

def __init__(self, syntax: str = 'simple', **kwargs):

59

"""

60

Django model field for storing specification objects.

61

62

Args:

63

syntax: Specification syntax ('simple' or 'npm')

64

**kwargs: Standard CharField arguments

65

66

Database Storage: Stored as VARCHAR string in specification format

67

Python Value: Returns SimpleSpec or NpmSpec object based on syntax

68

"""

69

```

70

71

**Usage Examples:**

72

73

```python

74

from semantic_version.django_fields import SpecField

75

76

class Dependency(models.Model):

77

package_name = models.CharField(max_length=100)

78

version_requirement = SpecField(syntax='simple')

79

npm_requirement = SpecField(syntax='npm')

80

81

# Usage

82

dep = Dependency.objects.create(

83

package_name="requests",

84

version_requirement=SimpleSpec('>=2.0.0,<3.0.0'),

85

npm_requirement=NpmSpec('^2.0.0')

86

)

87

88

# Retrieved values are specification objects

89

retrieved = Dependency.objects.get(id=dep.id)

90

print(type(retrieved.version_requirement)) # <class 'semantic_version.base.SimpleSpec'>

91

print(Version('2.5.0') in retrieved.version_requirement) # True

92

```

93

94

### Base Field Class

95

96

The underlying base field implementation (not typically used directly).

97

98

```python { .api }

99

class SemVerField(models.CharField):

100

"""

101

Base class for semantic version fields.

102

103

Provides common functionality for version and specification fields.

104

Not intended for direct use - use VersionField or SpecField instead.

105

106

Inherits from CharField with max_length defaulting to 200.

107

"""

108

109

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

110

def from_db_value(self, value, expression, connection, *args): ...

111

def get_prep_value(self, obj): ...

112

def get_db_prep_value(self, value, connection, prepared=False): ...

113

def value_to_string(self, obj): ...

114

def run_validators(self, value): ...

115

```

116

117

## Field Methods

118

119

### Database Conversion

120

121

Automatic conversion between database storage and Python objects.

122

123

```python { .api }

124

def to_python(self, value) -> Version | SimpleSpec | NpmSpec | None:

125

"""

126

Convert database value to appropriate Python object.

127

128

Args:

129

value: Database value (string) or existing object

130

131

Returns:

132

Version or specification object, or None if value is None

133

"""

134

135

def from_db_value(self, value, expression, connection, *args) -> Version | SimpleSpec | NpmSpec | None:

136

"""

137

Convert value from database to Python object.

138

139

Called when loading data from the database.

140

"""

141

142

def get_prep_value(self, obj) -> str | None:

143

"""

144

Convert Python object to database storage format.

145

146

Args:

147

obj: Version or specification object

148

149

Returns:

150

String representation for database storage

151

"""

152

```

153

154

### Migration Support

155

156

Support for Django migrations and schema changes.

157

158

```python { .api }

159

def deconstruct(self) -> tuple:

160

"""

161

Return field definition for Django migrations.

162

163

Returns:

164

Tuple of (name, path, args, kwargs) for migration files

165

"""

166

```

167

168

## Advanced Usage

169

170

### Version Field with Coercion

171

172

Automatically fix common version format issues:

173

174

```python

175

class FlexiblePackage(models.Model):

176

name = models.CharField(max_length=100)

177

version = VersionField(coerce=True) # Automatically coerce invalid formats

178

179

# This will work even with non-standard version strings

180

package = FlexiblePackage.objects.create(

181

name="legacy-package",

182

version="1.2" # Will be coerced to Version('1.2.0')

183

)

184

185

print(package.version) # Version('1.2.0')

186

```

187

188

### Multiple Specification Syntaxes

189

190

Support different specification formats in the same model:

191

192

```python

193

class ProjectDependency(models.Model):

194

name = models.CharField(max_length=100)

195

simple_spec = SpecField(syntax='simple')

196

npm_spec = SpecField(syntax='npm')

197

198

def check_version(self, version):

199

"""Check if version satisfies both specifications."""

200

return (version in self.simple_spec and

201

version in self.npm_spec)

202

203

dep = ProjectDependency.objects.create(

204

name="lodash",

205

simple_spec=SimpleSpec('>=4.0.0,<5.0.0'),

206

npm_spec=NpmSpec('^4.0.0')

207

)

208

209

test_version = Version('4.17.21')

210

print(dep.check_version(test_version)) # True

211

```

212

213

### Query Operations

214

215

Use version fields in database queries:

216

217

```python

218

# Filter by exact version

219

packages = Package.objects.filter(version='1.2.3')

220

221

# Use string representations in queries

222

recent_packages = Package.objects.filter(version__gte='2.0.0')

223

224

# Complex queries with version comparisons

225

major_v1 = Package.objects.filter(version__startswith='1.')

226

227

# Order by version (uses string ordering, may not be semantically correct)

228

ordered = Package.objects.order_by('version')

229

```

230

231

### Custom Field Behavior

232

233

Extend field behavior for specific use cases:

234

235

```python

236

class StrictVersionField(VersionField):

237

"""Version field that only accepts release versions (no prerelease)."""

238

239

def to_python(self, value):

240

version = super().to_python(value)

241

if version and version.prerelease:

242

raise ValidationError('Prerelease versions not allowed')

243

return version

244

245

class Package(models.Model):

246

name = models.CharField(max_length=100)

247

stable_version = StrictVersionField()

248

```

249

250

## Migration Examples

251

252

### Adding Version Fields

253

254

```python

255

# Generated migration

256

from django.db import migrations

257

from semantic_version.django_fields import VersionField, SpecField

258

259

class Migration(migrations.Migration):

260

dependencies = [

261

('myapp', '0001_initial'),

262

]

263

264

operations = [

265

migrations.AddField(

266

model_name='package',

267

name='version',

268

field=VersionField(),

269

),

270

migrations.AddField(

271

model_name='dependency',

272

name='requirement',

273

field=SpecField(syntax='simple'),

274

),

275

]

276

```

277

278

### Changing Field Options

279

280

```python

281

# Migration to add coercion to existing field

282

class Migration(migrations.Migration):

283

dependencies = [

284

('myapp', '0002_add_version_fields'),

285

]

286

287

operations = [

288

migrations.AlterField(

289

model_name='package',

290

name='version',

291

field=VersionField(coerce=True),

292

),

293

]

294

```

295

296

## Error Handling

297

298

Django integration provides comprehensive error handling:

299

300

```python

301

from django.core.exceptions import ValidationError

302

303

# Invalid version strings raise ValidationError

304

try:

305

package = Package(name="test", version="invalid.version")

306

package.full_clean() # Triggers validation

307

except ValidationError as e:

308

print(f"Validation error: {e}")

309

310

# Handle coercion failures

311

class SafePackage(models.Model):

312

name = models.CharField(max_length=100)

313

version = VersionField(coerce=True, blank=True, null=True)

314

315

def clean(self):

316

if self.version:

317

try:

318

# Ensure version can be coerced

319

Version.coerce(str(self.version))

320

except ValueError:

321

raise ValidationError({'version': 'Invalid version format'})

322

```

323

324

## Performance Considerations

325

326

- Version fields store strings in database - queries use string comparison

327

- For semantic version ordering, load objects and sort in Python

328

- Consider indexing version fields for frequently queried ranges

329

- Use `select_related()` and `prefetch_related()` as with any CharField

330

- Coercion happens on every field access - cache results if needed

331

332

## Best Practices

333

334

1. **Use coercion sparingly** - only when dealing with legacy data

335

2. **Validate at model level** - add custom clean() methods for complex validation

336

3. **Choose appropriate syntax** - use 'simple' for most cases, 'npm' for Node.js compatibility

337

4. **Index frequently queried fields** - especially version fields used in filtering

338

5. **Handle None values** - use `blank=True, null=True` for optional versions

339

6. **Document field behavior** - specify which syntax and options are used