adm-ntuh-net/ntuh/submodule/django-categories/categories/registration.py
2024-12-12 10:19:16 +08:00

144 lines
5.9 KiB
Python
Executable file

"""
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})