or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

admin-integration.mdcore-registration.mdfield-management.mdforms-integration.mdindex.mdquery-interface.mdutils-configuration.md

query-interface.mddocs/

0

# Query Interface

1

2

Multilingual managers and querysets that automatically handle language-specific database queries, field lookups, and provide fallback functionality for missing translations.

3

4

## Capabilities

5

6

### Multilingual Manager

7

8

Custom manager that automatically rewrites queries to use appropriate translation fields based on the current language.

9

10

```python { .api }

11

class MultilingualManager(models.Manager):

12

"""

13

Manager for multilingual models that handles language-aware queries.

14

15

Automatically:

16

- Rewrites field lookups to use current language fields

17

- Handles fallback languages for queries

18

- Manages related model query rewriting

19

"""

20

21

def get_queryset(self):

22

"""Return queryset with translation field rewriting."""

23

24

def filter(self, *args, **kwargs):

25

"""Filter with automatic translation field rewriting."""

26

27

def exclude(self, *args, **kwargs):

28

"""Exclude with automatic translation field rewriting."""

29

30

def order_by(self, *field_names):

31

"""Order by with translation field rewriting."""

32

```

33

34

**Usage Example:**

35

36

```python

37

from modeltranslation.manager import MultilingualManager

38

39

class Article(models.Model):

40

title = models.CharField(max_length=255)

41

content = models.TextField()

42

43

objects = MultilingualManager()

44

45

# Queries automatically use current language

46

articles = Article.objects.filter(title__icontains='django')

47

# Becomes: filter(title_en__icontains='django') if current language is 'en'

48

49

articles = Article.objects.order_by('title')

50

# Becomes: order_by('title_en') if current language is 'en'

51

```

52

53

### Multilingual QuerySet

54

55

QuerySet that provides language-aware query operations and fallback handling.

56

57

```python { .api }

58

class MultilingualQuerySet(models.QuerySet):

59

"""

60

QuerySet with automatic translation field handling.

61

62

Features:

63

- Language-aware field lookups

64

- Fallback language support

65

- Translation field aggregation

66

"""

67

68

def filter(self, *args, **kwargs):

69

"""Filter with translation field rewriting."""

70

71

def exclude(self, *args, **kwargs):

72

"""Exclude with translation field rewriting."""

73

74

def order_by(self, *field_names):

75

"""Order with translation field rewriting."""

76

77

def values(self, *fields):

78

"""Values with translation and fallback field inclusion."""

79

80

def values_list(self, *fields, **kwargs):

81

"""Values list with translation field handling."""

82

```

83

84

### Combined Manager/QuerySet

85

86

Manager that provides both manager and queryset functionality in one class.

87

88

```python { .api }

89

class MultilingualQuerysetManager(MultilingualManager):

90

"""

91

Combined manager/queryset providing both manager and queryset methods.

92

Enables method chaining while maintaining translation functionality.

93

"""

94

95

def get_queryset(self):

96

"""Return MultilingualQuerySet instance."""

97

98

# Inherits all QuerySet methods for chaining

99

```

100

101

**Usage Example:**

102

103

```python

104

class Article(models.Model):

105

title = models.CharField(max_length=255)

106

content = models.TextField()

107

published = models.BooleanField(default=False)

108

109

objects = MultilingualQuerysetManager.from_queryset(MultilingualQuerySet)()

110

111

# Method chaining with translation support

112

recent_articles = (Article.objects

113

.filter(published=True)

114

.filter(title__icontains='django')

115

.order_by('-created_at')[:10])

116

```

117

118

### Field Lookup Rewriting

119

120

Automatic rewriting of field lookups to use appropriate translation fields.

121

122

```python { .api }

123

def rewrite_lookup_key(model, lookup_key):

124

"""

125

Rewrite field lookup keys to use translation fields.

126

127

Parameters:

128

- model: Model class being queried

129

- lookup_key: Original lookup key (e.g., 'title__icontains')

130

131

Returns:

132

- str: Rewritten lookup key (e.g., 'title_en__icontains')

133

"""

134

135

def get_translatable_fields_for_model(model):

136

"""

137

Get list of translatable field names for a model.

138

139

Parameters:

140

- model: Model class

141

142

Returns:

143

- list: Field names that are translatable, or None if not registered

144

"""

145

```

146

147

**Lookup Rewriting Examples:**

148

149

```python

150

# Simple field lookups

151

Article.objects.filter(title='Django')

152

# → filter(title_en='Django')

153

154

# Complex lookups with field transforms

155

Article.objects.filter(title__icontains='django', content__startswith='This')

156

# → filter(title_en__icontains='django', content_en__startswith='This')

157

158

# Related field lookups

159

Article.objects.filter(category__name='Technology')

160

# → filter(category__name_en='Technology') if Category.name is translatable

161

162

# Date/numeric fields work normally

163

Article.objects.filter(created_at__gte=date.today())

164

# → No rewriting needed for non-translatable fields

165

```

166

167

### Fallback Field Handling

168

169

Automatic inclusion of fallback language fields in queries and values.

170

171

```python { .api }

172

def append_fallback(model, fields):

173

"""

174

Add fallback language fields to field list.

175

176

Parameters:

177

- model: Model class

178

- fields: Sequence of field names

179

180

Returns:

181

- tuple: (expanded_fields_set, translated_field_names_set)

182

"""

183

184

def append_translated(model, fields):

185

"""

186

Add all translation fields for given field names.

187

188

Parameters:

189

- model: Model class

190

- fields: Iterable of field names

191

192

Returns:

193

- set: All translation field names for given fields

194

"""

195

```

