Задать вопрос
  • Как исправить ошибку с url адресом?

    @nurzhannogerbek Автор вопроса
    Сергей Горностаев, Здравствуйте! По вашему мнению, где конкретно я мог бы обойтись без относительных ссылок например?

    К примеру url адреса я указываю следующим образом в форме редактирования:
    <form method="post" action="{% url 'documents:category_year_edit' current_category current_year document.id %}" class='document-edit-form' enctype="multipart/form-data">
        <!--Cодержимое формы-->
    </form>


    urls.py:
    url(r'^(?P<category>\d+)/(?P<year>[0-9]{4})/edit/(?P<pk>\d+)/$',
            DocumentCategoryYearEdit.as_view(),
            name='category_year_edit'),


    В проблемный запрос (см. ниже), о котором я писал выше в посте формируется я так понимаю приложением django-el-pagination самостоятельно. Сам я на него повлиять не могу или я ошибаюсь?
    GET /documents/1/2009/edit/1120/?page=2&querystring_key=page HTTP/1.1" 200 5747
  • Как исправить ошибку с url адресом?

    @nurzhannogerbek Автор вопроса
    Konstantin Malyarov, Здравствуйте! Возвращает третий url /documents/1/2009/edit/1120/ (см. в посте). Это post запрос на сохранение новых изменений.
  • Как загружать данные в фоновом режиме через AJAX?

    @nurzhannogerbek Автор вопроса
    Animkim, здравствуйте! Все конечно выглядит круто, но данный код по факту возвращает лишь элементы верхнего уровня без каких либо детей. Например:
    {
    <Document: Title>: {},
    <Document: Title>: {},
     *** и так далее ***
    }

    К тому же даже если получу весь список документов, не совсем понятно как это все рендорить в шаблоне. На данный момент использую плагин Nestable2 для дерева на Frontend-e. Данный плагин дает возможность создать дерево c помощью JSON данных. Но это уже другая история.

    В любом случаи, спасибо за пищу для размышлений! :)
  • Как загружать данные в фоновом режиме через AJAX?

    @nurzhannogerbek Автор вопроса
    Animkim, Здравстуйте! :) Было бы круто так сделать, подскажите если есть идеи. Есть модель данных Document с полем parent, в которой хранится информация о предке. Так же есть поле position, с помощью которой определяется в какой последовательности должны стоять документы. Да, вы правы, get_children делает запрос к базе данных.

    models.py:
    class Document(models.Model):
        parent = models.ForeignKey('self', related_name='children', blank=True, null=True)
        position = models.PositiveIntegerField(blank=True, null=True)
  • Как открывать ajax запросом ветки дерева?

    @nurzhannogerbek Автор вопроса
    sim3x, Здравствуйте! :) Нет, не django-mptt. Использую приложение django-closuretree. Приложение очень удобное и простое. Данное приложение создает две таблице по логике Closure Table. Основная таблица (назовем ее Document), где хранится общая информация о документе и вторая таблица (назовем ее DocumentClosure), где хранится информация о связи документов между друг другом. Единственное что не предусмотрено в этом приложении так это рендоринг дерево. В django-mptt потомки кэшируются вроде из-за чего не происходит такой проблемы в производительностью при чтении. Могу ошибаться, так как не до конца понял механику django-mptt хоть и заглядывал под капот проекта. Было бы неплохо так же кэшировать потомков или подгружать их ajax-ом.
  • Как открывать ajax запросом ветки дерева?

    @nurzhannogerbek Автор вопроса
    С data-id pазобрался. Получаю id документа так: $(this).parent().data("id")
  • Как открывать ajax запросом ветки дерева?

    @nurzhannogerbek Автор вопроса
    sim3x, Здравствуйте! :) Есть страницы, которые рендорятся по 4~5 cекунд, если выводить все сразу на страницу. Я реализовал бесконечный скроллинг, это немного улучшило производительность. Посмотрев в терминале sql запросы к базе данных заметил, что происходит очень много микро запросов (0.002 мс), при проверке всех потомков каждого документа. Поэтому думаю лучше будет подгружать потомков с помощью ajax при попытки открыть ветку в дереве. Как вы считаете?

    В основной таблице 10534 записей (документов). Не знаю можно ли это считать много. Все ведь постигается в сравнении.

    Вот кстати пример узла который рендорит библиотека Nestable.
    <li class="dd-item infinite-item dd-collapsed" data-id="12005">
    
    	<!--Кнопки открытия/закрытия ветки-->
    	<i class="fa fa-minus-square" data-action="collapse" style="display: none;"></i>
    	<i class="fa fa-plus-square" data-action="expand" style=""></i>
    
    	<!--Область для перетаскивания-->
    	<div class="dd-handle"></div>
    
    	<div class="dd-content">
    		<span>
    			Название документа
    		</span>
    	</div>
    	
    	<!--Эту область хочу подгружать по необходимости-->
    	<ol class="dd-list infinite-container" style="display: none;">
    		<!--Дальше рекурсия-->
    	</ol>
    </li>


    Библиотека Nestable сразу добавляет кнопки открытия/закрытия веток, если в li элементе есть ol элемент. Поэтому приходится применять такую вот конструкцию:
    {% if node.get_children %}.

    Я начал составлять ajax запрос следующим образом, но возникли вопросы.
    1) Как запустить ajax запрос лишь один раз. Я имею введу после того как ветка откроется, то в следующих открытиях этой же ветки уже не нужно выполнять ajax запросы.
    2) Как получить значения data-id по клику на кнопку. Этот id нужен мне чтобы во view я мог сформировать queryset. Попросту говоря получить потомков данного документа:
    Document.objects.filter(id=data-id).get_descendants()

    3) Как потом подгружать их в шаблоне?

    $("i[data-action='expand']").click(function(){
    	$.ajax({
    		url: "",
    		type: "post",
    		contentType: 'application/json; charset= utf-8',
    		dataType: 'json',
    		data: $(this).closest("dd-item").attr("data-id"),  // Возвращает undefined
    	});
    });
  • Как отобразить в шаблоне рекурсивность древовидной структуру?

    @nurzhannogerbek Автор вопроса
    Артем Советников, ok. Удачного вам дня, Артем. Пошел дальше страдать c get_children() :D
  • Как отобразить в шаблоне рекурсивность древовидной структуру?

    @nurzhannogerbek Автор вопроса
    Артем Советников, Артем здравствуйте! :) Как раз копаюсь, разбираюсь. C методом recursetree полностью разобрался. В классе RecurseTreeNode есть два метода (render и _render_node). Как вы и советовали в методе render убрал кэширование (если не ошибаюсь за него отвечает cache_tree_children), а метод _render_node оставил без изменений. Теперь в файле models.py приступил к get_children, но здесь есть проблемки. Ведь в django-mptt есть поле parent в главной модели данных. В моем случаи я его вынес в отдельную модель DocumentClosure. При попытки запуска страницы c текущем кодом выдает ошибку. Видимо я куда-то не туда свернул или что-то упустил? Как бы вы переписали get_children? Если честно очень много взаимосвязей и малось мудрено. Нужен ли мне учитывать в get_children то что находится в блоке else. Нужно ли зарегистрировать self._tree_manager заранее где-то зарегистрировать, инициализировать?

    custom_tags.py:
    from django import template
    
    register = template.Library()
    
    @register.tag
    def recursetree(parser, token):
        bits = token.contents.split()
        if len(bits) != 2:
            raise template.TemplateSyntaxError(_('%s tag requires a queryset') % bits[0])
        queryset_var = template.Variable(bits[1])
        template_nodes = parser.parse(('endrecursetree',))
        parser.delete_first_token()
        return RecurseTreeNode(template_nodes, queryset_var)
    
    
    class RecurseTreeNode(template.Node):
        def __init__(self, template_nodes, queryset_var):
            self.template_nodes = template_nodes
            self.queryset_var = queryset_var
    
        def _render_node(self, context, node):
            bits = []
            context.push()
            for child in node.get_children():
                bits.append(self._render_node(context, child))
            context['node'] = node
            context['children'] = mark_safe(''.join(bits))
            rendered = self.template_nodes.render(context)
            context.pop()
            return rendered
    
        def render(self, context):
            queryset = self.queryset_var.resolve(context)
            roots = queryset  # Убрал cache_tree_children()
            bits = [self._render_node(context, node) for node in roots]
            return ''.join(bits)


    models.py:
    from functools import wraps
    
    def raise_if_unsaved(func):
        @wraps(func)
        def _fn(self, *args, **kwargs):
            if not self.pk:
                raise ValueError(
                    'Cannot call %(function)s on unsaved %(class)s instances'
                    % {'function': func.__name__, 'class': self.__class__.__name__}
                )
            return func(self, *args, **kwargs)
        return _fn
    
    
    class Document(models.Model):
        ***
    
        @raise_if_unsaved
        def get_children(self):
            if hasattr(self, '_cached_children'):
                qs = self._tree_manager.filter(pk__in=[n.pk for n in self._cached_children])
                qs._result_cache = self._cached_children
                return qs


    Ошибка: TypeError: 'NoneType' object is not iterable

    Полный Traceback:
    Traceback (most recent call last):
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/core/handlers/exception.py", line 41, in inner
        response = get_response(request)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/core/handlers/base.py", line 217, in _get_response
        response = self.process_exception_by_middleware(e, request)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/core/handlers/base.py", line 215, in _get_response
        response = response.render()
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/response.py", line 107, in render
        self.content = self.rendered_content
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/response.py", line 84, in rendered_content
        content = template.render(context, self._request)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/backends/django.py", line 66, in render
        return self.template.render(context)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 207, in render
        return self._render(context)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 199, in _render
        return self.nodelist.render(context)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 990, in render
        bit = node.render_annotated(context)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 957, in render_annotated
        return self.render(context)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/loader_tags.py", line 177, in render
        return compiled_parent._render(context)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 199, in _render
        return self.nodelist.render(context)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 990, in render
        bit = node.render_annotated(context)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 957, in render_annotated
        return self.render(context)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/loader_tags.py", line 177, in render
        return compiled_parent._render(context)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 199, in _render
        return self.nodelist.render(context)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 990, in render
        bit = node.render_annotated(context)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 957, in render_annotated
        return self.render(context)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/loader_tags.py", line 72, in render
        result = block.nodelist.render(context)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 990, in render
        bit = node.render_annotated(context)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 957, in render_annotated
        return self.render(context)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/loader_tags.py", line 72, in render
        result = block.nodelist.render(context)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 990, in render
        bit = node.render_annotated(context)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 957, in render_annotated
        return self.render(context)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/loader_tags.py", line 216, in render
        return template.render(context)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 209, in render
        return self._render(context)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 199, in _render
        return self.nodelist.render(context)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 990, in render
        bit = node.render_annotated(context)
      File "/Users/nurzhan_nogerbek/Virtualenvs/py2714/lib/python2.7/site-packages/django/template/base.py", line 957, in render_annotated
        return self.render(context)
      File "/Applications/Projects/web/dashboard.kase.kz/documents/templatetags/documents_tags.py", line 40, in render
        bits = [self._render_node(context, node) for node in roots]
      File "/Applications/Projects/web/dashboard.kase.kz/documents/templatetags/documents_tags.py", line 29, in _render_node
        for child in node.get_children():
    TypeError: 'NoneType' object is not iterable
  • Как правильно интегрировать Django с унаследованной базой данных?

    @nurzhannogerbek Автор вопроса
    Артем Советников, да вы правы. Я пытаетесь повторить таблицу в БД в модели Django. В целом смысл понятен теперь. Кажется у меня как раз случай который вы описали: не совпадения типов. К примеру в модели данных указал author = models.ForeignKey(***), но в самой таблице нет внешнего ключа. Спасибо вам за разъяснения!
  • Как правильно интегрировать Django с унаследованной базой данных?

    @nurzhannogerbek Автор вопроса
    1. manage.py migrate --fake [appname] - прошла успешно.
    2. makemigrations сделал и она создала 0001_initail.py файл.
    3. После этого попытался сделать команду migrate, но она не прошла. В данный момент не могу показать полной ошибки, так как сижу с другого компьютера. Но мне кажется проблема из-за того что модель данных и таблица не совпадают. Такое может быть? То есть в модели данных стоит author = models.ForeignKey(***), а в таблице нет внешнего ключа. Так как я уже упоманал стоит тип данных Number без ссылочной целостности. Я может чего-то не понимаю, возможно после команды migrate в идеале уже существующая таблица должна была поменяться?
  • Как отобразить в шаблоне рекурсивность древовидной структуру?

    @nurzhannogerbek Автор вопроса
    Артем Советников, Здравствуйте! Я так понял это тег для механики отрисовки в django-mptt:

    @register.tag
    def recursetree(parser, token):
        bits = token.contents.split()
        if len(bits) != 2:
            raise template.TemplateSyntaxError(_('%s tag requires a queryset') % bits[0])
        queryset_var = template.Variable(bits[1])
        template_nodes = parser.parse(('endrecursetree',))
        parser.delete_first_token()
        return RecurseTreeNode(template_nodes, queryset_var)


    Взял его за основу. Далее я так понимаю вы предлогаете переделать RecurseTreeNode, в частности метод get_children(), который в нем используется. Можете пожалуйста поподробней расказать или показать? Малось запутался...
  • Как правильно интегрировать Django с унаследованной базой данных?

    @nurzhannogerbek Автор вопроса
    Здравствуйте! С ошибкой разобрался, тоже применил команду: manage.py migrate --fake [appname].

    Проблема теперь в том, что к примеру я создал поле author = models.ForeignKey(***) в своей модели данных, а в этой старой унаследованной таблице нету ссылочной целостности, то есть стоит просто тип данных Number, где хранится id пользователя, это вроде не хорошо так хранить. Из-за этого мне кажется не проходит миграция. Здесь либо нужно менять таблицу, либо модель данных. Что вы думаете по этому поводу?

    Можно поинтересоваться, что вы подразумеваете под модифицировать схему через Django? Можете пожалуйста раскрыть свою мысль. Спасибо, за ссылку! Приложение пригодится.
  • Как отобразить в шаблоне рекурсивность древовидной структуру?

    @nurzhannogerbek Автор вопроса
    Здравствуйте! :) Спасибо вам за замечания, не судите пожалуйста строго. Вроде изучал разные архитектуры хранения иерархических данных, видимо что-то упустил. Просто django-mptt создает одну таблицу, в которой все хранится. Нужно было уйти от подхода с полем parent_id c одной табличкой (хоть и django-mptt сохраняет ссылочную целостность вроде для поля parent_id), поэтому пытаюсь реализовать Closure Table. Уже несколько дней ломаю голову. Подумал, что опытные программисты как вы смогут помочь обрисовать логику подобного кастомного тэга.

    Я правильно понимаю нужно в тег передать queryset, далее данный queryset преобразовать в json в формате грубо говоря:
    [{"id":1},{"id":2},{"id":3,"children":[{"id":4},{"id":5}]}]

    Далее с помощью этого json встравлять ul li к примеру...
    Я вижу вы хорошо ознакомлены с django-mptt. Какой механизм в их тэге?
  • Как правильно отпарсить JSON во view Django?

    @nurzhannogerbek Автор вопроса
    Павел Аксенов, Спасибо большое!!! Немного запутанно получилось с tree_id. C наступающим вас! =)
  • Как правильно отпарсить JSON во view Django?

    @nurzhannogerbek Автор вопроса
    Павел Аксенов, tree_id это поле для сортировки, она указывает в каком порядке должны отображаться ветки. К примеру:

    A              (tree_id=0, level=0)
    B              (tree_id=1, level=0)
    --B1         (tree_id=2, level=1)
    --B2         (tree_id=3, level=1)
    C              (tree_id=4, level=0)
    --C1         (tree_id=5, level=1)
    --C2         (tree_id=6, level=1)
    ----C21    (tree_id=7, level=2)
    ----C22    (tree_id=8, level=2)


    Получается подсчитать нужно сколько элементов есть в дереве для tree_id. Проверил ваш код, уровень вложенности (level) определяется верно.

    Попробовал так, но tree_id не правильный. Получается при рекурсии значение position снова начинается с position = 0. Где лучше всего установить начально значение position?
    @classmethod
    def tree_update(cls, parent_id, children, level=0):
        position = 0
        for child in children:
            cls.objects.filter(pk=child['id']).update(parent_id=parent_id, level=level, tree_id=position)
            position += 1
            cls.tree_update(child['id'], child.get('children', []), level + 1)
  • Как правильно отпарсить JSON во view Django?

    @nurzhannogerbek Автор вопроса
    Разобрался, ваш метод универсальный. Получается здесь происходит рекурсия. Cпасибо! C tree_id вроде все понятно, но с level немного непонятно для меня:

    @staticmethod
    def tree_update(parent_id, children):
        position = 0
        for child in children:
            Tree.objects.filter(pk=child['id']).update(parent_id=parent_id, tree_id=position, level=?)
            position += 1
            tree_update(child['id'], child.get('children', []))


    К примеру:
    A                (level=0)
    B                (level=0)
        B1          (level=1)
        B2          (level=1)
    C                (level=0)
        C1          (level=1)
        C2          (level=1)
            C21    (level=2)
            C22    (level=2)
  • Как правильно отпарсить JSON во view Django?

    @nurzhannogerbek Автор вопроса
    Александр Глухов, С первым вопросом разобрался. Оказывается забыл добавить position += 1 в последней итерации. Второй вопрос еще актуален :)
  • Как правильно отпарсить JSON во view Django?

    @nurzhannogerbek Автор вопроса
    Здравствуйте! Cпасибо за пример! У меня есть несколько вопросов. Подходит ли ваш метод tree_update для дерева с любым уровнем вложенности или есть ограничения? Просто у меня есть предположения, что метод не универсальный и подходит для дерева с уровнем вложенности 2. Просто в моем конкретном случаи максимальный уровень вложенности дерева равен 6. Второй вопрос как определить уровень вложенности (level). Позиция (tree_id) вроде определяется по номеру итерации.
  • Как правильно отпарсить JSON во view Django?

    @nurzhannogerbek Автор вопроса
    Александр Глухов, поспешил в выводами. Оказывается мой код ранее упомянутый в комментарии не работает корректно. Можете глянуть пожалуйста, просто интересно что не правильно сделал. Проблема когда пытаюсь переместить к примеру B1 у которой есть дети в пустую A. B1 становится потомком A, но вот B11 почему-то становится потомком B. Проверил json, который передается в view и он верный. Кажется проблема в самом моем коде, во вьюхе. Можете пожалуйста взглянуть и сказать свой вердикт. Просто интересно узнать, что не так.

    A
    B
        B1
            B11
        B2


    Второй вопрос касательно вашей процедуры. Я так понял вы тестируете на чистом Python без Django. Хочу протестить ее, но не могу понять как интегрировать ее в Django в своем Class Based View. Могли бы вы пояснить как в данной процедуре получать id элемента, ее позицию, id родителя, и уровень вложенности, чтобы я уже в Django мог бы менять значения:
    Document.objects.filter(id=?).update(tree_id=?, level=?, parent_id=?)