Моделирование пользовательской формы с помощью django crispy form

У меня возникла проблема, когда я хочу смоделировать стиль поля с помощью django-crispy-forms из шаблона, скачанного из интернета.

Поле выглядит следующим образом:

enter image description here

и html для этого раздела (очевидно, с использованием bootstrap5):

<div class="form-group mb-4">
    <label for="id_username">Username</label>
    <div class="input-group">
        <span class="input-group-text" id="basic-addon1">
            <svg class="icon icon-xs text-gray-600" fill="currentColor" viewBox="0 0 
                20 20" xmlns="http://www.w3.org/2000/svg"> <g 
                transform="translate(0.000000,20.000000) scale(0.100000,-0.100000)" 
                fill-rule="evenodd" stroke="none"> <path d="M72 168 c-18 -18 -14 -56 
                7 -68 26 -14 50 -3 57 26 11 42 -34 72 -64 42z M48 59 c-34 -20 -17 
                -29 52 -29 39 0 70 4 70 10 0 26 -87 40 -122 19z"/></svg>
        </span>                 

        <input type="text" class="form-control" placeholder="admin" name="username" 
            id="id_username" autofocus required>

    </div>  
</div>

Используя django-crispy-forms, я пытаюсь смоделировать это с помощью Layout() из crispy_forms.layout и используя класс формы в forms.py в django:

from django import forms
from django.utils.translation import gettext, gettext_lazy as _
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, MultiField, Fieldset, Submit, Div, HTML, Field, Row

class LoginForm(forms.Form):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper(self)
        self.helper.layout = Layout(
            Div(
                Div(
                    HTML('<span class="input-group-text" id="basic-addon1">'
                         '<svg class="icon icon-xs text-gray-600" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">'
                             '<g transform="translate(0.000000,20.000000) scale(0.100000,-0.100000)" fill-rule="evenodd" stroke="none">' 
                             '<path d="M72 168 c-18 -18 -14 -56 7 -68 26 -14 50 -3 57 26 11 42 -34 72 -64 42z M48 59 c-34 -20 -17 -29 52 -29 39 0 70 4 70 10 0 26 -87 40 -122 19z"/>'
                        '</svg>'
                        '</span>'
                    ),
                    Field('username',   css_class='form-control', placeholder='admin', autofocus=True, required=True),
                    css_class="input-group"
                ),
                css_class="form-group mb-4"
            ),
        )

    username = forms.CharField(label=_('Username'),)

И это выглядит следующим образом:

enter image description here

При проверке html из браузера:

<div class="form-group mb-4">
    <div class="input-group"> 
        <span class="input-group-text" id="basic-addon1">
            <!-- THAT SVG CODE -->
        </span> 
        <div id="div_id_username" class="control-group"> 
             <label for="id_username" class="control-label requiredField">
                    Username
                    <span class="asteriskField">*</span>
             </label> 
        ####==>#### <div class="controls">
             <input type="text" name="username" maxlength="150" class="form-control textinput textInput" placeholder="admin" autofocus="True" required="" id="id_username"> </div> </div> 
        ####==>#### </div>
    </div>
</div>

Очень близко, но вот проблема, использование Field из crispy_forms.layout добавляет <div> на текстовое поле <input>...

Есть идеи, как от этого избавиться?

Очевидно, что я мог бы скопировать и вставить весь код с помощью HTML() из crispy_forms.layout в Layout(), но тогда это разрушает цель использования django forms... - Я мог бы просто вывести его из шаблонов и извлечь поле из request.POST.

Есть идеи, как это решить? Большое спасибо.

Мне удалось обойти это, создав template под названием input_field_only.html.

{% load crispy_forms_field %}

<input type="{{ field.widget_type }}" class="form-control" placeholder="admin" name="{{ field.name }}" id="{{ field.id_for_label }}">

Сохранить в директории templates.

Затем в forms.py я буду использовать новый пользовательский шаблон вместе с LoginForm


class InputFieldOnly(Field):
    template = '<APP_NAME>/templates/input_field_only.html'


class LoginForm(forms.Form):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper(self)
        self.helper.layout = Layout(
            Div(
                Div(
                    HTML('<span class="input-group-text" id="basic-addon1">'
                         '<svg class="icon icon-xs text-gray-600" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">'
                             '<g transform="translate(0.000000,20.000000) scale(0.100000,-0.100000)" fill-rule="evenodd" stroke="none">' 
                             '<path d="M72 168 c-18 -18 -14 -56 7 -68 26 -14 50 -3 57 26 11 42 -34 72 -64 42z M48 59 c-34 -20 -17 -29 52 -29 39 0 70 4 70 10 0 26 -87 40 -122 19z"/>'
                        '</svg>'
                        '</span>'
                    ),
                                        # Add InputFieldOnly
                    InputFieldOnly('username'),
                    css_class="input-group"
                ),
                css_class="form-group mb-4"
            ),
        )
    # Add the widget argument here
    username = forms.CharField(label=_('Username'),)

Надеюсь, это поможет тем, кто столкнулся с той же проблемой!

Вернуться на верх