-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmodels.py
More file actions
executable file
·155 lines (118 loc) · 5.6 KB
/
models.py
File metadata and controls
executable file
·155 lines (118 loc) · 5.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# -*- coding: utf-8 -*-
import copy
from django.db import models
from django_utils.middleware import get_request
from django.utils.translation import get_language, ugettext_lazy as _
from django.utils.functional import curry
from django.db.models.base import ModelBase
from django.conf import settings
def create_pb_manager(superclass):
class PublishManager(models.Manager):
"""
Includes only objects marked as publish on current
"""
def get_query_set(self):
name = get_language() + '_publish'
return super(PublishManager, self).get_query_set().filter(**{str(name): True})
return PublishManager()
def create_ml_manager(superclass):
class MultilingualManager(superclass):
"""
Translates multilingual filter kwargs
"""
def _translate(self, **kwargs):
if hasattr(self.model, 'trans_fields'):
for key in kwargs.keys():
if key in self.model.trans_fields:
kwargs[str(get_language() + '_' + key)] = kwargs.pop(key)
return kwargs
def filter(self, *args, **kwargs):
return super(MultilingualManager, self).filter(*args, **self._translate(**kwargs))
def exclude(self, *args, **kwargs):
return super(MultilingualManager, self).exclude(*args, **self._translate(**kwargs))
def create(self, **kwargs):
from django.conf import settings
langs = [x[0] for x in settings.LANGUAGES]
lang = get_language()
langs = dict((l, 1) for l in langs)
if hasattr(self.model, 'trans_fields'):
for key in kwargs.keys():
if key in self.model.trans_fields:
val = kwargs.pop(key)
for l in langs:
if not langs.has_key(l + '_' + key):
kwargs[l + '_' + key] = val
return super(MultilingualManager, self).create(**kwargs)
return MultilingualManager()
class MultilingualMetaclass(models.base.ModelBase):
"""
Metaclass for multilingual models.
Creates dublicated fields in database. See also MultilingualBase.
For fields named publish initializes Publish manager
Usage:
class MultilingualModel(SomeModel):
__metaclass__ = MultilingualBase
trans_fields = ('title',)
multilingual_languages = ('ru', 'en')
title = models.CharField(...)
"""
def __new__(cls, name, bases, attrs):
languages = attrs.get('multilingual_languages', ('ru', 'en'))
attrs['multilingual_languages'] = languages
trans_fields = attrs.get('trans_fields', None)
if trans_fields is not None:
# криво! Нужно переписать
manager = attrs.get('objects', models.Manager()).__class__
attrs['objects'] = create_ml_manager(manager)
if 'publish' in trans_fields:
attrs['published'] = create_pb_manager(manager)
cls = super(MultilingualMetaclass, cls).__new__(cls, name, bases, attrs)
def _add_field(lang, nm, field):
field_lang = copy.copy(field)
field_lang.attname = lang + '_' + field_lang.attname
field_lang.name = lang + '_' + field_lang.name
field_lang.column = lang + '_' + field_lang.column
field_lang.verbose_name = unicode(field_lang.verbose_name) + ' ('+lang+')'
cls.add_to_class(lang + '_' + nm, field_lang)
if languages is not None and trans_fields is not None:
require_published = False
for nm in trans_fields:
for i, field in enumerate(cls._meta.local_fields):
if field.name == nm: break
if field.name != nm: break
del cls._meta.local_fields[i]
for lang in languages:
_add_field(lang, nm, field)
_get_value = lambda s, n: getattr(s, get_language() + '_' + n)
_set_value = lambda s, v, n: setattr(s, get_language() + '_' + n, v)
for field in trans_fields:
cls.add_to_class(field, property(curry(_get_value, n=field),
curry(_set_value, n=field) )
)
return cls
REPLICATE = getattr(settings, 'REPLICATE_MULTILINGUAL', False)
class MultilingualBase(models.Model):
"""
Base class for multilingual models.
class MultilingualModel(MultilingualBase):
trans_fields = ('title',)
multilingual_languages = ('ru', 'en')
title = models.CharField(...)
"""
__metaclass__ = MultilingualMetaclass
def save(self, *args, **kwargs):
if REPLICATE:
for field in self.trans_fields:
zero, not_zero = [], None
for lang in self.multilingual_languages:
value = getattr(self, "%s_%s" % (lang, field))
if not value:
zero.append(lang)
elif not_zero is None:
not_zero = value
if not_zero is not None and zero:
for lang in zero:
setattr(self, u"%s_%s" % (lang, field), not_zero)
return super(MultilingualBase, self).save(*args, **kwargs)
class Meta:
abstract = True