Django Forms'da css sınıfını tanımlama


192

Bir formum olduğunu varsayın

class SampleClass(forms.Form):
    name = forms.CharField(max_length=30)
    age = forms.IntegerField()
    django_hacker = forms.BooleanField(required=False)

Benim işlenmiş sayfamda sınıfa dayalı jQuery kullanabilirsiniz böylece her alanda css sınıfları tanımlamak için bir yolu var mı?

El ile formu oluşturmak zorunda değil umuyordum.



10
@ skyl Ben bunu django belgelerinde bulmak kolay olmadığını bir gösterge olarak alacaktı. Göz attım ve birkaç google araması da yaptım ve bulamadım, bu yüzden soru için memnunum ve benim oyumu alır.
Nils

Eski bir iş parçacığı biliyorum ama Django form alanlarında artık bir id_fieldname sınıfı var.
ratsimihah

1
Mevcut alan sınıflarına saygı gösterirken şablon içindeki form alanı için sınıfları nasıl tanımlayacağınızla ilgili bu cevaba bakınız
dimyG

Yanıtlar:


182

Python kodunda değişiklik gerektirmeyen ve böylece tasarımcılar ve bir kerelik sunum değişiklikleri için daha iyi olan başka bir çözüm: django-widget-tweaks . Umarım biri faydalı bulur.


61
Sadece aklı başında çözüm olduğunu söylemeliyim. Teşekkür ederim!. Python kodu ve özellikle form tanımında, stil için şeyler koymak için son yer - bunlar kesinlikle şablonlara ait.
Boris Chervenkov

5
Bu harika bir kütüphane! Bu cevabın dibine gömülmesi bir utanç.
Chris Lacasse

1
Tasarımcılar için harika! :-)
hobbes3

1
Mükemmel! Bunları yapmak için bazı filtreler geliştirmiştim, ancak bu proje çok daha güçlü. Teşekkürler!
msbrogli

1
aslında Jinja2 için de çalışıyor :-) Güvenli fileter sırasını değiştirdim ve kolon {{myform.email | add_class ("css_class_1 css_class_2") | safe}} yerine parantez ekledim. Bunu yazdığınız için teşekkürler. Django'nun bir parçası olmalı.
David Dehghan


78

Sınıftaki alanları bildirdikten sonra widget'lara sınıf tanımları eklemek için başka bir çözüm.

def __init__(self, *args, **kwargs):
    super(SampleClass, self).__init__(*args, **kwargs)
    self.fields['name'].widget.attrs['class'] = 'my_class'

4
ModelForms için, kullanılan varsayılan form alanının farkında olmanız gerekmediğinden ve çalışma zamanı koşullarına göre dinamik olarak farklı sınıflar ayarlayabildiğiniz için bu genellikle daha iyidir. Meta kodlama hacklerinden daha temiz ...
Daniel Naab

1
Bu, bir formdaki her alan için bir girdi istediğinizi varsayar, ki bu genellikle durum böyle değildir. Bir form bir modele bağlı olmak zorunda değildir - birçok modele bağlı olabilir. Model alanlarının ve form alanlarının 1: 1 ilişkisine sahip olması durumunda, evet, ModelForm çok daha iyi bir seçimdir.
ashchristopher

44

Django-widget-tweaks kullanın , kullanımı kolaydır ve oldukça iyi çalışır.

Aksi takdirde, bu özel bir şablon filtresi kullanılarak yapılabilir.

Formunuzu şu şekilde oluşturduğunuzu düşünürsek:

<form action="/contact/" method="post">
    {{ form.non_field_errors }}
    <div class="fieldWrapper">
        {{ form.subject.errors }}
        <label for="id_subject">Email subject:</label>
        {{ form.subject }}
    </div>
</form>

form.subject, as_widget yöntemine sahip bir BoundField örneğidir .

"my_app / templatetags / myfilters.py" klasöründe özel bir "addcss" filtresi oluşturabilirsiniz

from django import template

register = template.Library()

