def portfolio_menu(request): """Портфолио менюшка""" result = {} all_blocks = [] # Для перевода cache_time = 60 # 60 секунд cache_var = '%s_portfolio_menu' % (settings.PROJECT_NAME, ) if settings.IS_DOMAINS: domain = get_domain(request) if domain: cache_var += '_%s' % domain['pk'] inCache = cache.get(cache_var) ignore_cache = request.GET.get('ignore_cache') or request.GET.get( 'force_new') if inCache and not ignore_cache: result = inCache else: # Вытаскиваем менюшку portfolio portfolio_menu = Blocks.objects.filter(tag='portfolio', link='/portfolio/', state=4).first() parents = '%s_%s' % (portfolio_menu.parents, portfolio_menu.id) search_blocks = Blocks.objects.filter(state=4, is_active=True).filter( Q(parents=parents) | Q(parents__startswith='%s_' % parents)) for item in search_blocks: all_blocks.append(item) menu_queryset = [] recursive_fill(search_blocks, menu_queryset, parents) menus = sort_voca(menu_queryset) # -------------------------- # Переводим блоки/контейнеры # -------------------------- if settings.IS_DOMAINS: domains = get_domains() domain = get_domain(request, domains) if domain: domains = [domain] get_translate(all_blocks, domains) translate_rows(all_blocks, domain) result['menus'] = menus cache.set(cache_var, result, cache_time) result['request'] = request return result
def show_sitemap(self, request): """Формирование ссылок для карты сайта :param request: HttpRequest TODO: постраничная навигация TODO: выполнять кроном и ложить в кэш/файл """ managers = self.get_menu_managers() context = {} q_string = {} containers = {} # для перевода all_containers = [] all_blocks = [] for key, manager in managers.items(): query = Blocks.objects.filter( container__in=manager['containers']).order_by('position') manager['structure'] = [] for container in manager['containers']: menus = [] blocks = [ block for block in query if block.container_id == container ] recursive_fill(blocks, menus, parents='') sort_voca(menus) container = Containers.objects.filter(pk=container).first() all_containers.append(container) all_blocks += blocks manager['structure'].append({ 'container': container, 'blocks': menus }) # Переводим блоки/контейнеры if settings.IS_DOMAINS and request: domains = get_domains() domain = get_domain(request, domains) if domain: domains = [domain] get_translate(all_blocks, domains) translate_rows(all_blocks, domain) get_translate(all_containers, domains) translate_rows(all_containers, domain) context['managers'] = managers page = SearchLink(q_string, request, containers) if not page: page = Blocks(name='Карта сайта') context['breadcrumbs'] = [{ 'name': page.name, 'link': '/sitemap/', }] context['page'] = page context['containers'] = containers template = 'sitemap_html.html' return render(request, template, context)
def flatmenu(request, tag: str = None, containers: list = []): """Все виды меню в шаблоне :param tag: Тег контейнера меню :param containers: Контейнеры, которые нужно передать в шаблон""" result = {} all_blocks = [] # Для перевода if not tag: return result cache_time = 60 # 60 секунд cache_var = '%s_flatmenu_%s' % (settings.PROJECT_NAME, tag) if settings.IS_DOMAINS: domain = get_domain(request) if domain: cache_var += '_%s' % domain['pk'] inCache = cache.get(cache_var) ignore_cache = request.GET.get('ignore_cache') or request.GET.get('force_new') if inCache and not ignore_cache: result = inCache else: search_blocks = Blocks.objects.filter(container__tag=tag, state=4, is_active=True, container__is_active=True) for item in search_blocks: all_blocks.append(item) menu_queryset = [] recursive_fill(search_blocks, menu_queryset, '') menus = sort_voca(menu_queryset) # -------------------------- # Переводим блоки/контейнеры # -------------------------- if settings.IS_DOMAINS: domains = get_domains() domain = get_domain(request, domains) if domain: domains = [domain] get_translate(all_blocks, domains) translate_rows(all_blocks, domain) result['menus'] = menus cache.set(cache_var, result, cache_time) result['containers'] = containers result['request'] = request result['tag'] = tag return result
def ReturnFile(request, link): """Возвращаем файл""" if not link.startswith('/'): link = '/%s' % link # Заебал этот фавикон, думаю, # одна проверка на него не напряжет if link == '/favicon.ico': path = '%s/img/favicon.ico' % settings.STATIC_ROOT.rstrip('/') with open(path, 'rb') as f: response = HttpResponse(f.read(), content_type='image/x-icon') response['Content-Length'] = file_size(path) response['Content-Disposition'] = 'inline; filename=%s' % (path, ) return response elif link == '/sitemap.xml': context = {} sitemap = SitemapXML() context['managers'] = sitemap.get_menu_managers() template = 'sitemap_index.html' return render(request, template, context, content_type='text/xml') elif link.startswith('/sitemap/'): context = {} sitemap = SitemapXML() context['blocks'] = sitemap.get_manager(link) template = 'sitemap_xml.html' return render(request, template, context, content_type='text/xml') search_files = Files.objects.filter(link=link, is_active=True) # Если мультидомен, # то ищем в том числе специфический для домена файл, # но если нету, то возвращаем без домена if settings.IS_DOMAINS: domain = get_domain(request) search_file_with_domain = search_files.filter( domain=domain['pk']).values_list('id', flat=True) if search_file_with_domain: search_files = search_files.filter(domain=domain['pk']) search_file = search_files.first() if search_file: path = '%s%s' % (search_file.get_folder(), search_file.path) if not check_path(path): with open(full_path(path), 'rb') as f: response = HttpResponse(f.read(), content_type=search_file.mime) response['Content-Length'] = file_size(path) response['Content-Disposition'] = 'inline; filename=%s' % (path, ) return response else: # файл не найден - лучше 404 отдать raise Http404 return redirect("/")
def get_translations(request, *args, **kwargs): """Получение переводов для UI""" left_menu_prefix = 'left_menu_' result = { 'translations': [], '%stranslations' % left_menu_prefix: [], } domain = get_domain(request, priority='session') # Если русский, то без перевода if domain.get('lang') == 'rus' or not domain: return JsonResponse(result, safe=False) domain_pk = domain.get('pk') class_names = [] for class_name in request.POST.get('class_names', '').split(','): class_name = class_name.strip() if class_name: class_names.append(class_name) if class_names: translations = UITranslate.objects.filter(class_name__in=class_names, domain_pk=domain_pk).values( 'class_name', 'value') result['translations'] = list(translations) # --------------------------- # Меню надо возвращать всегда # --------------------------- menus = UITranslate.objects.filter(class_name__startswith=left_menu_prefix, domain_pk=domain_pk).values( 'class_name', 'value') for menu in menus: result['%stranslations' % left_menu_prefix].append({ 'class_name': menu['class_name'], 'value': menu['value'], }) result['class_names'] = class_names result['domain'] = domain return JsonResponse(result, safe=False)
def translate_mode(request, *args, **kwargs): """Перевод текстов админки""" result = {} domain = get_domain(request, priority='session') # Если русский, то без перевода if domain.get('lang') == 'rus': result['error'] = 'Русский то не надо переводить!' if request.POST.get('old_value'): result['old_value'] = request.POST['old_value'] return JsonResponse(result, safe=False) perms = get_user_permissions(request.user, UITranslate) if not perms['edit']: result['error'] = 'Недостаточно прав' elif not domain: result['error'] = 'Не выбран домен' else: domain_pk = domain.get('pk') class_name = request.POST.get('pk') value = request.POST.get('value', '')[:254] value = value.strip() analog = UITranslate.objects.filter(class_name=class_name, domain_pk=domain_pk).first() # Херим, если пустое поле if not value: if analog: analog.delete() result['success'] = 'Перевод удален' return JsonResponse(result, safe=False) if not analog: analog = UITranslate(class_name=class_name, domain_pk=domain_pk) analog.value = value analog.save() result['translate'] = object_fields(analog) result['success'] = 'Данные записаны' result['domain'] = domain return JsonResponse(result, safe=False)
def standard_show(self, only_query: bool = False, only_fields: list = None, related_fields: list = ()): """Стандартный вывод данных по модели filters = Q(name__isnull=True)|Q(name="") :param only_query: просто вернуть запрос с фильтрами :param only_fields: достать только определенные поля :param related_fields: ссылающиеся объекты (OneToOneRel) для фильтра """ result = [] # -------------------------- # Если прав нету на просмотр # - ну тогда "пасется" пусть # -------------------------- if not self.permissions['view']: if only_query: return self.model.objects.none() paginator, records = myPaginator(0, self.q_string['page'], self.q_string['by']) self.raw_paginator = paginator self.context['raw_paginator'] = self.raw_paginator self.paginator = navigator(paginator, self.q_string, self.paginator_template) self.context['paginator'] = self.paginator self.context['rows'] = result return result # ---------------------------- # OneToOneRel поля для фильтра # ---------------------------- related_types = {} if related_fields: for item in self.model._meta.related_objects: if item.name in related_fields and isinstance( item, fields.related.OneToOneRel): related_types[item.name] = object_fields_types( item.related_model()) types = object_fields_types(self.model()) query = self.model.objects.all() if self.select_related: query = query.select_related(*self.select_related) if only_fields: query = query.only(*only_fields) q = None if self.request: # ---------- # GET / POST # ---------- for q_var in ('q', 'data[q]'): if self.request.method == 'GET': if self.request.GET.get(q_var) and self.search_fields: q = self.request.GET[q_var] if self.request.method == 'POST': if self.request.POST.get(q_var) and self.search_fields: q = self.request.POST[q_var] # ------------------------------------------- # Если вдруг поисковая фраза не в q-параметре # ------------------------------------------- if self.q: q = self.q cond = Q() if q: if not self.q: # ----------------------------------------- # Мы не хотим, чтобы q писалось в # постраничную пагинацию параметром, # поэтому вообще не вносим его в q_string # это можно сделать после l.standard_show() # во view (l.q_string['q']['q'] = q # ----------------------------------------- self.q_string['q']['q'] = q # ----------------- # RAW / сырой поиск # ----------------- raw_qqize = [] q_array = q.split(' ') for item in q_array: tmp_cond = Q() for field in self.search_fields: if field in types: # --------------------------- # По целому числу, возможно, # стоит сделать строгий поиск # ("primary_key", "int") # --------------------------- # -------------------------------------- # По дате производим нестандартный поиск # -------------------------------------- if types[field] in ('date', 'datetime'): d = str_to_date(q) if d: tmp_cond.add(Q(**{field: d}), Q.OR) continue else: key = '%s__icontains' % field tmp_cond.add(Q(**{key: item}), Q.OR) raw_qqize.append(item) elif '__' in field: # Похоже ищем foreign_key fkey = field.rsplit('__', 1)[0] if fkey in self.select_related: key = '%s__icontains' % field tmp_cond.add(Q(**{key: item}), Q.OR) raw_qqize.append(item) if tmp_cond: cond.add(tmp_cond, Q.AND) # ----------------------------------------------------- # Заполняем слова для подсветки (если они не заполнены, # что гарантировано, если мы не юзаем поиск по индексу) # ----------------------------------------------------- if not self.words: self.words = raw_qqize # ------------------------------------------------------- # Чтобы расширить поиск скажем своим списком айдишников, # нужно ввести это условие как Q.OR тогда сможем искать # стандартным поиском, однако добавлять свои результаты # скажем необходимо найти запись по переводу из Languages # ------------------------------------------------------- if self.custom_filter: query = query.filter(Q(cond) | Q(self.custom_filter)) else: query = query.filter(cond) if self.filters: for item in self.filters: # ----------------------------------- # Принимаем в фильтры словарь или Q() # ----------------------------------- if isinstance(item, dict): key, value = item.popitem() if key in types: query = self.cond_for_query(key, value, types, query) elif '__' in key: key_arr = key.split('__') related_model = key_arr[-2] related_field = key_arr[-1] # -------------------------- # Обратная связь OneToOneRel # -------------------------- if related_types: if related_model in related_types and related_field in related_types[ related_model]: prefix = '__'.join(key_arr[:-1]) custom_types = { '%s__%s' % (prefix, k): v for k, v in related_types[related_model].items() if k == related_field } query = self.cond_for_query( key, value, custom_types, query) continue # ------------------------------ # Прямая связь на OneToOneRel/FK # ForwardOneToOneDescriptor # field.field.model - эта модель # field.field.remote_field.model # на связанную модель # ------------------------------ if related_model in types and types[ related_model] == 'foreign_key': field = getattr(self.model, related_model) remote_types = object_fields_types( field.field.remote_field.model()) prefix = '__'.join(key_arr[:-1]) remote_types = { '%s__%s' % (prefix, k): v for k, v in remote_types.items() if k == related_field } rfield = '%s__%s' % (prefix, related_field) query = self.cond_for_query( rfield, value, remote_types, query) continue query = query.filter(**{key: value}) elif isinstance(item, Q): query = query.filter(item) if self.excludes: for item in self.excludes: query = query.exclude(item) # ---------------------------- # Вернуть запрос для отдельных # предварительных манипуляций # ---------------------------- self.query = query if only_query: return query total_records = query.aggregate(Count("id"))['id__count'] paginator, records = myPaginator(total_records, self.q_string['page'], self.q_string['by']) self.raw_paginator = paginator self.context['raw_paginator'] = self.raw_paginator self.paginator = navigator(paginator, self.q_string, self.paginator_template) self.context['paginator'] = self.paginator if not total_records: self.context['rows'] = [] return [] if self.custom_order: order_by = [ 'ordering', ] # ---------- # Сортировки # ---------- if self.order_by: for item in self.order_by: order_by.append(item) query = query.extra(select={ 'ordering': self.custom_order, }, order_by=order_by) # ---------- # Сортировки # ---------- if self.order_by and not self.custom_order: query = query.order_by(*self.order_by) result = query[records['start']:records['end']] self.context['rows'] = result # ------- # Перевод # ------- if settings.IS_DOMAINS: domains = get_translate(result, self.context['domains']) # --------------------------------- # отдаем перевод по текущему домену # --------------------------------- if self.request and get_admin_translate_rows(self.request): domain = get_domain(self.request, domains, priority='session') translate_rows(result, domain) return result
def dynamic_portfolio(request): cache_time = 300 cache_var = '%s_dynamic_portfolio' % (settings.PROJECT_NAME, ) domains = get_domains() domain = get_domain(request, domains) if domain: cache_var += '_%s' % domain['pk'] inCache = cache.get(cache_var) if inCache and not request.GET.get('force_new'): return inCache # Вытаскиваем менюшку portfolio portfolio_menu = Blocks.objects.filter(tag='portfolio', link='/portfolio/', state=4).first() if not portfolio_menu: return {} parents = '%s_%s' % (portfolio_menu.parents, portfolio_menu.id) all_blocks = Blocks.objects.filter(state=4, is_active=True).filter( Q(parents=parents) | Q(parents__startswith='%s_' % parents)) all_blocks = [ block for block in all_blocks if not block.link == '/portfolio/' ] if domain: domains = [domain] get_translate(all_blocks, domains) translate_rows(all_blocks, domain) menu_queryset = [] recursive_fill(all_blocks, menu_queryset, parents) blocks = sort_voca(menu_queryset) # К каждому блоку надо достать описание по сссылке descriptions = [] # К каждому блоку надо достать кол-во фоток # привязанных к подблокам, и из каждого подблока # первую фотку надо еще и выводить for block in blocks: if not hasattr(block, 'sub'): continue block.count = 0 block.images = [] ids_subblocks = {subblock.id: subblock.link for subblock in block.sub} # Для описания надо узнать какая стат.страничка # ссылается на subblock.link и взять от нее описание #related_by_link = Blocks.objects.filter(container__state=3, link__in=ids_subblocks.values()) related_by_link = [] related_containers = block.linkcontainer_set.select_related( 'container').all() if related_containers: related_by_link = related_containers[ 0].container.blocks_set.filter(link__in=ids_subblocks.values()) ids_desc = {related.link: related for related in related_by_link} # К каждому subblock надо докинуть описалово, чтобы получить его в картинках desc_arr = {} subblock_sorting = [] for subblock in block.sub: subblock_sorting.append(subblock.id) if subblock.link in ids_desc: desc_block = ids_desc[subblock.link] descriptions.append(desc_block) desc_arr[subblock.id] = desc_block links = LinkContainer.objects.filter( block__in=ids_subblocks.keys()).values('container', 'block') ids_links = { link['container']: { 'block_id': link['block'], 'position': subblock_sorting.index(link['block']), } for link in links } imgas = Blocks.objects.filter(container__in=ids_links.keys(), img__isnull=False).order_by('position') block.count += len(links) analogs = [] for imga in imgas: if imga.container_id in analogs: continue if imga.container_id in ids_links: block_id = ids_links[imga.container_id]['block_id'] # Нашли block_id надо взять его описание для этой фотки if block_id in desc_arr: imga.custom_block = desc_arr[block_id] imga.custom_pos = ids_links[imga.container_id]['position'] analogs.append(imga.container_id) block.images.append(imga) # Правильная сортировка изображений так как они в админке block.images.sort(key=lambda x: x.custom_pos if hasattr(x, 'custom_pos') else 0, reverse=True) # Перевод описаний вытащенных по ссылкам if domain: domains = [domain] get_translate(descriptions, domains) translate_rows(descriptions, domain) main_block = Blocks(name='All', title=blocks[0].title, class_name=blocks[0].class_name) main_block.images = [] main_block.count = 0 max_size = max([len(block.images) for block in blocks]) for i in range(max_size): for block in blocks: if len(block.images) > i: main_block.images.append(block.images[-(i + 1)]) main_block.count += 1 blocks.insert(0, main_block) result = { 'blocks': blocks, } cache.set(cache_var, result, cache_time) return result