Source code for model_path_converter
# -*- coding: utf-8 -*-
import re
from django.urls import register_converter
from django.urls.converters import get_converter, IntConverter
__author__ = """Daniel Hepper"""
__email__ = 'daniel@consideratecode.com'
__version__ = '0.1.0'
[docs]def camel_to_snake(s):
camel_to_snake_regex = r'((?<=[a-z0-9])[A-Z]|(?!^)(?<!_)[A-Z](?=[a-z]))'
return re.sub(camel_to_snake_regex, r'_\1', s).lower()
[docs]def snake_to_camel(s):
snake_to_camel_regex = r"(?:^|_)(.)"
return re.sub(snake_to_camel_regex, lambda m: m.group(1).upper(), s)
[docs]class ModelConverterMixin:
[docs] def get_queryset(self):
if self.queryset:
return self.queryset.all()
return self.model.objects.all()
[docs] def to_python(self, value):
try:
return self.get_queryset().get(**{self.field: super().to_python(value)})
except self.model.DoesNotExist:
raise ValueError
return super().to_url(getattr(obj, self.field))
[docs]def register_model_converter(model, name=None, field='pk', base=IntConverter, queryset=None):
"""
Registers a custom path converter for a model.
:param model: a Django model
:param str name: name to register the converter as
:param str field: name of the lookup field
:param base: base path converter, either by name or as class
(optional, defaults to `django.urls.converter.IntConverter`)
:param queryset: a custom querset to use (optional, defaults to `model.objects.all()`)
"""
if name is None:
name = camel_to_snake(model.__name__)
converter_name = '{}Converter'.format(model.__name__)
else:
converter_name = '{}Converter'.format(snake_to_camel(name))
if isinstance(base, str):
base = get_converter(base).__class__
converter_class = type(
converter_name,
(ModelConverterMixin, base,),
{'model': model, 'field': field, 'queryset': queryset}
)
register_converter(converter_class, name)