@register.filter(name='addcss')
def addcss(value, arg):
    css_classes = value.field.widget.attrs.get('class', '').split(' ')
    if css_classes and arg not in css_classes:
        css_classes = '%s %s' % (css_classes, arg)
    return value.as_widget(attrs={'class': css_classes})

Ardından filtrenizi uygulayın:

{% load myfilters %}
<form action="/contact/" method="post">
    {{ form.non_field_errors }}
    <div class="fieldWrapper">
        {{ form.subject.errors }}
        <label for="id_subject">Email subject:</label>
        {{ form.subject|addcss:'MyClass' }}
    </div>
</form>

form.subjects daha sonra "MyClass" css sınıfıyla oluşturulur.

Umarım bu yardım.

DÜZENLEME 1

  • Göre Filtreyi güncelle dimyG bireyin cevap

  • Django-widget-tweak bağlantısı ekle

DÜZENLEME 2

  • Filtreyi Bhyd adlı kullanıcının yorumuna göre güncelle

3
Bu harika! KURU ve ekran katmanını kontrol katmanından ayırıyor. Benden +1!
alekwisnia

1
Ancak, şimdi bir dezavantaj fark ettim. Widget attr'lerinde sınıfı tanımlarsam, bu 'addcss' filtresi tarafından geçersiz kılınırlar. Bunu nasıl birleştireceğiniz hakkında bir fikriniz var mı?
alekwisnia

1
Yani, as_widget () attrs geçersiz kılar. Mevcut attreleri kullanmasını ve bunları yenisiyle genişletmesini nasıl sağlayabilirim?
alekwisnia

Mevcut alan sınıflarına nasıl saygı gösterileceğine dair bu cevaba bakınız
dimyG

get('class', None).split(' ')etiket yoksa başarısız olur değil sınıf özniteliği olarak Nonedöndürülür. Bunu değiştirme get('class', '').split(' ')eserleri
dtasev

32

Yöntemin genişletilmesi docs.djangoproject.com adresine işaret etti:

class MyForm(forms.Form): 
    comment = forms.CharField(
            widget=forms.TextInput(attrs={'size':'40'}))

Her alan için yerel widget türünü bilmek zahmetli olduğunu düşündüm ve sadece bir form alanına bir sınıf adı koymak için varsayılan geçersiz kılmak komik düşündüm. Bu benim için işe yarıyor gibi görünüyor:

class MyForm(forms.Form): 
    #This instantiates the field w/ the default widget
    comment = forms.CharField()

    #We only override the part we care about
    comment.widget.attrs['size'] = '40'

Bu benim için biraz daha temiz görünüyor.


Bu, yıllar önce, diğerlerinin söylediği şeydir, ancak talep edilen 'sınıf' yerine 'boyut' ile yapıyorsunuz.
Chris Morgan

3
@Chris Morgan Aslında, Form bildiriminde "comment.widget.attrs" kullanılmasını öneren ilk kişi o ( init ile uğraşmak veya görünümde yapmak yerine ).
DarwinSurvivor

29

Belirli bir sınıf miras formda bulunan tüm alanları isterseniz, sadece bir üst sınıf, o devralır tanımlamak forms.ModelFormve sonra ondan devralan

class BaseForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(BaseForm, self).__init__(*args, **kwargs)
        for field_name, field in self.fields.items():
            field.widget.attrs['class'] = 'someClass'


class WhateverForm(BaseForm):
    class Meta:
        model = SomeModel

Bu, 'form-control'sınıfı, kod çoğaltması eklemeden, uygulamamın tüm formlarındaki tüm alanlara otomatik olarak eklememe yardımcı oldu.


1
Lütfen sınıf isimlerini büyük harfle başlatın (ayrıca, BaseForm bunun için çok daha iyi bir isim gibi görünüyor)
Alvaro

16

İşte görünümde değiştirmek için basit bir yol. şablona geçmeden hemen önce görünümde ekleyin.

form = MyForm(instance = instance.obj)
form.fields['email'].widget.attrs = {'class':'here_class_name'}

14

Sınıfları formunuza aşağıdaki gibi eklemeniz yeterlidir.

