|
1 from django.db import models |
|
2 from django.conf import settings |
|
3 from django.core.exceptions import ValidationError |
|
4 from django.contrib.contenttypes.models import ContentType |
|
5 from django.utils.translation import get_language |
|
6 |
|
7 class TranslationFieldDescriptor(object): |
|
8 """ |
|
9 A descriptor used for the original translated field. |
|
10 """ |
|
11 def __init__(self, name, initial_val=""): |
|
12 """ |
|
13 The ``name`` is the name of the field (which is not available in the |
|
14 descriptor by default - this is Python behaviour). |
|
15 """ |
|
16 self.name = name |
|
17 self.val = initial_val |
|
18 |
|
19 def __set__(self, instance, value): |
|
20 # print "Descriptor.__set__%s %s %s.%s: %s" % (id(instance), id(self), type(instance), self.name, value) |
|
21 lang = get_language() |
|
22 loc_field_name = build_localized_fieldname(self.name, lang) |
|
23 |
|
24 # also update the translation field of the current language |
|
25 setattr(instance, loc_field_name, value) |
|
26 |
|
27 # update the original field via the __dict__ to prevent calling the |
|
28 # descriptor |
|
29 instance.__dict__[self.name] = value |
|
30 |
|
31 |
|
32 def __get__(self, instance, owner): |
|
33 # print "Descriptor.__get__%s %s %s.%s: %s" % (id(instance), id(self), type(instance), self.name, self.val) |
|
34 if not instance: |
|
35 raise ValueError(u"Translation field '%s' can only be "\ |
|
36 "accessed via an instance not via "\ |
|
37 "a class." % self.name) |
|
38 |
|
39 lang = get_language() |
|
40 loc_field_name = build_localized_fieldname(self.name, lang) |
|
41 if hasattr(instance, loc_field_name): |
|
42 return getattr(instance, loc_field_name) or instance.__dict__[self.name] |
|
43 return instance.__dict__[self.name] |
|
44 |
|
45 |
|
46 #def create_model(name, fields=None, app_label='', module='', options=None, admin_opts=None): |
|
47 #""" |
|
48 #Create specified model. |
|
49 #This is taken from http://code.djangoproject.com/wiki/DynamicModels |
|
50 #""" |
|
51 #class Meta: |
|
52 ## Using type('Meta', ...) gives a dictproxy error during model creation |
|
53 #pass |
|
54 |
|
55 #if app_label: |
|
56 ## app_label must be set using the Meta inner class |
|
57 #setattr(Meta, 'app_label', app_label) |
|
58 |
|
59 ## Update Meta with any options that were provided |
|
60 #if options is not None: |
|
61 #for key, value in options.iteritems(): |
|
62 #setattr(Meta, key, value) |
|
63 |
|
64 ## Set up a dictionary to simulate declarations within a class |
|
65 #attrs = {'__module__': module, 'Meta': Meta} |
|
66 |
|
67 ## Add in any fields that were provided |
|
68 #if fields: |
|
69 #attrs.update(fields) |
|
70 |
|
71 ## Create the class, which automatically triggers ModelBase processing |
|
72 #model = type(name, (models.Model,), attrs) |
|
73 |
|
74 ## Create an Admin class if admin options were provided |
|
75 #if admin_opts is not None: |
|
76 #class Admin(admin.ModelAdmin): |
|
77 #pass |
|
78 #for key, value in admin_opts: |
|
79 #setattr(Admin, key, value) |
|
80 #admin.site.register(model, Admin) |
|
81 |
|
82 #return model |
|
83 |
|
84 |
|
85 def copy_field(field): |
|
86 """Instantiate a new field, with all of the values from the old one, except the |
|
87 to and to_field in the case of related fields. |
|
88 |
|
89 This taken from http://www.djangosnippets.org/snippets/442/ |
|
90 """ |
|
91 base_kw = dict([(n, getattr(field,n, '_null')) for n in models.fields.Field.__init__.im_func.func_code.co_varnames]) |
|
92 if isinstance(field, models.fields.related.RelatedField): |
|
93 rel = base_kw.get('rel') |
|
94 rel_kw = dict([(n, getattr(rel,n, '_null')) for n in rel.__init__.im_func.func_code.co_varnames]) |
|
95 if isinstance(field, models.fields.related.ForeignKey): |
|
96 base_kw['to_field'] = rel_kw.pop('field_name') |
|
97 base_kw.update(rel_kw) |
|
98 base_kw.pop('self') |
|
99 return field.__class__(**base_kw) |
|
100 |
|
101 |
|
102 def build_localized_fieldname(field_name, lang): |
|
103 return '%s_%s' % (field_name, lang) |