def get(self, request, obj_id=None): from apps.realms import get_realms if obj_id is None: # Запрошен список всех известных категорий. item = get_category_lists( init_kwargs={ 'show_title': True, 'show_links': lambda cat: reverse(self.realm.get_details_urlname(), args=[cat.id]) }, additional_parents_aliases=get_category_aliases_under()) return self.render(request, {'item': item}) # Выводим список материалов (разбитых по областям сайта) для конкретной категории. category_model = get_category_model() category = get_object_or_404(category_model.objects.select_related('parent'), pk=obj_id) realm_list = [] for realm in get_realms(): if hasattr(realm.model, 'categories'): # ModelWithCategory objs = realm.model.get_objects_in_category(category)[:5] if objs: realm_list.append({ 'objects': objs, 'url': reverse(realm.get_tags_urlname(), args=[category.id]), 'realm': realm }) return self.render(request, {self.realm.name: category, 'item': category, 'realm_list': realm_list})
def get(self, request, obj_id=None): from apps.realms import get_realms realms = get_realms().values() if obj_id is None: # Запрошен список всех известных категорий. item = get_category_lists( init_kwargs={ 'show_title': True, 'show_links': lambda cat: reverse(self.realm.get_details_urlname(), args=[cat.id]) }, additional_parents_aliases=get_category_aliases_under()) return self.render(request, {'item': item, 'realms': realms}) # Выводим список материалов (разбитых по областям сайта) для конкретной категории. category_model = get_category_model() category = get_object_or_404( category_model.objects.select_related('parent'), pk=obj_id) realms_links = OrderedDict() for realm in realms: realm_model = realm.model if not hasattr(realm_model, 'categories'): # ModelWithCategory continue items = realm_model.get_objects_in_category(category) if not items: continue realm_title = realm_model.get_verbose_name_plural() _, plural = realm.get_names() realms_links[realm_title] = (plural, items) return self.render( request, { self.realm.name: category, 'item': category, 'realms_links': realms_links })
class CategoryRealm(RealmBase): """ Область с категориями. """ view_listing_description = 'Карта категорий материалов по языку программирования Python доступных на сайте.' view_listing_keywords = 'материалы по питону, python по категориям' model = get_category_model() icon = 'tag' name = 'category' name_plural = 'categories' allowed_views = ('listing', 'details') ready_for_digest = False sitemap_enabled = False show_on_main = False show_on_top = False view_listing_title = 'Путеводитель' view_listing_base_class = CategoryListingView view_details_base_class = CategoryListingView SYNDICATION_NAMESPACE = 'category_feeds' @classmethod def get_sitetree_details_item(cls): return item( 'Категория «{{ category.parent.title }} — {{ category.title }}»', 'categories:details category.id', in_menu=False, in_sitetree=False) @classmethod def init(cls): # Включаем прослушивание сигналов, необходимое для функционировая области. tie_model = get_tie_model() # url-синдикации будут обновлены в случае добавления/удаления связи сущности с категорией. signals.post_save.connect(cls.update_syndication_urls, sender=tie_model) signals.post_delete.connect(cls.update_syndication_urls, sender=tie_model) @classmethod def get_urls(cls): urls = super().get_urls() urls += CategoryRealm.get_syndication_urls() return urls @classmethod def get_syndication_url(cls): return 'feed/' @classmethod def update_syndication_urls(cls, **kwargs): """Обновляет url-шаблоны синдикации, заменяя старые новыми.""" target_namespace = cls.SYNDICATION_NAMESPACE linked_category_id_str = 'category_%s' % kwargs['instance'].category_id pattern_idx = -1 resolver = get_resolver(None) urlpatterns = getattr(resolver.urlconf_module, 'urlpatterns', resolver.urlconf_module) for idx, pattern in enumerate(urlpatterns): if getattr(pattern, 'namespace', '') == target_namespace: pattern_idx = idx if linked_category_id_str in pattern.reverse_dict.keys(): # Категория была известна и ранее, перепривязка URL не требуется. return break if pattern_idx > -1: del urlpatterns[pattern_idx] urlpatterns += cls.get_syndication_urls() @classmethod def get_syndication_urls(cls): """Возвращает url-шаблоны с привязанными сгенерированными представлениями для потоков синдикации (RSS) с перечислением новых материалов в категориях. :return: """ feeds = [] tie_model = get_tie_model() categories = tie_model.get_linked_objects(by_category=True) def get_in_category(category_id): """Возвращает объекты из разных областей в указанной категории.""" linked = tie_model.get_linked_objects( filter_kwargs={'category_id': category_id}, id_only=True) result = [] for model, ids in linked.items(): result.extend(model.get_actual().filter( id__in=ids)[:SYNDICATION_ITEMS_LIMIT]) result = sorted(result, key=attrgetter('time_published'), reverse=True) return result[:SYNDICATION_ITEMS_LIMIT] for category in categories.keys(): title = category.title category_id = category.id feed = RealmBase._get_syndication_feed( title=title, description='Материалы в категории «%s». %s' % (title, category.note), func_link=lambda self: reverse(CategoryRealm. get_details_urlname(), args=[self.category_id]), func_items=lambda self: get_in_category(self.category_id), cls_name='Category%s' % category_id) feed.category_id = category_id feeds.append( url(r'^%s/%s/$' % (category_id, SYNDICATION_URL_MARKER), feed, name='category_%s' % category_id)) _, realm_name_plural = CategoryRealm.get_names() return [ url(r'^%s/' % realm_name_plural, (feeds, realm_name_plural, cls.SYNDICATION_NAMESPACE)) ]
from uuid import uuid4 import pytest from django.db.utils import IntegrityError from django.template.base import TemplateSyntaxError from django.template.context import Context from sitecats.exceptions import SitecatsLockedCategoryDelete, SitecatsConfigurationError from sitecats.models import Category, Tie from sitecats.settings import UNRESOLVED_URL_MARKER from sitecats.toolbox import CategoryList, get_category_aliases_under, get_tie_model, \ get_category_model MODEL_TIE = get_tie_model() MODEL_CATEGORY = get_category_model() from sitecats.tests.testapp.models import Comment, Article @pytest.fixture def create_comment(): from sitecats.tests.testapp.models import Comment def create_comment_(): comment = Comment(title='comment%s' % uuid4().hex) comment.save() return comment return create_comment_
from uuid import uuid4 import pytest from django.db.utils import IntegrityError from django.template.base import TemplateSyntaxError from django.template.context import Context from sitecats.exceptions import SitecatsLockedCategoryDelete, SitecatsConfigurationError from sitecats.models import Category, Tie from sitecats.settings import UNRESOLVED_URL_MARKER from sitecats.toolbox import CategoryList, get_category_aliases_under, get_tie_model, \ get_category_model MODEL_TIE = get_tie_model() MODEL_CATEGORY = get_category_model() from sitecats.tests.testapp.models import Comment, Article @pytest.fixture def create_comment(): from sitecats.tests.testapp.models import Comment def create_comment_(): comment = Comment(title='comment%s' % uuid4().hex) comment.save() return comment return create_comment_