는 내 질문에 대한 답을 찾기 위해 관리했습니다 내가 후대를 위해 여기를 게시하도록하겠습니다. 레이블 클래스의 경우 나는 here과 here (사용자의 답변 : 2732686)이라는 영감을 받았습니다. 첫 번째 링크는 런타임에 BoundField
클래스의 label_tag
메서드를 재정의 할 것을 제안합니다. 그것은 제 2의 링크에서 제안 된 것보다 덜 장황한 솔루션이지만, 프로젝트 전체에 걸친 해킹을 들었을 때 권장하지는 않습니다. 여기서는 레이블의 두 번째 링크에서 제안 된대로 장고의 하위 클래스 매니아를 따릅니다. 프로젝트에서
settings.py, 추가
# Default css classes for widgets and labels
DEFAULT_CSS = {
'error': 'w3-panel w3-red', # displayed in the label
'errorlist': 'w3-padding-8 w3-red', # encloses the error list
'required': 'w3-text-indigo', # used in the label and label + input enclosing box. NB: w3-validate only works if the input precedes the label!
'label': 'w3-label',
'Textarea': 'w3-input w3-border',
'TextInput': 'w3-input w3-border',
'Select': 'w3-select w3-border',
}
NB를 : 떨어져 4 첫번째 키,에서 키 장고의 위젯 이름과 일치해야합니다. 에서
당신의 forms.py (또는 다른 곳에), 추가 : 당신은 단순히 DefaultCssModelForm
및 DefaultCssForm
대신 ModelForm
및 Form
를 서브 클래 싱,
그런 다음 프로젝트 이름으로 <MY_PROJECT>
대체 :
from django.forms import ModelForm, inlineformset_factory, Form, BoundField
from django.forms.utils import ErrorList
from django.utils.html import format_html, force_text
from django.conf import settings
class CustErrorList(ErrorList):
# custom error list format to use defcss
def __str__(self):
return self.as_div()
def as_div(self):
if not self:
return ''
return format_html('<div class="{}">{}</div>',
settings.DEFAULT_CSS['errorlist'],
' '.join([ force_text(e) for e in self ])
)
class CustBoundField(BoundField):
# overload label_tag to include default css classes for labels
def label_tag(self, contents=None, attrs=None, label_suffix=None):
newcssclass = settings.DEFAULT_CSS['label']
if attrs is None:
attrs = {}
elif 'class' in attrs:
newcssclass = ' '.join([ attrs['class'], newcssclass ]) # NB: order has no impact here (but it does in the style sheet)
attrs.update({ 'class': newcssclass })
# return the output of the original method with the modified attrs
return super(CustBoundField, self).label_tag(contents, attrs, label_suffix)
def custinit(self, subclass, *args, **kwargs):
# overload Form or ModelForm inits, to use default CSS classes for widgets
super(subclass, self).__init__(*args, **kwargs)
self.error_class = CustErrorList # change the default error class
# Loop on fields and add css classes
# Warning: must loop on fields, not on boundfields, otherwise inline_formsets break
for field in self.fields.values():
thiswidget = field.widget
if thiswidget .is_hidden:
continue
newcssclass = settings.DEFAULT_CSS[ thiswidget.__class__.__name__ ]
thisattrs = thiswidget.attrs
if 'class' in thisattrs:
newcssclass = ' '.join([ thisattrs['class'], newcssclass ]) # NB: order has no impact here (but it does in the style sheet)
thisattrs.update({ 'class': newcssclass })
def custgetitem(self, name):
# Overload of Form getitem to use the custom BoundField with
# css-classed labels. Everything here is just a copy of django's version,
# apart from the call to CustBoundField
try:
field = self.fields[name]
except KeyError:
raise KeyError(
"Key '%s' not found in '%s'. Choices are: %s." % (
name,
self.__class__.__name__,
', '.join(sorted(f for f in self.fields)),
)
)
if name not in self._bound_fields_cache:
self._bound_fields_cache[name] = CustBoundField(self, field, name)
# In the original version, field.get_bound_field is called, but
# this method only calls BoundField. It is much easier to
# subclass BoundField and call it directly here
return self._bound_fields_cache[name]
class DefaultCssModelForm(ModelForm):
# Defines the new reference ModelForm, with default css classes
error_css_class = settings.DEFAULT_CSS['error']
required_css_class = settings.DEFAULT_CSS['required']
def __init__(self, *args, **kwargs):
custinit(self, DefaultCssModelForm, *args, **kwargs)
def __getitem__(self, name):
return custgetitem(self, name)
class DefaultCssForm(Form):
# Defines the new reference Form, with default css classes
error_css_class = settings.DEFAULT_CSS['error']
required_css_class = settings.DEFAULT_CSS['required']
def __init__(self, *args, **kwargs):
custinit(self, DefaultCssForm, *args, **kwargs)
def __getitem__(self, name):
return custgetitem(self, name)
NB를 양식을 정의 할 때. formsets
의 경우이 클래스를 기본 클래스로 사용하십시오.설명 :
class MyForm(DefaultCssModelForm):
class Meta:
model = MyModel
fields = '__all__'
MyFormSet = inlineformset_factory(..., ..., form=DefaultCssModelForm, ...)