【问题标题】:How to add custom styling to Forms created with Django CreateView如何为使用 Django CreateView 创建的表单添加自定义样式
【发布时间】:2017-06-12 06:05:58
【问题描述】:

我对 Django 很陌生。按照一些教程,我设法使用 Python 通用视图 (CreateView)

创建了一个表单

我有一个“问题”模型

class Question(models.Model):
    title = models.CharField(max_length=200)
    body = models.TextField(max_length=2000)
    category = models.CharField(max_length=50)
    votes = models.IntegerField(default=0)
    asked_date = models.DateTimeField(default=datetime.now)

使用这个模型我创建了一个视图类

class QuestionCreate(CreateView):
    model = Question
    fields = ['title', 'body', 'category']

这确实会生成一个漂亮的 HTML 表单。但是如何将 CSS 属性传递给每个字段?

【问题讨论】:

    标签: django


    【解决方案1】:

    我在基于 Bootstrap 框架的 Django 应用程序中遇到了类似的问题。我的第一次尝试:

    # views.py
    from django.views.generic.edit import UpdateView
    from . import models
    
    class ModuleUpdateView(UpdateView):
        model = models.Module
        fields = ['name', 'description', 'status']
    

    如下所示:

    确实不是很好!第二次尝试意味着为我的视图定义一个自定义 ModelForm 并应用其中的所有自定义:

    # forms.py
    from .models import Module
    
    class ModuleForm(forms.ModelForm):
        def __init__(self, *args, **kwargs):
            super(ModuleForm, self).__init__(*args, **kwargs)
            for visible in self.visible_fields():
                visible.field.widget.attrs['class'] = 'form-control'
    
        class Meta:
            model = Module
            fields = ['name', 'description', 'status']
    

    请注意__init__ 中的for 循环,它将form-control CSS 类添加到所有可见的表单字段。 form-control 的 CSS 样式由 Bootstrap 提供,因此我什至不必修改样式表。

    一旦我有了自定义的 ModelForm,我就可以如下重写我的 View 类:

    # views.py
    from django.views.generic.edit import UpdateView
    from . import forms, models
    
    class ModuleUpdateView(UpdateView):
        model = models.Module
        form_class = forms.ModuleForm
    

    您可以在下面看到结果。

    好多了!

    希望对您有所帮助,如有问题,请随时发表评论。

    【讨论】:

      【解决方案2】:

      您可以为 Question 编写一个模型表单并将其传递给创建视图,

      class QuestionForm(forms.ModelForm):
      
          class Meta:
              model = Question
              fields = ('myfield1', 'myfield2) 
              widgets = {
              'myfield1': forms.TextInput(attrs={'class': 'myfieldclass'}),
              }
      

      或者你可以重写init方法来为每个字段指定一个特定的类,

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

      然后,将其传递给CreateView的属性form_class

      class QuestionCreate(CreateView):
          model = Question
          form_class = QuestionForm
      

      【讨论】:

        【解决方案3】:
        class FooForm(forms.ModelForm):
            def __init__(self, *args, **kwargs):
                super(FooForm, self).__init__(*args, **kwargs)
                self.fields['field1'].widget.attrs = { 'class': 'fooclass' }
        
            class Meta:
                model = FooModel
                fields = ['field1', 'field2']
        

        您不能直接将css 添加到CreateView,因为您需要创建ModelForm 并在创建视图中使用form_class = FooForm,在此ModelForm 中您可以为字段使用特定类并根据需要使用 css 设置样式

        【讨论】:

        • 相当不便吧..人们会认为将有一种简单的方法来设置伴随createview的html表单的样式,调试表单对象有包含css和js列表的媒体字段虽然是空的,也许有办法添加一些样式
        【解决方案4】:

        如果我们想为渲染的表单添加一些引导样式,我们可以使用 django-crispy-forms:

        pip install django-crispy-forms
        

        然后将“crispy-forms”添加到已安装的应用程序中。
        在表单模板页面中加载crispy_form_tags,而不是使用{{form}},使用{{form|crispy}}。

        Crispy 的文档。

        【讨论】:

          【解决方案5】:

          最好的方法是重写get_form 函数。

          class QuestionCreate(CreateView):
              model = Question
              fields = ['title', 'body', 'category', 'MyField']
          
              def get_form(self, form_class=None):
                  form = super(QuestionCreate, self).get_form(form_class)
                  form['MyField'].field.widget.attrs.update({'class' : 'MyClass'})
                  return form
          

          或者,如果您想将属性添加到所有字段,您可以使用 for 循环,如下所示:

          class QuestionCreate(CreateView):
              model = Question
              fields = ['title', 'body', 'category', 'MyField']
          
              def get_form(self, form_class=None):
                  form = super(OPCCreateView, self).get_form(form_class)
                  for visible in form.visible_fields():
                      visible.field.widget.attrs.update({'class' : 'MyClass'})
                  return form
          

          【讨论】:

            猜你喜欢
            • 2020-03-15
            • 2016-03-25
            • 2017-12-19
            • 1970-01-01
            • 2010-12-26
            • 1970-01-01
            • 2012-04-12
            • 2017-06-17
            • 1970-01-01
            相关资源
            最近更新 更多