196

197

**Fallback Usage:**

198

199

```python

200

# When querying values, fallback fields are automatically included

201

articles = Article.objects.values('title', 'content')

202

203

# If current language is 'fr' with fallback to 'en', this becomes:

204

# values('title_fr', 'title_en', 'content_fr', 'content_en')

205

206

# The model instance will show the French value if available,

207

# otherwise the English fallback

208

```

209

210

### Language-Aware Aggregation

211

212

Aggregation functions that work with translation fields and fallbacks.

213

214

```python

215

from django.db.models import Count, Q

216

from modeltranslation.utils import get_language

217

218

# Count articles with non-empty titles in current language

219

current_lang = get_language()

220

Article.objects.aggregate(

221

count=Count('id', filter=Q(**{f'title_{current_lang}__isnull': False}))

222

)

223

224

# Aggregate across all languages

225

from modeltranslation.settings import AVAILABLE_LANGUAGES

226

227

for lang in AVAILABLE_LANGUAGES:

228

count = Article.objects.filter(**{f'title_{lang}__isnull': False}).count()

229

print(f"Articles with {lang} title: {count}")

230

```

231

232

### Custom QuerySet Methods

233

234

Extend querysets with translation-specific methods.

235

236

```python

237

class ArticleQuerySet(MultilingualQuerySet):

238

def published(self):

239

"""Filter for published articles."""

240

return self.filter(published=True)

241

242

def with_translation(self, language=None):

243

"""Filter articles that have translation in specified language."""

244

from modeltranslation.utils import get_language

245

lang = language or get_language()

246

247

# Get translatable fields for this model

248

from modeltranslation.translator import translator

249

opts = translator.get_options_for_model(self.model)

250

251

# Create filter conditions for non-empty translation fields

252

conditions = Q()

253

for field_name in opts.fields:

254

field_lookup = f"{field_name}_{lang}__isnull"

255

conditions &= ~Q(**{field_lookup: True})

256

257

return self.filter(conditions)

258

259

def missing_translation(self, language=None):

260

"""Filter articles missing translation in specified language."""

261

from modeltranslation.utils import get_language

262

lang = language or get_language()

263

264

from modeltranslation.translator import translator

265

opts = translator.get_options_for_model(self.model)

266

267

conditions = Q()

268

for field_name in opts.fields:

269

field_lookup = f"{field_name}_{lang}__isnull"

270

conditions |= Q(**{field_lookup: True})

271

272

return self.filter(conditions)

273

274

class Article(models.Model):

275

title = models.CharField(max_length=255)

276

content = models.TextField()

277

published = models.BooleanField(default=False)

278

279

objects = MultilingualQuerysetManager.from_queryset(ArticleQuerySet)()

280

281

# Usage

282

published_with_french = Article.objects.published().with_translation('fr')

283

missing_german = Article.objects.missing_translation('de')

284

```

285

286

### Related Model Queries

287

288

Handle translation fields in related model queries and joins.

289

290

```python

291

# Related model lookups are automatically rewritten

292

Article.objects.filter(category__name='Technology')

293

# If Category.name is translatable:

294

# → filter(category__name_en='Technology')

295

296

# Prefetch related with translations

297

Article.objects.prefetch_related('category').filter(title__icontains='django')

298

299

# Select related with translation fields

300

Article.objects.select_related('category').values('title', 'category__name')

301

# Automatically includes appropriate translation fields

302

```

303

304

## Advanced Usage

305

306

### Custom Field Resolution

307

308

Override field resolution for complex translation scenarios.

309

310

```python

311

class CustomMultilingualQuerySet(MultilingualQuerySet):

312

def _rewrite_filter_args(self, *args, **kwargs):

313

"""Custom logic for rewriting filter arguments."""

314

# Custom field resolution logic

315

return super()._rewrite_filter_args(*args, **kwargs)

316

```

317

318

### Performance Optimization

319

320

Optimize queries for large datasets with translations.

321

322

```python

323

# Use only() and defer() with translation fields

324

Article.objects.only('title_en', 'title_fr').filter(published=True)

325

326

# Defer translation fields not needed immediately

327

Article.objects.defer('content_de', 'content_es').filter(category__name='Tech')

328

329

# Use select_related for foreign key translations

330

Article.objects.select_related('category').filter(title__icontains='django')

331

```

332

333

### Raw SQL with Translations

334

335

Handle raw SQL queries with translation field names.

336

337

```python

338

from modeltranslation.utils import build_localized_fieldname, get_language

339

340

current_lang = get_language()

341

title_field = build_localized_fieldname('title', current_lang)

342

343

# Raw query with dynamic field names

344

Article.objects.extra(

345

where=[f"{title_field} ILIKE %s"],

346

params=['%django%']

347

)

348

```

349

350

### Bulk Operations

351

352

Bulk create, update, and delete operations with translation fields.

353

354

```python

355

# Bulk create with translation fields

356

articles = [

357

Article(title_en='English Title', title_fr='Titre Français'),

358

Article(title_en='Another Title', title_fr='Autre Titre'),

359

]

360

Article.objects.bulk_create(articles)

361

362

# Bulk update translation fields

363

Article.objects.filter(category_id=1).update(

364

title_fr='Nouveau Titre',

365

content_fr='Nouveau contenu'

366

)

367

```