Django - Как применить CSS для набора моделей радиомодулей? [Дубликат]

Чтобы использовать методы и член объекта, вам сначала нужно создать этот объект. Если вы его не создали (переменная, которая должна содержать объект, не инициализируется), но вы пытаетесь использовать его методы или переменные, вы получите эту ошибку.

Иногда вы можете просто забыть инициализировать .

Отредактировано: new не может вернуть значение null, но исключение огня при ошибке. Давно это было на некоторых языках, но не больше. Спасибо @John Saunders за указание на это.

7
задан Nate 17 June 2011 в 00:52
поделиться

4 ответа

Ответ Антона работал, и на какое-то время был достойный ответ, но, к сожалению, он стал недостижимым. Итак, взяв сигнал из 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 %}. Намного легче позаботиться!

4
ответ дан Nate 3 September 2018 в 16:32
поделиться

Выбор должен быть в модели:

class RatherComplicatedModel(models.Model):
    BAR_CHOICES = (
        (0, "No Textbox"),
        (1, "One Textbox: "),
    )
    #some other stuff...
    bar = models.IntegerField(blank=True, null=True, choices=BAR_CHOICES)

Тогда просто:

class RatherComplicatedForm(forms.ModelForm):
    #various and sundry code...
    bar = forms.ChoiceField(widget=forms.RadioSelect(), 
                 choices=RatherComplicatedModel.BAR_CHOICES)
    class Meta:
        model = RatherComplicatedModel
3
ответ дан Paulo Scardine 3 September 2018 в 16:32
поделиться

Я сделал бы это путем подкласса RadioFieldRenderer и привязки его к пользовательскому виджету:

# forms.py
from django import forms
from django.forms.widgets import RadioSelect, RadioFieldRenderer
from django.template.loader import render_to_string
from myapp.models import RatherComplicatedModel


class MyRadioFieldRenderer(RadioFieldRenderer):
    def render(self):
        return render_to_string(
            'my_radio_widget.html',
                    {'field': self})


class MyRadioSelect(RadioSelect):
    renderer = MyRadioFieldRenderer


class RatherComplicatedForm(forms.ModelForm):
    RADIO_CHOICES = (
        ('none', "No Textbox"),
        ('one', "One Textbox: "),
    )
    rad = forms.ChoiceField(widget=MyRadioSelect(),choices=RADIO_CHOICES)

    class Meta:
        model = RatherComplicatedModel

Затем шаблон:

#my_radio_widget.html
<ul>
    {% for choice in field %}
        <li>
            <label for="id_{{ field.name }}_{{ forloop.counter0 }}">
                <input type="radio"
                       name="{{ field.name }}"
                       value="{{ choice.choice_value }}"
                       id="id_{{ field.name }}_{{ forloop.counter0 }}"
                       {% if field.value == choice.choice_value %}
                           checked='checked'
                       {% endif %}/>
                {{ choice.choice_label }}
            </label>
        </li>
    {% endfor %}
</ul>
2
ответ дан seddonym 3 September 2018 в 16:32
поделиться

Если я правильно понимаю вашу проблему, вы можете получить доступ к кортежу в шаблоне:

<ul>
    {# Assuming {{ field }} here is {{ form.rad }} #}
    {% for choice in field.field.choices %}
    <li>
        <label for="id_{{ field.html_name }}_{{ forloop.counter0 }}">
            <input type="radio"
                id="id_{{ field.html_name }}_{{ forloop.counter0 }}"
                value="{{ choice.0 }}"
                name="{{ field.html_name }}" />
            {{ choice.1 }}
            {% if choice.0 == 'one' %}
                {# Necessary field here #}
                {{ form.bar }}
            {% else %}
                No Textbox
            {% endif %}
        </label>
    </li>
    {% endfor %}
</ul>
5
ответ дан Tony 3 September 2018 в 16:32
поделиться