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