Câu hỏi thú vị và tôi nghĩ có lẽ đáng được chú ý hơn một chút trong tài liệu.
Dưới đây là một ví dụ từ a question I've just asked:
class DateSelectorWidget(widgets.MultiWidget):
def __init__(self, attrs=None, dt=None, mode=0):
if dt is not None:
self.datepos = dt
else:
self.datepos = date.today()
# bits of python to create days, months, years
# example below, the rest snipped for neatness.
years = [(year, year) for year in year_digits]
_widgets = (
widgets.Select(attrs=attrs, choices=days),
widgets.Select(attrs=attrs, choices=months),
widgets.Select(attrs=attrs, choices=years),
)
super(DateSelectorWidget, self).__init__(_widgets, attrs)
def decompress(self, value):
if value:
return [value.day, value.month, value.year]
return [None, None, None]
def format_output(self, rendered_widgets):
return u''.join(rendered_widgets)
What've tôi thực hiện?
- subclassed
django.forms.widgets.MultiWidget
- thực hiện một constructor tạo ra nhiều
widgets.WidgetName
widget trong một tuple . Điều này rất quan trọng vì lớp siêu sử dụng sự tồn tại của bộ dữ liệu này để xử lý một số thứ cho bạn.
- Đầu ra định dạng của tôi là thông qua, nhưng ý tưởng là bạn có thể thêm html tùy chỉnh tại đây nếu bạn muốn
- Tôi cũng đã thực hiện
decompress
vì bạn phải - bạn sẽ được chuyển các giá trị từ cơ sở dữ liệu trong một đối tượng value
. decompress
ngắt kết nối này để hiển thị trong tiện ích. Làm thế nào và những gì bạn làm ở đây là tùy thuộc vào bạn và phụ thuộc vào widget.
Những điều tôi không có, nhưng có thể có, overriden:
render
, đây là thực sự chịu trách nhiệm về render widget, vì vậy bạn chắc chắn cần phải gọi siêu Phương thức render nếu bạn phân lớp này. Bạn có thể thay đổi cách mọi thứ được hiển thị ngay trước khi kết xuất bằng cách phân lớp này.
Ví dụ, django markitup 's làm cho phương pháp:
def render(self, name, value, attrs=None):
html = super(MarkItUpWidget, self).render(name, value, attrs)
if self.auto_preview:
auto_preview = "$('a[title=\"Preview\"]').trigger('mouseup');"
else: auto_preview = ''
html += ('<script type="text/javascript">'
'(function($) { '
'$(document).ready(function() {'
' $("#%(id)s").markItUp(mySettings);'
' %(auto_preview)s '
'});'
'})(jQuery);'
'</script>' % {'id': attrs['id'],
'auto_preview': auto_preview })
return mark_safe(html)
value_from_datadict
- Xem câu hỏi của tôi here. value_from_datadict kéo giá trị được liên kết với tiện ích này ra khỏi từ điển dữ liệu của tất cả dữ liệu được gửi cùng với biểu mẫu này. Trong trường hợp multiwidget đại diện cho một trường duy nhất, bạn cần phải tạo lại giá trị đó từ nhiều tiện ích con của bạn, đó là cách dữ liệu sẽ được gửi.
_get_media
có thể hữu ích cho bạn nếu bạn muốn truy xuất phương tiện bằng cách sử dụng phương tiện truyền thông đại diện của django. Các chu trình thực hiện mặc định mà các widget yêu cầu cho media; nếu bạn phân lớp nó và đang sử dụng bất kỳ vật dụng ưa thích nào bạn cần gọi là siêu; nếu tiện ích của bạn cần bất kỳ phương tiện nào thì bạn cần thêm nó bằng cách sử dụng nó.
Ví dụ, django phụ tùng markitup 's thực hiện điều này:
def _media(self):
return forms.Media(
css= {'screen': (posixpath.join(self.miu_skin, 'style.css'),
posixpath.join(self.miu_set, 'style.css'))},
js=(settings.JQUERY_URL,
absolute_url('markitup/jquery.markitup.js'),
posixpath.join(self.miu_set, 'set.js')))
media = property(_media)
Một lần nữa, nó đang tạo ra một tuple các đường dẫn đến vị trí chính xác, cũng giống như phụ tùng của tôi đã tạo ra một tuple của widget trong __init__
.
Tôi nghĩ rằng hãy bao gồm nó cho các phần quan trọng của lớp MultiWidget
. Những gì bạn đang cố gắng làm phụ thuộc vào những gì bạn đã tạo ra/vật dụng bạn đang sử dụng, đó là lý do tại sao tôi không thể đi vào chi tiết dễ dàng. Tuy nhiên, nếu bạn muốn xem các lớp cơ sở cho chính mình và hãy xem các ý kiến, hãy xem the source.
Giải pháp này hơi bị hack, nhưng nội tuyến hơn với cách chúng tôi mong đợi truy cập các trường con trong mẫu. http://stackoverflow.com/questions/24866936/render-only-one-part-of-a-multiwidget-in-django – farthVader