from django.db import models from core.container.manager import GFKManager class Info(models.Model): objects = GFKManager() title = models.CharField( max_length=256, blank=True, null=True ) header = models.TextField( max_length=500, blank=True, null=True ) tags = models.ManyToManyField( 'self', symmetrical=False, blank=True, null=True ) def content_type_name(self): return self.content_type.model_class()._meta.verbose_name class Model(models.Model): info = CustomGenericRelation( 'Info', related_name="%(class)s_info" ) class A(Model): field = models.CharField( max_length=256, blank=True, null=True ) class B(Model): pass
# -*- coding: utf-8 -*- from django.contrib.contenttypes import generic from django.db.models.related import RelatedObject from south.modelsinspector import add_introspection_rules class CustomGenericRelation(generic.GenericRelation): def contribute_to_related_class(self, cls, related): super(CustomGenericRelation, self).contribute_to_related_class(cls, related) if self.rel.related_name and not hasattr(self.model, self.rel.related_name): rel_obj = RelatedObject(cls, self.model, self.rel.related_name) setattr(cls, self.rel.related_name, rel_obj) add_introspection_rules([ ( [CustomGenericRelation], [], {}, ), ], ["^core\.ext\.fields\.generic\.CustomGenericRelation"])
Info.objects.filter(content_type__in=(CT.models.A, CT.models.B))
rom django.contrib.contenttypes.models import ContentType from django.db import models from models import Model class Inner(object): def __get__(self, name): return getattr(self.name) class ContentTypeMap(object): __raw__ = {} def __get__(self, obj, addr): path = addr.pop(0) if not hasattr(obj, path): setattr(obj, path, type(path, (object,), {'parent': obj})) attr = getattr(obj, path) return self.__get__(attr, addr) if addr else attr def __init__(self): for model in filter(lambda X: issubclass(X, Model), models.get_models()): content_type = ContentType.objects.get_for_model(model) obj = self.__get__(self, model.__module__.split('.')) self.__raw__[content_type.model] = content_type.id setattr(obj, '%s' % model.__name__, content_type) for obj in map(lambda X: self.__get__(self, X.__module__.split('.')), filter(lambda X: issubclass(X, Model), models.get_models())): setattr(obj.parent, obj.__name__, obj()) CT = ContentTypeMap()
from django.conf.urls.defaults import * from django.http import HttpResponseForbidden from django_widgets.loading import registry from sekizai.context import SekizaiContext from tastypie.resources import Resource from tastypie.utils import trailing_slash from tastypie.serializers import Serializer from core.widgets.cms_plugins import PLUGIN_TEMPLATE_MAP from core.ext.decorator import api_require_request_parameters class HtmlSreializer(Serializer): def to_html(self, data, options=None): return data class WidgetResource(Resource): class Meta: resource_name = 'widget' include_resource_uri = False serializer = HtmlSreializer(formats=['html']) def prepend_urls(self): return [ url(r"^(?P<resource_name>%s)/render%s$" % (self._meta.resource_name, trailing_slash()), self.wrap_view('render'), name="api_render") ] @api_require_request_parameters(['template']) def render(self, request, **kwargs): data = dict(request.GET) template = data.pop('template')[0] if 'widget' in data: widget = registry.get(data.pop('widget')[0]) else: if template not in PLUGIN_TEMPLATE_MAP: return HttpResponseForbidden() widget = PLUGIN_TEMPLATE_MAP[template] data = dict(map(lambda (K, V): (K.rstrip('[]'), V) if K.endswith('[]') else (K.rstrip('[]'), V[0]), data.items())) return self.create_response( request, widget.render(SekizaiContext({'request': request}), template, data, relative_template_path=False) ) def obj_get_list(self, bundle, **kwargs): return []
import os import json from django import forms from django.conf import settings from django_widgets.loading import registry from cms.models import CMSPlugin from cms.plugin_base import CMSPluginBase from cms.plugin_pool import plugin_pool from core.widgets.widgets import ItemWidget PLUGIN_MAP = {} PLUGIN_CT_MAP = {} PLUGIN_TEMPLATE_MAP = {} class PluginWrapper(CMSPluginBase): admin_preview = False class FormWrapper(forms.ModelForm): widget = None templates_available = () def __init__(self, *args, **kwargs): super(FormWrapper, self).__init__(*args, **kwargs) if not self.fields['template'].initial: # TODO self.fields['template'].initial = self.widget.default_template self.fields['template'].help_text = 'at PROJECT_ROOT/templates/%s' % self.widget.get_template_folder() if self.templates_available: self.fields['template'].widget = forms.Select() self.fields['template'].widget.choices = self.templates_available self.__extra_fields__ = set(self.fields.keys()) - set(self._meta.model._meta.get_all_field_names()) data = json.loads(self.instance.data or '{}') if self.instance else {} for key, value in data.items(): self.fields[key].initial = value def clean(self): cleaned_data = super(FormWrapper, self).clean() cleaned_data['data'] = json.dumps(dict( map( lambda K: (K, cleaned_data[K]), filter( lambda K: K in cleaned_data, self.__extra_fields__ ) ) )) return cleaned_data class Meta: model = CMSPlugin widgets = { 'data': forms.HiddenInput() } def get_templates_available(widget): template_folder = widget.get_template_folder() real_folder = os.path.join(settings.TEMPLATE_DIRS[0], *template_folder.split('/')) result = () if os.path.exists(real_folder): for path, dirs, files in os.walk(real_folder): if path == real_folder: choices = filter(lambda filename: filename.endswith('html'), files) result = zip(choices, choices) rel_folder = '%(template_folder)s%(inner_path)s' % { 'template_folder': template_folder, 'inner_path': path.replace(real_folder, '') } for filename in files: PLUGIN_TEMPLATE_MAP['/'.join((rel_folder, filename))] = widget return result def register_plugin(widget, plugin): plugin_pool.register_plugin(plugin) PLUGIN_MAP[widget.__class__] = plugin if issubclass(widget.__class__, ItemWidget): for content_type in widget.__class__.content_types: if content_type not in PLUGIN_CT_MAP: PLUGIN_CT_MAP[content_type] = [] PLUGIN_CT_MAP[content_type].append(plugin) def get_plugin_form(widget, widget_name): return type('FormFor%s' % widget_name, (FormWrapper,), dict(map( lambda (key, options): (key, (options.pop('field') if 'field' in options else forms.CharField)(initial=getattr(widget, key, None), **options)), getattr(widget, 'kwargs', {}).items() ) + [('widget', widget), ('templates_available', get_templates_available(widget))])) def register_plugins(widgets): for widget_name, widget in widgets: if getattr(widget, 'registered', False): continue name = 'PluginFor%s' % widget_name plugin = type( name, (PluginWrapper,), { 'name': getattr(widget, 'name', widget_name), 'widget': widget, 'form': get_plugin_form(widget, widget_name) } ) register_plugin(widget, plugin) register_plugins(registry.widgets.items())
Source: https://habr.com/ru/post/228411/
All Articles