class UserLoginForm(forms.Form):
    username = forms.CharField(widget=forms.TextInput(
        attrs={
        'class':'form-control',
        'placeholder':'Username'
        }
    ))
    password = forms.CharField(widget=forms.PasswordInput(
        attrs={
        'class':'form-control',
        'placeholder':'Password'
        }
    ))

5

Yukarıda tüm alanlara aynı sınıfı verecek bir varyasyon var (örn. Jquery güzel yuvarlak köşeler).

  # Simple way to assign css class to every field
  def __init__(self, *args, **kwargs):
    super(TranslatedPageForm, self).__init__(*args, **kwargs)
    for myField in self.fields:
      self.fields[myField].widget.attrs['class'] = 'ui-state-default ui-corner-all'

5

Bunu deneyebilirsiniz ..

class SampleClass(forms.Form):
  name = forms.CharField(max_length=30)
  name.widget.attrs.update({'class': 'your-class'})
...

Daha fazla bilgi için: Django Widget'ları


2

Şablondaki bir formun alanına (view.py veya form.py içinde değil) bir sınıf eklemek istediğinizde, örneğin 3. taraf uygulamalarını görünümlerini geçersiz kılmaksızın değiştirmek istediğiniz durumlarda, ardından açıklandığı gibi bir şablon filtresi içinde Charlesthk cevap çok uygundur. Ancak bu yanıtta şablon filtresi, alanın sahip olabileceği tüm sınıfları geçersiz kılar.

Bunu düzenleme olarak eklemeye çalıştım, ancak yeni bir cevap olarak yazılması önerildi.

İşte, alanın mevcut sınıflarına saygı duyan bir şablon etiketi:

from django import template

register = template.Library()


@register.filter(name='addclass')
def addclass(field, given_class):
    existing_classes = field.field.widget.attrs.get('class', None)
    if existing_classes:
        if existing_classes.find(given_class) == -1:
            # if the given class doesn't exist in the existing classes
            classes = existing_classes + ' ' + given_class
        else:
            classes = existing_classes
    else:
        classes = given_class
    return field.as_widget(attrs={"class": classes})

Önerin için teşekkürler. Cevabımı buna göre daha "pitonik" bir yaklaşımla düzenledim.
Charlesthk

büyük !!, aradığım şey bu
ugali yumuşak

1

Görüldüğü gibi bunu form yapıcısında ( init işlevi) veya form sınıfı başlatıldıktan sonra yapabilirsiniz. Kendi formunuzu yazmıyorsanız ve bu form başka bir yerden geliyorsa bu bazen gereklidir -

def some_view(request):
    add_css_to_fields = ['list','of','fields']
    if request.method == 'POST':
        form = SomeForm(request.POST)
        if form.is_valid():
            return HttpResponseRedirect('/thanks/')
    else:
        form = SomeForm()

    for key in form.fields.keys():
        if key in add_css_to_fields:
            field = form.fields[key]
            css_addition = 'css_addition '
            css = field.widget.attrs.get('class', '')
            field.widget.attrs['class'] = css_addition + css_classes

    return render(request, 'template_name.html', {'form': form})

1

Django Çıtır Formlarını da kullanabilirsiniz , Bootstrap veya Foundation gibi bazı CSS çerçevelerini kullanmak istemeniz durumunda formları tanımlamak için harika bir araçtır. Ve orada form alanlarınız için sınıfları belirtmek kolaydır.

Form sınıfınız şu şekilde:

from django import forms

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Div, Submit, Field
from crispy_forms.bootstrap import FormActions

class SampleClass(forms.Form):
    name = forms.CharField(max_length=30)
    age = forms.IntegerField()
    django_hacker = forms.BooleanField(required=False)

    helper = FormHelper()
    helper.form_class = 'your-form-class'
    helper.layout = Layout(
        Field('name', css_class='name-class'),
        Field('age', css_class='age-class'),
        Field('django_hacker', css-class='hacker-class'),
        FormActions(
            Submit('save_changes', 'Save changes'),
        )
    )
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.