Django形式的CSS样式

时间:2011-04-29 03:41:01

标签: css django django-forms

我想设计以下内容:

forms.py:

from django import forms

class ContactForm(forms.Form):
    subject = forms.CharField(max_length=100)
    email = forms.EmailField(required=False)
    message = forms.CharField(widget=forms.Textarea)

contact_form.html:

<form action="" method="post">
  <table>
    {{ form.as_table }}
  </table>
  <input type="submit" value="Submit">
</form>

例如,如何为subjectemailmessage设置 ID 以提供外部样式表到?

17 个答案:

答案 0 :(得分:150)

取自我的回答: How to markup form fields with <div class='field_type'> in Django

class MyForm(forms.Form):
    myfield = forms.CharField(widget=forms.TextInput(attrs={'class' : 'myfieldclass'}))

class MyForm(forms.ModelForm):
    class Meta:
        model = MyModel

    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)
        self.fields['myfield'].widget.attrs.update({'class' : 'myfieldclass'})

class MyForm(forms.ModelForm):
    class Meta:
        model = MyModel
        widgets = {
            'myfield': forms.TextInput(attrs={'class': 'myfieldclass'}),
        }

---编辑---
以上是对原始问题代码进行最简单的更改,以完成所要求的内容。如果您在其他地方重复使用该表单,它还可以防止您重复自己;如果你使用Django的as_table / as_ul / as_p表单方法,你的类或其他属性就可以正常工作。如果您需要完全控制完全自定义渲染,则为clearly documented

- 编辑2 ---
添加了一种更新的方法来为ModelForm指定widget和attrs。

答案 1 :(得分:85)

这可以使用自定义模板过滤器完成。考虑以这种方式渲染表单:

<form action="/contact/" method="post">
  {{ form.non_field_errors }}
  <div class="fieldWrapper">
    {{ form.subject.errors }}
    {{ form.subject.label_tag }}
    {{ form.subject }}
    <span class="helptext">{{ form.subject.help_text }}</span>
  </div>
</form>

form.subject是具有as_widget()方法的BoundField个实例。

您可以在 my_app / templatetags / myfilters.py 中创建自定义过滤器addclass

from django import template

register = template.Library()

@register.filter(name='addclass')
def addclass(value, arg):
    return value.as_widget(attrs={'class': arg})

然后应用您的过滤器:

{% load myfilters %}

<form action="/contact/" method="post">
  {{ form.non_field_errors }}
  <div class="fieldWrapper">
    {{ form.subject.errors }}
    {{ form.subject.label_tag }}
    {{ form.subject|addclass:'MyClass' }}
    <span class="helptext">{{ form.subject.help_text }}</span>
  </div>
</form>

form.subjects将使用MyClass CSS类进行渲染。

答案 2 :(得分:27)

如果您不想将任何代码添加到表单中(如@ shadfc的答案中的评论中所述),这当然是可能的,这里有两个选项。

首先,您只需在HTML中引用单独字段,而不是一次引用整个表单:

<form action="" method="post">
    <ul class="contactList">
        <li id="subject" class="contact">{{ form.subject }}</li>
        <li id="email" class="contact">{{ form.email }}</li>
        <li id="message" class="contact">{{ form.message }}</li>
    </ul>
    <input type="submit" value="Submit">
</form>

(请注意,我还将其更改为未排序的列表。)

其次,请注意outputting forms as HTML上的文档,Django:

  

字段ID,由...生成   将'id_'添加到字段名称。   id属性和标签是   默认包含在输出中。

您的所有表单字段都有唯一的 ID 。因此,您可以在CSS文件中引用 id_subject 来设置主题字段的样式。我应该注意,这是表单采用默认 HTML时的行为方式,只需要打印表单,而不是单个字段:

<ul class="contactList">
    {{ form }}  # Will auto-generate HTML with id_subject, id_email, email_message 
    {{ form.as_ul }} # might also work, haven't tested
</ul>

在输出表单时可以查看上一个链接以了解其他选项(您可以执行表格等)。

注意 - 我意识到这与向每个元素添加不同(如果你在Form中添加了一个字段,你也需要更新CSS) - 但它是很容易通过CSS中的 id 引用所有字段,如下所示:

#id_subject, #id_email, #email_message 
{color: red;}

答案 3 :(得分:11)

你可以这样做:

class ContactForm(forms.Form):
    subject = forms.CharField(max_length=100)
    subject.widget.attrs.update({'id' : 'your_id'})

希望有效。

Ignas

答案 4 :(得分:11)

根据this博文,您可以使用自定义模板过滤器向您的字段添加css类。

from django import template
register = template.Library()

@register.filter(name='addcss')
def addcss(field, css):
    return field.as_widget(attrs={"class":css})
  

将它放在你应用的templatetags /文件夹中,你现在就可以了

