145 lines
5.9 KiB
Python
145 lines
5.9 KiB
Python
|
"""
|
||
|
These functions handle the adding of fields to other models
|
||
|
"""
|
||
|
from django.db.models import FieldDoesNotExist, ForeignKey, ManyToManyField
|
||
|
from . import fields
|
||
|
# from settings import self._field_registry, self._model_registry
|
||
|
from django.utils.translation import ugettext_lazy as _
|
||
|
from django.core.exceptions import ImproperlyConfigured
|
||
|
|
||
|
|
||
|
FIELD_TYPES = {
|
||
|
'ForeignKey': ForeignKey,
|
||
|
'ManyToManyField': ManyToManyField,
|
||
|
}
|
||
|
|
||
|
|
||
|
class Registry(object):
|
||
|
def __init__(self):
|
||
|
self._field_registry = {}
|
||
|
self._model_registry = {}
|
||
|
|
||
|
def register_model(self, app, model_name, field_type, field_definitions):
|
||
|
"""
|
||
|
Process for Django 1.7 +
|
||
|
app: app name/label
|
||
|
model_name: name of the model
|
||
|
field_definitions: a string, tuple or list of field configurations
|
||
|
field_type: either 'ForeignKey' or 'ManyToManyField'
|
||
|
"""
|
||
|
from django.apps import apps
|
||
|
import collections
|
||
|
|
||
|
app_label = app
|
||
|
|
||
|
if isinstance(field_definitions, str):
|
||
|
field_definitions = [field_definitions]
|
||
|
elif not isinstance(field_definitions, collections.Iterable):
|
||
|
raise ImproperlyConfigured(_('Field configuration for %(app)s should be a string or iterable') % {'app': app})
|
||
|
|
||
|
if field_type not in ('ForeignKey', 'ManyToManyField'):
|
||
|
raise ImproperlyConfigured(_('`field_type` must be either `"ForeignKey"` or `"ManyToManyField"`.'))
|
||
|
|
||
|
try:
|
||
|
if not hasattr(model_name, "_meta"):
|
||
|
app_config = apps.get_app_config(app)
|
||
|
app_label = app_config.label
|
||
|
model = app_config.get_model(model_name)
|
||
|
else:
|
||
|
model = model_name
|
||
|
model_name = model._meta.model_name
|
||
|
opts = model._meta
|
||
|
if app_label not in self._model_registry:
|
||
|
self._model_registry[app_label] = []
|
||
|
if model not in self._model_registry[app_label]:
|
||
|
self._model_registry[app_label].append(model)
|
||
|
except LookupError:
|
||
|
raise ImproperlyConfigured('Model "%(model)s" doesn\'t exist in app "%(app)s".' % {'model': model_name, 'app': app})
|
||
|
|
||
|
if not isinstance(field_definitions, (tuple, list)):
|
||
|
field_definitions = [field_definitions]
|
||
|
|
||
|
for fld in field_definitions:
|
||
|
extra_params = {'to': 'categories.Category', 'blank': True}
|
||
|
if field_type != 'ManyToManyField':
|
||
|
extra_params['null'] = True
|
||
|
if isinstance(fld, str):
|
||
|
field_name = fld
|
||
|
elif isinstance(fld, dict):
|
||
|
if 'name' in fld:
|
||
|
field_name = fld.pop('name')
|
||
|
else:
|
||
|
continue
|
||
|
extra_params.update(fld)
|
||
|
else:
|
||
|
raise ImproperlyConfigured(
|
||
|
_("%(settings)s doesn't recognize the value of %(app)s.%(model)s") % {
|
||
|
'settings': 'CATEGORY_SETTINGS',
|
||
|
'app': app,
|
||
|
'model': model_name})
|
||
|
registry_name = ".".join([app_label, model_name.lower(), field_name])
|
||
|
if registry_name in self._field_registry:
|
||
|
continue
|
||
|
|
||
|
try:
|
||
|
opts.get_field(field_name)
|
||
|
except FieldDoesNotExist:
|
||
|
self._field_registry[registry_name] = FIELD_TYPES[field_type](**extra_params)
|
||
|
self._field_registry[registry_name].contribute_to_class(model, field_name)
|
||
|
|
||
|
def register_m2m(self, model, field_name='categories', extra_params={}):
|
||
|
return self._register(model, field_name, extra_params, fields.CategoryM2MField)
|
||
|
|
||
|
def register_fk(self, model, field_name='category', extra_params={}):
|
||
|
return self._register(model, field_name, extra_params, fields.CategoryFKField)
|
||
|
|
||
|
def _register(self, model, field_name, extra_params={}, field=fields.CategoryFKField):
|
||
|
app_label = model._meta.app_label
|
||
|
registry_name = ".".join((app_label, model.__name__, field_name)).lower()
|
||
|
|
||
|
if registry_name in self._field_registry:
|
||
|
return # raise AlreadyRegistered
|
||
|
opts = model._meta
|
||
|
try:
|
||
|
opts.get_field(field_name)
|
||
|
except FieldDoesNotExist:
|
||
|
if app_label not in self._model_registry:
|
||
|
self._model_registry[app_label] = []
|
||
|
if model not in self._model_registry[app_label]:
|
||
|
self._model_registry[app_label].append(model)
|
||
|
self._field_registry[registry_name] = field(**extra_params)
|
||
|
self._field_registry[registry_name].contribute_to_class(model, field_name)
|
||
|
|
||
|
registry = Registry()
|
||
|
|
||
|
|
||
|
def _process_registry(registry, call_func):
|
||
|
"""
|
||
|
Given a dictionary, and a registration function, process the registry
|
||
|
"""
|
||
|
from django.core.exceptions import ImproperlyConfigured
|
||
|
from django.apps import apps
|
||
|
|
||
|
for key, value in list(registry.items()):
|
||
|
model = apps.get_model(*key.split('.'))
|
||
|
if model is None:
|
||
|
raise ImproperlyConfigured(_('%(key)s is not a model') % {'key': key})
|
||
|
if isinstance(value, (tuple, list)):
|
||
|
for item in value:
|
||
|
if isinstance(item, str):
|
||
|
call_func(model, item)
|
||
|
elif isinstance(item, dict):
|
||
|
field_name = item.pop('name')
|
||
|
call_func(model, field_name, extra_params=item)
|
||
|
else:
|
||
|
raise ImproperlyConfigured(_("%(settings)s doesn't recognize the value of %(key)s") %
|
||
|
{'settings': 'CATEGORY_SETTINGS', 'key': key})
|
||
|
elif isinstance(value, str):
|
||
|
call_func(model, value)
|
||
|
elif isinstance(value, dict):
|
||
|
field_name = value.pop('name')
|
||
|
call_func(model, field_name, extra_params=value)
|
||
|
else:
|
||
|
raise ImproperlyConfigured(_("%(settings)s doesn't recognize the value of %(key)s") %
|
||
|
{'settings': 'CATEGORY_SETTINGS', 'key': key})
|