mirror of
https://github.com/Hopiu/django-modeltranslation.git
synced 2026-05-09 13:54:44 +00:00
cleanup: remove code for old djago
This commit is contained in:
parent
63543f2356
commit
84115df1dc
1 changed files with 51 additions and 118 deletions
|
|
@ -1,7 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from functools import partial
|
||||
|
||||
from django import VERSION
|
||||
import django
|
||||
from django.utils.six import with_metaclass
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.db.models import Manager, ForeignKey, OneToOneField
|
||||
|
|
@ -17,10 +17,6 @@ from modeltranslation.manager import (MultilingualManager, MultilingualQuerysetM
|
|||
from modeltranslation.utils import build_localized_fieldname, parse_field
|
||||
|
||||
|
||||
NEW_RELATED_API = VERSION >= (1, 9)
|
||||
NEW_DEFERRED_API = NEW_MANAGER_API = NEW_ABSTRACT_API = VERSION >= (1, 10)
|
||||
|
||||
|
||||
class AlreadyRegistered(Exception):
|
||||
pass
|
||||
|
||||
|
|
@ -163,12 +159,8 @@ def add_translation_fields(model, opts):
|
|||
# Rebuild information about parents fields. If there are opts.local_fields, field cache would be
|
||||
# invalidated (by model._meta.add_field() function). Otherwise, we need to do it manually.
|
||||
if len(opts.local_fields) == 0:
|
||||
try:
|
||||
model._meta._fill_fields_cache()
|
||||
except AttributeError:
|
||||
# Django 1.8 removed _fill_fields_cache
|
||||
model._meta._expire_cache()
|
||||
model._meta.get_fields()
|
||||
model._meta._expire_cache()
|
||||
model._meta.get_fields()
|
||||
|
||||
|
||||
def has_custom_queryset(manager):
|
||||
|
|
@ -178,6 +170,29 @@ def has_custom_queryset(manager):
|
|||
return old_diff or new_diff
|
||||
|
||||
|
||||
def patch_manager_class(manager):
|
||||
if isinstance(manager, MultilingualManager):
|
||||
return
|
||||
if manager.__class__ is Manager:
|
||||
manager.__class__ = MultilingualManager
|
||||
else:
|
||||
class NewMultilingualManager(MultilingualManager, manager.__class__,
|
||||
MultilingualQuerysetManager):
|
||||
_old_module = manager.__module__
|
||||
_old_class = manager.__class__.__name__
|
||||
|
||||
def deconstruct(self):
|
||||
return (
|
||||
False, # as_manager
|
||||
'%s.%s' % (self._old_module, self._old_class), # manager_class
|
||||
None, # qs_class
|
||||
self._constructor_args[0], # args
|
||||
self._constructor_args[1], # kwargs
|
||||
)
|
||||
|
||||
manager.__class__ = NewMultilingualManager
|
||||
|
||||
|
||||
def add_manager(model):
|
||||
"""
|
||||
Monkey patches the original model to use MultilingualManager instead of
|
||||
|
|
@ -188,51 +203,18 @@ def add_manager(model):
|
|||
if model._meta.abstract:
|
||||
return
|
||||
|
||||
def patch_manager_class(manager):
|
||||
if isinstance(manager, MultilingualManager):
|
||||
return
|
||||
if manager.__class__ is Manager:
|
||||
manager.__class__ = MultilingualManager
|
||||
else:
|
||||
class NewMultilingualManager(MultilingualManager, manager.__class__,
|
||||
MultilingualQuerysetManager):
|
||||
if VERSION < (1, 10):
|
||||
use_for_related_fields = getattr(
|
||||
manager.__class__,
|
||||
"use_for_related_fields",
|
||||
not has_custom_queryset(manager),
|
||||
)
|
||||
_old_module = manager.__module__
|
||||
_old_class = manager.__class__.__name__
|
||||
|
||||
def deconstruct(self):
|
||||
return (
|
||||
False, # as_manager
|
||||
'%s.%s' % (self._old_module, self._old_class), # manager_class
|
||||
None, # qs_class
|
||||
self._constructor_args[0], # args
|
||||
self._constructor_args[1], # kwargs
|
||||
)
|
||||
|
||||
manager.__class__ = NewMultilingualManager
|
||||
|
||||
if NEW_MANAGER_API:
|
||||
# Inspired by django.db.models.options.Options.managers (find all
|
||||
# managers by following the normal Python MRO rules), but keeps the
|
||||
# original managers instead of making copies.
|
||||
managers = []
|
||||
seen = set()
|
||||
bases = (b for b in model.mro() if hasattr(b, '_meta'))
|
||||
for base in bases:
|
||||
for manager in base._meta.local_managers:
|
||||
if manager.name in seen:
|
||||
continue
|
||||
managers.append(manager)
|
||||
seen.add(manager.name)
|
||||
|
||||
else:
|
||||
managers = ((getattr(model, x[1]) for x in
|
||||
model._meta.concrete_managers + model._meta.abstract_managers))
|
||||
# Inspired by django.db.models.options.Options.managers (find all
|
||||
# managers by following the normal Python MRO rules), but keeps the
|
||||
# original managers instead of making copies.
|
||||
managers = []
|
||||
seen = set()
|
||||
bases = [b for b in model.mro() if hasattr(b, '_meta')]
|
||||
for base in bases:
|
||||
for manager in base._meta.local_managers:
|
||||
if manager.name in seen:
|
||||
continue
|
||||
managers.append(manager)
|
||||
seen.add(manager.name)
|
||||
|
||||
for current_manager in managers:
|
||||
prev_class = current_manager.__class__
|
||||
|
|
@ -245,10 +227,8 @@ def add_manager(model):
|
|||
# share the same class.
|
||||
model._default_manager.__class__ = current_manager.__class__
|
||||
patch_manager_class(model._base_manager)
|
||||
if VERSION >= (1, 10):
|
||||
model._meta.base_manager_name = 'objects'
|
||||
if hasattr(model._meta, "_expire_cache"):
|
||||
model._meta._expire_cache()
|
||||
model._meta.base_manager_name = 'objects'
|
||||
model._meta._expire_cache()
|
||||
|
||||
|
||||
def patch_constructor(model):
|
||||
|
|
@ -259,12 +239,11 @@ def patch_constructor(model):
|
|||
|
||||
def new_init(self, *args, **kwargs):
|
||||
self._mt_init = True
|
||||
if NEW_DEFERRED_API or not self._deferred:
|
||||
populate_translation_fields(self.__class__, kwargs)
|
||||
for key, val in list(kwargs.items()):
|
||||
new_key = rewrite_lookup_key(model, key)
|
||||
# Old key is intentionally left in case old_init wants to play with it
|
||||
kwargs.setdefault(new_key, val)
|
||||
populate_translation_fields(self.__class__, kwargs)
|
||||
for key, val in list(kwargs.items()):
|
||||
new_key = rewrite_lookup_key(model, key)
|
||||
# Old key is intentionally left in case old_init wants to play with it
|
||||
kwargs.setdefault(new_key, val)
|
||||
old_init(self, *args, **kwargs)
|
||||
model.__init__ = new_init
|
||||
|
||||
|
|
@ -328,37 +307,6 @@ def patch_refresh_from_db(model):
|
|||
model.refresh_from_db = new_refresh_from_db
|
||||
|
||||
|
||||
def patch_metaclass(model):
|
||||
"""
|
||||
Monkey patches original model metaclass to exclude translated fields on deferred subclasses.
|
||||
"""
|
||||
old_mcs = model.__class__
|
||||
|
||||
class translation_deferred_mcs(old_mcs):
|
||||
"""
|
||||
This metaclass is essential for deferred subclasses (obtained via only/defer) to work.
|
||||
|
||||
When deferred subclass is created, some translated fields descriptors could be overridden
|
||||
by DeferredAttribute - which would cause translation retrieval to fail.
|
||||
Prevent this from happening with deleting those attributes from class being created.
|
||||
This metaclass would be called from django.db.models.query_utils.deferred_class_factory
|
||||
"""
|
||||
def __new__(cls, name, bases, attrs):
|
||||
if attrs.get('_deferred', False):
|
||||
opts = translator.get_options_for_model(model)
|
||||
were_deferred = set()
|
||||
for field_name in opts.fields.keys():
|
||||
if attrs.pop(field_name, None):
|
||||
# Field was deferred. Store this for future reference.
|
||||
were_deferred.add(field_name)
|
||||
if len(were_deferred):
|
||||
attrs['_fields_were_deferred'] = were_deferred
|
||||
return super(translation_deferred_mcs, cls).__new__(cls, name, bases, attrs)
|
||||
# Assign to __metaclass__ wouldn't work, since metaclass search algorithm check for __class__.
|
||||
# http://docs.python.org/2/reference/datamodel.html#__metaclass__
|
||||
model.__class__ = translation_deferred_mcs
|
||||
|
||||
|
||||
def delete_cache_fields(model):
|
||||
opts = model._meta
|
||||
cached_attrs = ('_field_cache', '_field_name_cache', '_name_map', 'fields', 'concrete_fields',
|
||||
|
|
@ -431,7 +379,7 @@ def patch_related_object_descriptor_caching(ro_descriptor):
|
|||
class NewSingleObjectDescriptor(LanguageCacheSingleObjectDescriptor, ro_descriptor.__class__):
|
||||
pass
|
||||
|
||||
if VERSION[0] == 2:
|
||||
if django.VERSION[0] == 2:
|
||||
ro_descriptor.related.get_cache_name = partial(
|
||||
NewSingleObjectDescriptor.get_cache_name,
|
||||
ro_descriptor,
|
||||
|
|
@ -505,11 +453,11 @@ class Translator(object):
|
|||
add_translation_fields(model, opts)
|
||||
|
||||
# Delete all fields cache for related model (parent and children)
|
||||
related = ((
|
||||
related = (
|
||||
f for f in model._meta.get_fields()
|
||||
if (f.one_to_many or f.one_to_one) and
|
||||
f.auto_created
|
||||
) if NEW_RELATED_API else model._meta.get_all_related_objects())
|
||||
)
|
||||
|
||||
for related_obj in related:
|
||||
delete_cache_fields(related_obj.model)
|
||||
|
|
@ -521,19 +469,12 @@ class Translator(object):
|
|||
patch_constructor(model)
|
||||
|
||||
# Connect signal for model
|
||||
if NEW_DEFERRED_API:
|
||||
post_init.connect(delete_mt_init, sender=model)
|
||||
else:
|
||||
# deferred models have their own classes and the `sender` does not match.
|
||||
# Connect signal for all models.
|
||||
post_init.connect(delete_mt_init, dispatch_uid="modeltranslation")
|
||||
post_init.connect(delete_mt_init, sender=model)
|
||||
|
||||
# Patch clean_fields to verify form field clearing
|
||||
patch_clean_fields(model)
|
||||
|
||||
# Patch __metaclass__ and other methods to allow deferring to work
|
||||
if not NEW_DEFERRED_API:
|
||||
patch_metaclass(model)
|
||||
patch_get_deferred_fields(model)
|
||||
patch_refresh_from_db(model)
|
||||
|
||||
|
|
@ -559,24 +500,18 @@ class Translator(object):
|
|||
setattr(model, field.get_attname(), desc)
|
||||
|
||||
# Set related field names on other model
|
||||
if NEW_RELATED_API and not field.remote_field.is_hidden():
|
||||
if not field.remote_field.is_hidden():
|
||||
other_opts = self._get_options_for_model(field.remote_field.model)
|
||||
other_opts.related = True
|
||||
other_opts.related_fields.append(field.related_query_name())
|
||||
# Add manager in case of non-registered model
|
||||
add_manager(field.remote_field.model)
|
||||
elif not NEW_RELATED_API and not field.rel.is_hidden():
|
||||
other_opts = self._get_options_for_model(field.rel.to)
|
||||
other_opts.related = True
|
||||
other_opts.related_fields.append(field.related_query_name())
|
||||
add_manager(field.rel.to) # Add manager in case of non-registered model
|
||||
|
||||
if isinstance(field, OneToOneField):
|
||||
# Fix translated_field caching for SingleRelatedObjectDescriptor
|
||||
sro_descriptor = (
|
||||
getattr(field.remote_field.model, field.remote_field.get_accessor_name())
|
||||
if NEW_RELATED_API
|
||||
else getattr(field.rel.to, field.related.get_accessor_name()))
|
||||
)
|
||||
patch_related_object_descriptor_caching(sro_descriptor)
|
||||
|
||||
def unregister(self, model_or_iterable):
|
||||
|
|
@ -619,8 +554,6 @@ class Translator(object):
|
|||
Returns an instance of translation options with translated fields
|
||||
defined for the ``model`` and inherited from superclasses.
|
||||
"""
|
||||
if not NEW_DEFERRED_API and model._deferred:
|
||||
model = model._meta.proxy_for_model
|
||||
if model not in self._registry:
|
||||
# Create a new type for backwards compatibility.
|
||||
opts = type("%sTranslationOptions" % model.__name__,
|
||||
|
|
|
|||
Loading…
Reference in a new issue