{{field|addcss:"form-control"}}

答案 5 :(得分:7)

您可以使用此库:https://pypi.python.org/pypi/django-widget-tweaks

它允许您执行以下操作:

{% load widget_tweaks %}
<!-- add 2 extra css classes to field element -->
{{ form.title|add_class:"css_class_1 css_class_2" }}

答案 6 :(得分:5)

你可以这样做:

<form action="" method="post">
    <table>
        {% for field in form %}
        <tr><td>{{field}}</td></tr>
        {% endfor %}
    </table>
    <input type="submit" value="Submit">
</form>

然后您可以将类/ ID添加到例如<td>标记中。您当然可以使用您想要的任何其他标签。以Working with Django forms为例,查看表单中每个field的可用内容({{field}}例如只输出输入标记,而不是标签等等。)

答案 7 :(得分:3)

我真的没看到这个......

https://docs.djangoproject.com/en/1.8/ref/forms/api/#more-granular-output

更细粒度的输出

as_p(),as_ul()和as_table()方法只是懒惰开发人员的快捷方式 - 它们不是表单对象可以显示的唯一方式。

类BoundField 用于显示Form实例的单个字段的HTML或访问属性。

此对象的 str ()(Python 2上的 unicode )方法显示此字段的HTML。

要检索单个BoundField,请使用字段名称作为关键字在表单上使用字典查找语法:

>>> form = ContactForm()
>>> print(form['subject'])
<input id="id_subject" type="text" name="subject" maxlength="100" />

要检索所有BoundField对象,请迭代表单:

>>> form = ContactForm()
>>> for boundfield in form: print(boundfield)
<input id="id_subject" type="text" name="subject" maxlength="100" />
<input type="text" name="message" id="id_message" />
<input type="email" name="sender" id="id_sender" />
<input type="checkbox" name="cc_myself" id="id_cc_myself" />

特定于字段的输出符合表单对象的auto_id设置:

>>> f = ContactForm(auto_id=False)
>>> print(f['message'])
<input type="text" name="message" />
>>> f = ContactForm(auto_id='id_%s')
>>> print(f['message'])
<input type="text" name="message" id="id_message" />

答案 8 :(得分:2)

您可能不需要覆盖表单类“__init__”,因为Django设置了name&amp; HTML id中的input个属性。你可以拥有这样的CSS:

form input[name='subject'] {
    font-size: xx-large;
}

答案 9 :(得分:2)

Django有一个非常容易安装和出色的工具,我用它来设置样式,它可以用于每个前端框架,如Bootstrap,Materialise,Foundation等。它被称为widget-tweaks文档:{{3 }}

  1. 您可以将它与Django的通用视图一起使用
  2. 或使用您自己的表格:
  3. 来自django导入表格

    class ContactForm(forms.Form):
        subject = forms.CharField(max_length=100)
        email = forms.EmailField(required=False)
        message = forms.CharField(widget=forms.Textarea)
    

    而不是使用默认值:

    {{ form.as_p }} or {{ form.as_ul }}
    

    您可以使用render_field属性以自己的方式编辑它,这样就可以像这个例子一样为您提供类似html的样式:

    template.html

    {% load widget_tweaks %}
    
    <div class="container">
       <div class="col-md-4">
          {% render_field form.subject class+="form-control myCSSclass" placeholder="Enter your subject here" %}
       </div>
       <div class="col-md-4">
          {% render_field form.email type="email" class+="myCSSclassX myCSSclass2" %}
       </div>
       <div class="col-md-4">
          {% render_field form.message class+="myCSSclass" rows="4" cols="6" placeholder=form.message.label %}
       </div>
    </div>
    

    此库让您有机会从后端将您的前端分开

答案 10 :(得分:1)

在Django 1.10中(也可能更早),您可以按照以下步骤进行操作。

型号:

state[payload.keys].faqs.push({ breed: '', name '' })

形式:

class Todo(models.Model):
    todo_name = models.CharField(max_length=200)
    todo_description = models.CharField(max_length=200, default="")
    todo_created = models.DateTimeField('date created')
    todo_completed = models.BooleanField(default=False)

    def __str__(self):
        return self.todo_name

模板:

class TodoUpdateForm(forms.ModelForm):
    class Meta:
        model = Todo
        exclude = ('todo_created','todo_completed')

答案 11 :(得分:1)

一种解决方案是在页面准备好后使用JavaScript添加所需的CSS类。例如,使用bootstrap类(jQuery用于简洁)样式化django表单输出:

<script type="text/javascript">
    $(document).ready(function() {
        $('#some_django_form_id').find("input[type='text'], select, textarea").each(function(index, element) {
            $(element).addClass("form-control");
        });
    });
</script>

这样可以避免将样式细节与业务逻辑混合在一起。

答案 12 :(得分:0)

