Задать вопрос
  • Как сохранить несколько файлов (изображений) одновременно?

    @nurzhannogerbek Автор вопроса
    Павел Аксенов: Я так понял эти два метода находятся на одном уровне? Протестировал данный код. Есть 2 проблемы. После нажатия кнопки submit перебрасывается на страницу, где показывается JSON данные. Возможно это происходит из-за того что убрали .serialize() из JS. Вторая проблема создается объект Article, но без изображений. Папка images пуста. Также пробовал переименовать названия метода с save_images на save_image, но результата это не дало.
  • Как сохранить несколько файлов (изображений) одновременно?

    @nurzhannogerbek Автор вопроса
    Павел Аксенов: Да, я заметил в Traceback ссылку на это поле. Дело в том, что есть пару полей у модели Article, которые я счел опустить в своем посте. В том месте, где находятся такие символы "******" во view (article_add) записываются данные в эти поля. Сами эти поля нету в форме. Поэтому я и использовал article_form.save(commit=False). Как же быть в таком случаи? Есть ли у вас предложения?
  • Как сохранить несколько файлов (изображений) одновременно?

    @nurzhannogerbek Автор вопроса
    Павел Аксенов: Изменил код, но к сожалению выводится точно такая же ошибка как указывал ранее. Пробовал с разными форматами изображений и с разными количествами изображений (.png, .jpeg). В папке image появляется лишь первый из указанных изображений. Изучив Traceback мне кажется, что проблемы с созданием объектов Image и сохранением данных в БД. В методе save в форме есть строка: Image.objects.create(image=each, acticle=instance). Насколько она правильная по вашему мнению? Кстати, в роли первичного ключа в модели Article использую UUID. Не знаю может ли это влиять как-то на результат...
  • Как сохранить несколько файлов (изображений) одновременно?

    @nurzhannogerbek Автор вопроса
    Павел Аксенов: Нет, у обоих выбранных изображений в названии были только латинские буквы. Вот названия файлов: "IMG_2184.JPG" и "IMG_2178.JPG". А почему вы спросили про названия файлов? Это как-то может повлиять?
  • Как сохранить несколько файлов (изображений) одновременно?

    @nurzhannogerbek Автор вопроса
    Павел Аксенов: Я загрузил два изображения в поле image и заметил, что в media_root в папке images, куда должны отправляться изображения стоит первое из выбранных изображений.
  • Как сохранить несколько файлов (изображений) одновременно?

    @nurzhannogerbek Автор вопроса
    Павел Аксенов: Здравствуйте! Вы правы, я использую AJAX. Почитал про FormData и кажется вы правы это то, что мне нужно. Я добавил JS код в пост, можете его проверить пожалуйста? Я добавил следующий код в метод saveForm:
    var dataForm = new FormData(form);

    На текущий момент поле image в forms.py выглядит так:
    image = MultiMediaField(min_num=1, media_type='image')


    Выбрал файлы (изображения), нажал кнопку submit и выдала такую вот ошибку:
    Traceback (most recent call last):
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\core\handlers\exception.py", line 39, in inner
        response = get_response(request)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\core\handlers\base.py", line 187, in _get_response
        response = self.process_exception_by_middleware(e, request)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\core\handlers\base.py", line 185, in _get_response
        response = wrapped_callback(request, *callback_args, **callback_kwargs)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\reversion\revisions.py", line 296, in do_revision_context
        return func(*args, **kwargs)
      File "C:\Users\Nurzhan\PycharmProjects\RMS\project\views.py", line 1689, in article_add
        article= article_form.save(commit=False)
      File "C:\Users\Nurzhan\PycharmProjects\RMS\project\forms.py", line 271, in save
        Image.objects.create(image=each, article=instance)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
        return getattr(self.get_queryset(), name)(*args, **kwargs)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\query.py", line 399, in create
        obj.save(force_insert=True, using=self.db)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\base.py", line 796, in save
        force_update=force_update, update_fields=update_fields)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\base.py", line 824, in save_base
        updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\base.py", line 908, in _save_table
        result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\base.py", line 947, in _do_insert
        using=using, raw=raw)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
        return getattr(self.get_queryset(), name)(*args, **kwargs)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\query.py", line 1045, in _insert
        return query.get_compiler(using=using).execute_sql(return_id)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\sql\compiler.py", line 1054, in execute_sql
        cursor.execute(sql, params)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\backends\utils.py", line 79, in execute
        return super(CursorDebugWrapper, self).execute(sql, params)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\backends\utils.py", line 64, in execute
        return self.cursor.execute(sql, params)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\utils.py", line 94, in __exit__
        six.reraise(dj_exc_type, dj_exc_value, traceback)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\utils\six.py", line 685, in reraise
        raise value.with_traceback(tb)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\backends\utils.py", line 64, in execute
        return self.cursor.execute(sql, params)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\sql_server\pyodbc\base.py", line 539, in execute
        return self.cursor.execute(sql, params)
    django.db.utils.IntegrityError: ('23000', '[23000] [Microsoft][ODBC SQL Server Driver][SQL Server]�������� ���������� INSERT � ������������ FOREIGN KEY "project_image_article_id_1cd62783_fk_project_article_code". �������� ��������� � ���� ������ "RMS", ������� "dbo.project_article", column \'code\'. (547) (SQLExecDirectW)')


    Можете пожалуйста подсказать, что делаю не так? Как я понял с Traceback ошибка с сохранением в БД.
  • Как правильно создать кастомный виджет для поля?

    @nurzhannogerbek Автор вопроса
    Павел Аксенов: Здравствуйте! На счет классов вопрос был актуален еще, с тегом span разобрался. Спасибо вам большое!!! =)
  • Как прикрутить DropzoneJS к полю в Джанго?

    @nurzhannogerbek Автор вопроса
    Я подключил js и сss файлы в шаблоне. В консоли не выдает ошибки. Я пробовал в article_add.html вместо
    $("#id_image").dropzone({ url: "{% url 'article_add' %}" });
    добавить
    $(".dropzone").dropzone({ url: "{% url 'article_add' %}" });
    . В конце формы, то есть там где стоит данный кусок кода появляется некое поле куда можно перетаскивать файлы. Мне же нужно к существующему полю (#id_image) прикрепить dropzone. Что вы думаете по этому поводу?
  • Как правильно создать кастомный виджет для поля?

    @nurzhannogerbek Автор вопроса
    Павел Аксенов: Здравствуйте! Немного запоздало, но хочется спросить такой вопрос. Пытаюсь поместить названия Групп и Задач в тег span, но безрезультатно. Можете подсказать куда смотреть в вашем js коде? Просто я подумал поместив названия в тег span можно в поместить на них обработчик событий по клику или это можно сделать и без этого? Также вопрос такой как установить класс в тег ul li отдельно для Задачи у Группы. Я имею введу <ul class='group'> и <ul class='task'>? На данный момент есть var html = $('<ul class="">'); но он ко всем ul применяется.

    Я так понял вот эти две строки?
    html.append(make_li(name, lst[name]))
    и
    html.text(name).append(make_ul(elem));
  • Как добавить возможность загружать изображения в django-ckeditor?

    @nurzhannogerbek Автор вопроса
    Да, создал. Проблему с загрузкой изображения решил. В документации было написано следующее:
    By default the upload and browse URLs use staff_member_required decorator - ckeditor_uploader/urls.py - if you want other decorators just insert two urls found in that urls.py and don’t include it.


    Необходим был вот такой url:

    urlpatterns += [
        url(r'^upload/', login_required(views.upload), name='ckeditor_upload'),
        url(r'^browse/', never_cache(login_required(views.browse)), name='ckeditor_browse'),
    ]


    Но есть проблемы по прежнему. Странное поведение в Firefox (нельзя ввести что либо во все input-ы). Так же при нажатии submit должна была создаться новая запись (в моем случаи новая статья), но ничего не происходит. Как сохранить данные в БД? Что нитак в файле view? Что думаете?
  • Как правильно создать кастомный виджет для поля?

    @nurzhannogerbek Автор вопроса
    Павел Аксенов: СПАСИБО ВАМ БОЛЬШОЕ!!! Заработало! Мне очень стыдно, что отнял у вас столько времени, но кажется это была моя ошибка. Дело в том, что я столько всего вчера перепробовал и сегодня удалив все, начал с самого начало, на чистую голову и все заработало. Кажется было много лишнего в коде и почистив его все заработало. СПАСИБО ВАМ ОГРОМНОЕ! =)
  • Как правильно создать кастомный виджет для поля?

    @nurzhannogerbek Автор вопроса
    Павел Аксенов: Если убрать {{ form.data_tree }} они по одной, без дублирования, нету лишь вложенности.
  • Как правильно создать кастомный виджет для поля?

    @nurzhannogerbek Автор вопроса
    Павел Аксенов: Да, я описывал 4 форму. Я пробовал вчера убрать {{ form.data_tree }}, тогда исчезает вложенность, остаются лишь одни функции.
  • Как правильно создать кастомный виджет для поля?

    @nurzhannogerbek Автор вопроса
    Павел Аксенов: Cпасибо большое за советы! Заработало!!! Но есть проблемы, а точнее странное поведение. Хотел узнать у вас с чем они связаны и как быть.

    Форма у меня находится в модальном окне и содержимое модального окна загружается через AJAX. Вроде вывело, но почему-то записи функций дублируются. Вот скриншот:
    58d8fc7a44eb4928a5c913d76f95ca0a.PNG
    Также форму ставил в модальное окно без ее загрузки через AJAX. Результат был такой же.

    При этом за приделами модального окна форма отображается нормально, без дублирования функций.

    Поэксперементировав я понял, что избавиться от дублирования, можно лишь сделав блок tree пустым в template (убрать {{ form.function }}).

    При этом когда сделал блок tree пустым происходит еще одна проблема. Когда я закрываю модальное окно и снова его открываю то функции исчезают. Вот скриншот:
    9825cb29b865483185b43bcb3033ff41.PNG
  • Как правильно создать кастомный виджет для поля?

    @nurzhannogerbek Автор вопроса
    Павел Аксенов: А что у вас в 4 форме? Просто я пробовал запустить 4 форму, но выдает ошибку. Я лишь изменил id на code (UUID) и кажется из за возникли ошибки с JSON.

    Ошибка 4 формы:
    Traceback (most recent call last):
    File "C:\Users\Nurzhan\PycharmProjects\RMS\project\forms.py", line 360, in data_tree
        return mark_safe(date_tree_template.format(json.dumps(tree), 'function'))
        raise TypeError(repr(o) + " is not JSON serializable")
    TypeError: UUID('79ea5a9c-f3a1-453e-bb37-e5c1182a383e') is not JSON serializable


    Вторая форма заработала. Спасибо! =)
  • Как правильно создать кастомный виджет для поля?

    @nurzhannogerbek Автор вопроса
    Павел Аксенов: Я если честно, то я запутался))) Вроде же от форм создаваемых на основе модели (ModelForm) вроде отказались. А разве all_functions, который во вью формирую, не нужно в def __init__(self, all_function, *args, **kwargs) помещать? Можете весь код второй формы целиком еще раз отправить пожалуйста?!
  • Как правильно создать кастомный виджет для поля?

    @nurzhannogerbek Автор вопроса
    Павел Аксенов: c UUID я разобрался, переписал все места, где есть упоминание id, на название поля своего первичного ключа (в моем случаи сode). С помощью этой формы Requirement как раз создается, поэтому нужен ли instance? Я пробовал вчера убрать instance, но выдавала ошибки, поэтому счет нужным оставить их. Кстати, а что на счет списка (all_functions), который я формирую во view и передаю через конструктор в форму (Проблема во второй форме)?
  • Как правильно создать кастомный виджет для поля?

    @nurzhannogerbek Автор вопроса
    Павел Аксенов: У меня возникли вопросы.

    ВТОРАЯ ФОРМА:
    Смог запустить вторую форму и должен сказать, что она очень красивая =) Но тут возникли проблемы. Я список функций формирую во view и пытаюсь передать ее в конструктор, но выдает ошибку. Возможно неправильно объявил в конструкторе. Что сделал не так? Также еще вопрос по второй форме, если я захочу добавить поле какое нибудь (в моем случаи поле name, которая CharField) я просто должен добавить перед методом _init_ инициализировать это поле?

    forms.py: (место где добавил список функций и добавил поле name)
    class RequirementForm2(forms.Form):
        name = forms.СharField()
        
        def __init__(self, all_functions, *args, **kwargs):
           *SOME CODE*
            super(RequirementForm2, self).__init__(*args, **kwargs)
            self.functions = all_functions.select_related('task').select_related('task__group')
            *SOME CODE*


    Ошибка по второй форме:
    Traceback (most recent call last):
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\core\handlers\exception.py", line 39, in inner
        response = get_response(request)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\core\handlers\base.py", line 187, in _get_response
        response = self.process_exception_by_middleware(e, request)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\core\handlers\base.py", line 185, in _get_response
        response = wrapped_callback(request, *callback_args, **callback_kwargs)
      File "C:\Users\Nurzhan\PycharmProjects\RMS\project\views.py", line 1076, in group_requirement_detail
        form = RequirementForm2(request.POST or None, instance=Requirement.objects.first(), all_functions=all_functions)  # TEST FORM
    TypeError: __init__() got multiple values for argument 'all_functions'


    ПЕРВАЯ ФОРМА:
    Не могу запустить первую форму выдает ошибку массивную, не особо понял на что именно ругается. Можете взглянуть?

    Ошибка по первой форме:
    Traceback (most recent call last):
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\core\handlers\exception.py", line 39, in inner
        response = get_response(request)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\core\handlers\base.py", line 187, in _get_response
        response = self.process_exception_by_middleware(e, request)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\core\handlers\base.py", line 185, in _get_response
        response = wrapped_callback(request, *callback_args, **callback_kwargs)
      File "C:\Users\Nurzhan\PycharmProjects\RMS\project\views.py", line 1092, in group_requirement_detail
        return render(request, 'project/group_requirement_detail.html', context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\shortcuts.py", line 30, in render
        content = loader.render_to_string(template_name, context, request, using=using)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\loader.py", line 68, in render_to_string
        return template.render(context, request)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\backends\django.py", line 66, in render
        return self.template.render(context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py", line 208, in render
        return self._render(context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py", line 199, in _render
        return self.nodelist.render(context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py", line 994, in render
        bit = node.render_annotated(context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py", line 961, in render_annotated
        return self.render(context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\loader_tags.py", line 174, in render
        return compiled_parent._render(context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py", line 199, in _render
        return self.nodelist.render(context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py", line 994, in render
        bit = node.render_annotated(context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py", line 961, in render_annotated
        return self.render(context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\loader_tags.py", line 70, in render
        result = block.nodelist.render(context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py", line 994, in render
        bit = node.render_annotated(context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py", line 961, in render_annotated
        return self.render(context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py", line 1044, in render
        output = self.filter_expression.resolve(context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py", line 711, in resolve
        obj = self.var.resolve(context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py", line 852, in resolve
        value = self._resolve_lookup(context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py", line 915, in _resolve_lookup
        current = current()
      File "C:\Users\Nurzhan\PycharmProjects\RMS\project\forms.py", line 268, in to_tree
        return render_to_string('project/tree_form.html', context={'tree': tree})
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\loader.py", line 68, in render_to_string
        return template.render(context, request)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\backends\django.py", line 66, in render
        return self.template.render(context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py", line 208, in render
        return self._render(context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py", line 199, in _render
        return self.nodelist.render(context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py", line 994, in render
        bit = node.render_annotated(context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py", line 961, in render_annotated
        return self.render(context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\defaulttags.py", line 209, in render
        nodelist.append(node.render_annotated(context))
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py", line 961, in render_annotated
        return self.render(context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\defaulttags.py", line 209, in render
        nodelist.append(node.render_annotated(context))
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py", line 961, in render_annotated
        return self.render(context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\defaulttags.py", line 209, in render
        nodelist.append(node.render_annotated(context))
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py", line 961, in render_annotated
        return self.render(context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py", line 1050, in render
        return render_value_in_context(output, context)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\template\base.py", line 1028, in render_value_in_context
        value = force_text(value)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\utils\encoding.py", line 76, in force_text
        s = six.text_type(s)
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\utils\html.py", line 391, in <lambda>
        klass.__str__ = lambda self: mark_safe(klass_str(self))
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\forms\boundfield.py", line 43, in __str__
        return self.as_widget()
      File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\forms\boundfield.py", line 89, in as_widget
        attrs = self.build_widget_attrs(attrs, widget)
      File "C:\Users\Nurzhan\PycharmProjects\RMS\project\forms.py", line 232, in build_widget_attrs
        self.initial = widget.attrs.get('value') if widget.attrs.get('value') in self.initial else None
    AttributeError: can't set attribute
  • Как правильно создать кастомный виджет для поля?

    @nurzhannogerbek Автор вопроса
    Павел Аксенов: Здравствуйте! У меня есть модель Requirement c двумя полями: name (CharField) и function (ManyToManyField). Поэтому я думал, что в форму будут выводиться два виджета для каждого поля. Поэтому и ошибочно думал, что для поля function нужен будет кастомный виджет. Я только начал изучать ваш код и хотел спросить у вас в чем разница между формами RequirementForm и RequirementForm2? Еще хотел узнать нужно будет ли ввести изменения в код если у меня в моделях Group, Task, Function в роли первичного ключа используется UUID?

    code = models.UUIDField(_('Code'), primary_key=True, default=uuid.uuid4, editable=False)
  • Как создать древовидный список с сheckbox?

    @nurzhannogerbek Автор вопроса
    Павел Аксенов: Если честно, к сожалению вопрос еще не решен. Пока что примерно сверстал template виджета. Я так понял нужно всеже создать свой собственный виджет, но раньше я не создавал сам виджеты и не понимаю с чего начать при его создании. Посмотрел пару примеров, и понял, что вышеупомянутый template можно указать в ручную при создании виджета, но только я не понимаю какое наследование должно быть в моего виджета. По сути это некий MultipleModelChoiseField куда поступает queryset или ModelChoiseField. Как указать это в виджете еще не разобрался. Что вы думаете на счет вышесказанного?

    tree_widget.html:
    {% for group in groups %}
        <p>{{ group }}</p>
        {% for task in group.task_set.all %}
            <p>{{ task }}</p>
            {% for function in task.function_set.all %}
                <p>
                   <input type="checkbox" name="option" value="{{ function }}">{{ function }}
                </p>
            {% endfor %}
        {% endfor %}
    {% endfor %}


    forms.py:
    class ProgramForm(forms.ModelForm):
        function = forms.ModelMultipleChoiceField(required=True, widget=CustomTreeWidget, queryset=Group.objects.none())
    
        class Meta:
            model = Program
            fields = ('function',)
    
        def __init__(self, all_groups, *args, **kwargs):
            super(ProgramForm, self).__init__(*args, **kwargs)
            self.fields['function'].queryset = all_groups  # I take all Group objects from view


    widgets.py:
    class СustomTreeWidget(CheckboxSelectMultiple):
        template_name = 'tree_widget.html'
        ???