Ответ Антона работал, и на какое-то время был достойный ответ, но, к сожалению, он стал недостижимым. Итак, взяв сигнал из diff , прикрепленный к билету django # 9230 , я просто обезглавил django.forms.forms.BoundField
from django import forms
def MonkeyPatchDjangoFormsBoundField():
def prepare_widget_render(self, widget=None, attrs=None, only_initial=False):
"""
Prepare the data needed for the widget rendering.
"""
if not widget:
widget = self.field.widget
attrs = attrs or {}
auto_id = self.auto_id
if auto_id and 'id' not in attrs and 'id' not in widget.attrs:
if not only_initial:
attrs['id'] = auto_id
else:
attrs['id'] = self.html_initial_id
if not only_initial:
name = self.html_name
else:
name = self.html_initial_name
return widget, name, attrs
def as_widget(self, widget=None, attrs=None, only_initial=False):
"""
Renders the field by rendering the passed widget, adding any HTML
attributes passed as attrs. If no widget is specified, then the
field's default widget will be used.
"""
widget, name, attrs = self.prepare_widget_render(widget, attrs, only_initial)
return widget.render(name, self.value(), attrs=attrs)
def __iter__(self):
"""
Check if current widget has a renderer and iterate renderer.
"""
widget, name, attrs = self.prepare_widget_render()
if not hasattr(widget, 'get_renderer'):
raise Exception, "Can not iterate over widget '%s'" % widget.__class__.__name__
renderer = widget.get_renderer(name, self.value(), attrs=attrs)
for entry in renderer:
yield entry
def __getitem__(self,idx):
"""
Tries to use current widget's renderer, and then check attribute.
"""
widget, name, attrs = self.prepare_widget_render()
try:
renderer = widget.get_renderer(name, self.value(), attrs=attrs)
return renderer[idx]
except Exception:
return getattr(self,idx)
forms.forms.BoundField.prepare_widget_render = prepare_widget_render
forms.forms.BoundField.as_widget = as_widget
forms.forms.BoundField.__iter__ = __iter__
forms.forms.BoundField.__getitem__ = __getitem__
Это позволило мне иметь доступ к радиовводам напрямую, используя {{ form.field.0.tag }}
или через итерацию - {% for radio in form.field %} {{ radio.tag }} {% endfor %}
. Намного легче позаботиться!
Это - потому что к любому повторяемому можно присоединиться, не только перечисляет, но и результатом и "столяром" всегда являются строки.
, Например:
import urllib2
print('\n############\n'.join(
urllib2.urlopen('http://data.stackexchange.com/users/7095')))
Поскольку join()
метод находится в строковом классе вместо класса списка?
я соглашаюсь, что это выглядит забавным.
См. http://www.faqs.org/docs/diveintopython/odbchelper_join.html :
Исторический очерк. , Когда я сначала изучил Python, я ожидал, что соединение будет методом списка, который возьмет разделитель в качестве аргумента. Много людей чувствует то же самое, и there’s история метода соединения. До Python 1.6 строковые didn’t имеют все эти полезные методы. Был отдельный строковый модуль, который содержал все строковые функции; каждая функция взяла строку в качестве своего первого аргумента. Функции считали достаточно важными для помещения на сами строки, которые имели смысл для функций как более низкий, верхнее, и разделяли. Но многие жесткие Python программисты возразили против нового метода соединения, утверждая, что это должен быть метод списка вместо этого, или что это, перемещение shouldn’t вообще, но просто остается частью старого строкового модуля (который все еще имеет много полезного материала в нем). Я использую новый метод соединения исключительно, но Вы будете видеть код, написанный так или иначе, и если он действительно беспокоит Вас, можно использовать старую функцию string.join вместо этого.
---Mark Pilgrim, Погружение в Python
Я соглашаюсь, что это парадоксально сначала, но существует серьезное основание. Соединение не может быть методом списка потому что:
существует на самом деле два метода соединения (Python 3.0):
>>> b"".join
<built-in method join of bytes object at 0x00A46800>
>>> "".join
<built-in method join of str object at 0x00A28D40>
, Если бы соединение было методом списка, то оно должно было бы осмотреть свои аргументы для решения который из них звонить. И Вы не можете присоединиться к байту и ул. вместе, таким образом, способ, которым у них есть он теперь, имеет смысл.
Думайте о нем как о естественной ортогональной операции для разделения.
я понимаю, почему это применимо к чему-либо повторяемому и так не может легко быть реализовано всего в списке.
Для удобочитаемости, я хотел бы видеть его на языке, но я не думаю, что это на самом деле выполнимо - если бы iterability были интерфейсом затем, то это могло бы быть добавлено к интерфейсу, но это - просто конвенция и таким образом, нет никакого центрального способа добавить его к набору вещей, которые повторяемы.
Прежде всего, потому что результатом someString.join()
является строка.
последовательность (список или кортеж или безотносительно) не появляется в результате, просто строка. Поскольку результатом является строка, он имеет смысл как метод строки.
Переменные my_list
и "-"
являются оба объектами. А именно, они - экземпляры классов list
и str
, соответственно. Эти join
функция принадлежит классу str
. Поэтому синтаксис "-".join(my_list)
используется, потому что объект "-"
берет my_list
в качестве входа.