编辑:另一种(稍好一点)做我建议的方式在这里得到解答:Django form input field styling

以上所有选项都很棒,我以为我会投入这个选项,因为它不同。

如果您想在表单上自定义样式,类等,可以在模板中输入与表单字段匹配的html输入。例如,对于CharField,(默认小部件是TextInput),假设你想要一个看起来像引导的文本输入。你会做这样的事情:

<input type="text" class="form-control" name="form_field_name_here">

只要你把表单字段名称与html name attribue匹配,(并且widget可能也需要匹配输入类型)当你运行时,Django将在该字段上运行所有相同的验证器validateform.is_valid()

设置标签,错误消息和帮助文本等其他内容的样式不需要太多解决方法,因为您可以执行form.field.error.as_text之类的操作,并根据需要设置样式。实际的字段是需要一些摆弄的字段。

我不知道这是最好的方式,还是我推荐的方式,但这是一种方式,对某人来说可能是对的。

这是样式表单的一个有用的演练,它包括SO上列出的大多数答案(比如在窗口小部件和小部件调整上使用attr)。 https://simpleisbetterthancomplex.com/article/2017/08/19/how-to-render-django-form-manually.html

答案 13 :(得分:0)

样式化窗口小部件实例

如果要使一个小部件实例看起来与另一个小部件实例不同,则在实例化小部件对象并将其分配给表单字段时可能需要指定其他属性(并可能向CSS文件添加一些规则)。

https://docs.djangoproject.com/en/2.2/ref/forms/widgets/

为此,请在创建窗口小部件时使用Widget.attrs参数:

class CommentForm(forms.Form):
    name = forms.CharField(widget=forms.TextInput(attrs={'class': 'special'}))
    url = forms.URLField()
    comment = forms.CharField(widget=forms.TextInput(attrs={'size': '40'}))

您还可以在表单定义中修改小部件:

class CommentForm(forms.Form):
    name = forms.CharField()
    url = forms.URLField()
    comment = forms.CharField()

    name.widget.attrs.update({'class': 'special'})
    comment.widget.attrs.update(size='40')

或者,如果未在表单上直接声明该字段(例如模型表单字段),则可以使用Form.fields属性:

class CommentForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['name'].widget.attrs.update({'class': 'special'})
        self.fields['comment'].widget.attrs.update(size='40')

然后Django将在渲染的输出中包括额外的属性:

>>> f = CommentForm(auto_id=False)
>>> f.as_table()
<tr><th>Name:</th><td><input type="text" name="name" class="special" required></td></tr>
<tr><th>Url:</th><td><input type="url" name="url" required></td></tr>
<tr><th>Comment:</th><td><input type="text" name="comment" size="40" required></td></tr>

答案 14 :(得分:0)

将您的表单编写为:

    class MyForm(forms.Form):
         name = forms.CharField(widget=forms.TextInput(attr={'class':'name'}))
         message = forms.CharField(widget=forms.Textarea(attr={'class':'message'}))

在您的HTML字段中执行以下操作:

{% for field in form %}
      <div class="row">
        <label for="{{ field.name}}">{{ field.name }}</label>{{ field }}
     </div>
{% endfor %}

然后在您的CSS中编写如下内容:

.name{
      /* you already have this class so create it's style form here */
}
.message{
      /* you already have this class so create it's style form here */
}
label[for='message']{
      /* style for label */
}

希望这个答案值得一试!请注意,您必须已编写视图才能呈现包含表单的HTML文件。

答案 15 :(得分:0)

我正在尝试使用此解决方案来保持整个应用程序的一致性:

def bootstrap_django_fields(field_klass, css_class):
    class Wrapper(field_klass):
        def __init__(self, **kwargs):
            super().__init__(**kwargs)

        def widget_attrs(self, widget):
            attrs = super().widget_attrs(widget)
            if not widget.is_hidden:
                attrs["class"] = css_class
            return attrs

    return Wrapper


MyAppCharField = bootstrap_django_fields(forms.CharField, "form-control")

然后,您不必在逐个表单的基础上定义CSS类,只需使用自定义表单字段即可。


从技术上讲,也可以在启动时重新定义Django的forms类,例如:

forms.CharField = bootstrap_django_fields(forms.CharField, "form-control")

然后,即使您不在直接控制的应用程序中,也可以全局设置样式。这似乎很粗略,所以我不确定是否可以推荐。

答案 16 :(得分:0)

对于更大的表单,而不是编写为每个字段分类的 css

class UserRegistration(forms.ModelForm):
   # list charfields

   class Meta:
      model = User
      fields = ('username', 'first_name', 'last_name', 'email', 'password', 'password2')

   def __init__(self, *args, **kwargs):
      super(UserRegistration, self).__init__(*args, **kwargs)
      for field in self.fields:
         self.fields[field].widget.attrs['class'] = 'form-control'