add I18nField and replace the title JSONField with it
This commit is contained in:
parent
968fc3885d
commit
f94be40470
4 changed files with 174 additions and 18 deletions
|
@ -2,11 +2,14 @@ import json
|
|||
import logging
|
||||
import typing
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.validators import RegexValidator
|
||||
from django.db import models
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.functional import cached_property, lazy
|
||||
from django.utils.text import format_lazy
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import get_language
|
||||
from shapely import validation
|
||||
from shapely.geometry import LineString, MultiPolygon, Point, Polygon, mapping, shape
|
||||
from shapely.geometry.base import BaseGeometry
|
||||
|
@ -126,3 +129,67 @@ class JSONField(models.TextField):
|
|||
def value_to_string(self, obj):
|
||||
value = self.value_from_object(obj)
|
||||
return self.get_prep_value(value)
|
||||
|
||||
|
||||
def get_i18n_value(i18n_dict, fallback_language, fallback_any, fallback_value):
|
||||
lang = get_language()
|
||||
if i18n_dict:
|
||||
if lang in i18n_dict:
|
||||
return i18n_dict[lang]
|
||||
if fallback_language in i18n_dict:
|
||||
return i18n_dict[fallback_language]
|
||||
if fallback_any:
|
||||
return next(iter(i18n_dict.values()))
|
||||
return str(fallback_value)
|
||||
|
||||
|
||||
lazy_get_i18n_value = lazy(get_i18n_value, str)
|
||||
|
||||
|
||||
class I18nDescriptor:
|
||||
def __init__(self, field):
|
||||
self.field = field
|
||||
|
||||
def __get__(self, instance, cls=None):
|
||||
if instance is None:
|
||||
return self
|
||||
|
||||
fallback_value = self.field.fallback_value
|
||||
if fallback_value is not None:
|
||||
fallback_value = format_lazy(fallback_value, model_name=instance._meta.verbose_name, pk=instance.pk)
|
||||
return lazy_get_i18n_value(getattr(instance, self.field.attname),
|
||||
fallback_language=self.field.fallback_language,
|
||||
fallback_any=self.field.fallback_any,
|
||||
fallback_value=fallback_value)
|
||||
|
||||
|
||||
class I18nField(JSONField):
|
||||
def __init__(self, plural_name=None, fallback_language=settings.LANGUAGE_CODE,
|
||||
fallback_any=False, fallback_value=None, default=None):
|
||||
self.plural_name = plural_name
|
||||
self.fallback_language = fallback_language
|
||||
self.fallback_any = fallback_any
|
||||
self.fallback_value = fallback_value
|
||||
super().__init__(default=(dict(default) if default else {}), null=False)
|
||||
|
||||
def deconstruct(self):
|
||||
name, path, args, kwargs = super().deconstruct()
|
||||
kwargs = {}
|
||||
if self.default != {}:
|
||||
kwargs['default'] = self.default
|
||||
if self.plural_name is not None:
|
||||
kwargs['plural_name'] = self.plural_name
|
||||
if self.fallback_language != settings.LANGUAGE_CODE:
|
||||
kwargs['fallback_language'] = self.fallback_language
|
||||
if self.fallback_any:
|
||||
kwargs['fallback_any'] = self.fallback_any
|
||||
if self.fallback_value is not None:
|
||||
kwargs['fallback_value'] = self.fallback_value
|
||||
return name, path, args, kwargs
|
||||
|
||||
def contribute_to_class(self, cls, name, *args, **kwargs):
|
||||
super().contribute_to_class(cls, name, *args, **kwargs)
|
||||
setattr(cls, self.name, I18nDescriptor(self))
|
||||
|
||||
def get_attname(self):
|
||||
return self.name+'_i18n' if self.plural_name is None else self.plural_name
|
||||
|
|
104
src/c3nav/mapdata/migrations/0053_i18nfield.py
Normal file
104
src/c3nav/mapdata/migrations/0053_i18nfield.py
Normal file
|
@ -0,0 +1,104 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.6 on 2017-11-29 23:28
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import c3nav.mapdata.fields
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('mapdata', '0052_auto_20171125_1335'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='accessrestriction',
|
||||
name='titles',
|
||||
field=c3nav.mapdata.fields.I18nField(fallback_any=True, fallback_value='{model_name} {pk}',
|
||||
plural_name='titles'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='area',
|
||||
name='titles',
|
||||
field=c3nav.mapdata.fields.I18nField(fallback_any=True, fallback_value='{model_name} {pk}',
|
||||
plural_name='titles'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='level',
|
||||
name='titles',
|
||||
field=c3nav.mapdata.fields.I18nField(fallback_any=True, fallback_value='{model_name} {pk}',
|
||||
plural_name='titles'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='locationgroup',
|
||||
name='titles',
|
||||
field=c3nav.mapdata.fields.I18nField(fallback_any=True, fallback_value='{model_name} {pk}',
|
||||
plural_name='titles'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='locationgroupcategory',
|
||||
name='titles',
|
||||
field=c3nav.mapdata.fields.I18nField(fallback_any=True, fallback_value='{model_name} {pk}',
|
||||
plural_name='titles'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='poi',
|
||||
name='titles',
|
||||
field=c3nav.mapdata.fields.I18nField(fallback_any=True, fallback_value='{model_name} {pk}',
|
||||
plural_name='titles'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='space',
|
||||
name='titles',
|
||||
field=c3nav.mapdata.fields.I18nField(fallback_any=True, fallback_value='{model_name} {pk}',
|
||||
plural_name='titles'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='waytype',
|
||||
name='titles',
|
||||
field=c3nav.mapdata.fields.I18nField(fallback_any=True, fallback_value='{model_name} {pk}',
|
||||
plural_name='titles'),
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='accessrestriction',
|
||||
old_name='titles',
|
||||
new_name='title',
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='area',
|
||||
old_name='titles',
|
||||
new_name='title',
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='level',
|
||||
old_name='titles',
|
||||
new_name='title',
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='locationgroup',
|
||||
old_name='titles',
|
||||
new_name='title',
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='locationgroupcategory',
|
||||
old_name='titles',
|
||||
new_name='title',
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='poi',
|
||||
old_name='titles',
|
||||
new_name='title',
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='space',
|
||||
old_name='titles',
|
||||
new_name='title',
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='waytype',
|
||||
old_name='titles',
|
||||
new_name='title',
|
||||
),
|
||||
]
|
|
@ -5,7 +5,7 @@ from django.db import models
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import get_language, get_language_info
|
||||
|
||||
from c3nav.mapdata.fields import JSONField
|
||||
from c3nav.mapdata.fields import I18nField
|
||||
from c3nav.mapdata.models import MapUpdate
|
||||
|
||||
|
||||
|
@ -47,7 +47,7 @@ class SerializableMixin(models.Model):
|
|||
|
||||
|
||||
class TitledMixin(SerializableMixin, models.Model):
|
||||
titles = JSONField(default={})
|
||||
title = I18nField(plural_name='titles', fallback_any=True, fallback_value='{model_name} {pk}')
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
@ -75,15 +75,6 @@ class TitledMixin(SerializableMixin, models.Model):
|
|||
result['display'].append((language, title))
|
||||
return result
|
||||
|
||||
@property
|
||||
def title(self):
|
||||
lang = get_language()
|
||||
if self.titles:
|
||||
if lang in self.titles:
|
||||
return self.titles[lang]
|
||||
return next(iter(self.titles.values()))
|
||||
return super().title
|
||||
|
||||
|
||||
class BoundsMixin(SerializableMixin, models.Model):
|
||||
bottom = models.DecimalField(_('bottom coordinate'), max_digits=6, decimal_places=2)
|
||||
|
|
|
@ -117,12 +117,6 @@ class Location(LocationSlug, AccessRestrictionMixin, TitledMixin, models.Model):
|
|||
return code+':'+str(self.id)
|
||||
return self.slug
|
||||
|
||||
@property
|
||||
def title(self):
|
||||
if not self.titles and self.slug:
|
||||
return self._meta.verbose_name + ' ' + self.slug
|
||||
return super().title
|
||||
|
||||
@property
|
||||
def subtitle(self):
|
||||
return ''
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue