在django-crispy-forms中创建控件行

时间:2021-12-13 16:02:40

Using django-crispy-forms I want to combine two (or more) widgets on a single row. See also the attached example. I think it should be possible using that library, although the documentation does include examples on this issue and the source code didn't help either. So has anyone managed to get similar results using django-crispy-forms?

使用django-crispy-forms我想在一行中组合两个(或更多)小部件。另请参见附带的示例。我认为应该可以使用该库,虽然文档中包含有关此问题的示例,但源代码也没有帮助。那么有没有人设法使用django-crispy-forms获得类似的结果?

在django-crispy-forms中创建控件行

The HTML required for such a form looks like this:

这种表单所需的HTML如下所示:

<div class="control-group">
    <label for="desc" class="control-label">
        Description
    </label>
    <div class="controls controls-row">
        <input class="span2" maxlength="255" type="text" id="desc">
        <input class="span3" maxlength="255" type="text">
    </div>
</div>

3 个解决方案

#1


3  

You could do it with defining HTML object in `def init(self, *args, **kwargs): in layout object. This HTML will give you all the freedom you want for your needs.

您可以在`def init(self,* args,** kwargs)中定义HTML对象:在布局对象中。此HTML将为您提供所需的所有*。

There is another way too. To actually make your own template in in your templates folder and then in your layout object define the path to that template Example:

还有另一种方式。要在模板文件夹中实际创建自己的模板,然后在布局对象中定义该模板的路径示例:

Field('name', template='path/to/template/single_line_input.html'),

Where 'name' is actually a widget.

'name'实际上是一个小部件。

Of course you could always try to do it with playing around in the CSS files for your app, something like float: left or display: inline might help, but you would have to define the classes on the widgets which should be displayed inline. This could be a bit tricky for someone who is not skilled in frontend CSS (for result could be various in different browsers and on different resolutions, so needless to say some testing is needed). The problem you have is mainly the fact that browsers are rendering input fields as block objects by default, so they take up all the space in one line even if their width is less.

当然你总是可以尝试在你的应用程序的CSS文件中玩游戏,例如float:left或display:inline可能有帮助,但是你必须在小部件上定义应该内联显示的类。对于不熟悉前端CSS的人来说这可能有点棘手(因为结果可能在不同的浏览器和不同的分辨率上各种各样,所以不用说需要进行一些测试)。您遇到的问题主要是浏览器默认将输入字段渲染为块对象,因此即使宽度较小,它们也占用一行中的所有空间。

#2


7  

Yes. Use Layouts

是。使用布局

Here's an example snippet to get you going.

这是一个让你前进的示例片段。

def __init__(self, *args, **kwargs):
    self.helper = FormHelper()
    self.helper.form_method = 'get'
    self.helper.form_id = 'id_search'
    self.helper.layout = Layout(
            Div(
                Div(Field('arrival_date', css_class='span12 input-large calendar',
                    placeholder='dd/mm/yyyy'), css_class='span5'),
                Div(Field('departure_date', css_class='span12 input-large calendar',
                    placeholder='dd/mm/yyyy'), css_class='span5'),
                Div(Field('rooms', css_class='span12'), css_class='span2 styled-rooms'),
                css_class='row-fluid',
            ),
        )

#3


2  

You can use MultiValueField and MultiWidget to get this behavior. You'll need to think about and modify the compress and decompress methods, but something like the following should get you part way there.

您可以使用MultiValueField和MultiWidget来获取此行为。您需要考虑并修改压缩和解压缩方法,但是类似下面的内容应该让您分道扬..

from django import forms
from crispy_forms.helper import FormHelper

class MyWidget(forms.MultiWidget):
    widgets = (forms.TextInput(), forms.TextInput())
    super(ExpirationDateWidget, self).__init__(widgets)

    def decompress(self, value):
        if value:
            return value.split('|')  # or however you combined the two values
        return [None, None]


class MyMultiField(forms.MultiValueField):
    def __init__(self, *args, **kwargs):
        self.widget = MyWidget(*args, **kwargs)

    def compress(self, data_list):
        return data_list[0] + '|' + data_list[1]  # or other logical compression


class MyForm(forms.Form):
    multi_field = MyMultiField()
    # other fields like category and category_new

    def __init__(self, *args, **kwargs):
        self.helper = FormHelper()
        self.helper.form_class = 'form-horizontal'
        self.helper.layout = Layout('multi_field', 'category', 'category_new')

This will result in something like:

这将导致类似于:

 <div id="div_id_multi_field" class="control-group">
     <label for="id_multi_field_0" class="control-label">Multi Field</label>
     <div class="controls">
         <input id="id_multi_field_0">
         <input id="id_multi_field_1">
     </div>
 </div>

#1


3  

You could do it with defining HTML object in `def init(self, *args, **kwargs): in layout object. This HTML will give you all the freedom you want for your needs.

您可以在`def init(self,* args,** kwargs)中定义HTML对象:在布局对象中。此HTML将为您提供所需的所有*。

There is another way too. To actually make your own template in in your templates folder and then in your layout object define the path to that template Example:

还有另一种方式。要在模板文件夹中实际创建自己的模板,然后在布局对象中定义该模板的路径示例:

Field('name', template='path/to/template/single_line_input.html'),

Where 'name' is actually a widget.

'name'实际上是一个小部件。

Of course you could always try to do it with playing around in the CSS files for your app, something like float: left or display: inline might help, but you would have to define the classes on the widgets which should be displayed inline. This could be a bit tricky for someone who is not skilled in frontend CSS (for result could be various in different browsers and on different resolutions, so needless to say some testing is needed). The problem you have is mainly the fact that browsers are rendering input fields as block objects by default, so they take up all the space in one line even if their width is less.

当然你总是可以尝试在你的应用程序的CSS文件中玩游戏,例如float:left或display:inline可能有帮助,但是你必须在小部件上定义应该内联显示的类。对于不熟悉前端CSS的人来说这可能有点棘手(因为结果可能在不同的浏览器和不同的分辨率上各种各样,所以不用说需要进行一些测试)。您遇到的问题主要是浏览器默认将输入字段渲染为块对象,因此即使宽度较小,它们也占用一行中的所有空间。

#2


7  

Yes. Use Layouts

是。使用布局

Here's an example snippet to get you going.

这是一个让你前进的示例片段。

def __init__(self, *args, **kwargs):
    self.helper = FormHelper()
    self.helper.form_method = 'get'
    self.helper.form_id = 'id_search'
    self.helper.layout = Layout(
            Div(
                Div(Field('arrival_date', css_class='span12 input-large calendar',
                    placeholder='dd/mm/yyyy'), css_class='span5'),
                Div(Field('departure_date', css_class='span12 input-large calendar',
                    placeholder='dd/mm/yyyy'), css_class='span5'),
                Div(Field('rooms', css_class='span12'), css_class='span2 styled-rooms'),
                css_class='row-fluid',
            ),
        )

#3


2  

You can use MultiValueField and MultiWidget to get this behavior. You'll need to think about and modify the compress and decompress methods, but something like the following should get you part way there.

您可以使用MultiValueField和MultiWidget来获取此行为。您需要考虑并修改压缩和解压缩方法,但是类似下面的内容应该让您分道扬..

from django import forms
from crispy_forms.helper import FormHelper

class MyWidget(forms.MultiWidget):
    widgets = (forms.TextInput(), forms.TextInput())
    super(ExpirationDateWidget, self).__init__(widgets)

    def decompress(self, value):
        if value:
            return value.split('|')  # or however you combined the two values
        return [None, None]


class MyMultiField(forms.MultiValueField):
    def __init__(self, *args, **kwargs):
        self.widget = MyWidget(*args, **kwargs)

    def compress(self, data_list):
        return data_list[0] + '|' + data_list[1]  # or other logical compression


class MyForm(forms.Form):
    multi_field = MyMultiField()
    # other fields like category and category_new

    def __init__(self, *args, **kwargs):
        self.helper = FormHelper()
        self.helper.form_class = 'form-horizontal'
        self.helper.layout = Layout('multi_field', 'category', 'category_new')

This will result in something like:

这将导致类似于:

 <div id="div_id_multi_field" class="control-group">
     <label for="id_multi_field_0" class="control-label">Multi Field</label>
     <div class="controls">
         <input id="id_multi_field_0">
         <input id="id_multi_field_1">
     </div>
 </div>