Django: Using Radio select box on model formsets

眉间皱痕 提交于 2019-12-08 06:35:35

问题


Hey, I'm using a model formset to let my users edit their photo album. I want to put a Radio select box on every photo saying "Set as cover image" so that I can process all the photos and find the one who should be album cover. The problem is how can I a field with radio select on to the formset and still keep it mutal with the rest of the photos? This is my current code:

class ProjectGalleryForm(forms.ModelForm):
    remove_photo = forms.BooleanField()
    # set_as_cover_image = .... ?? <-- what to put?
    class Meta:
        model = Photo
        exclude = (
            'effect',
            'caption',
            'title_slug',
            'crop_from',
            'is_public',
            'slug',
            'tags'
        )

回答1:


I think the key here is that the radio button is not actually part of the formset: it's part of the parent form. It's the actual Album model that needs to know which of the Photo objects is the cover image. So what you want to do is to display each option from the radio button alongside its corresponding line in the Photo formset - and that's the tricky bit, because Django can't render form fields in that way. You'll need to produce the HTML for each option manually.

So, given these forms, and assuming the Album model has a cover_image which is a OneToOneField to Photo:

class AlbumForm(forms.modelForm):
    class Meta:
        model = Album

photo_formset = forms.inlineformset_factory(Album, Photo, form=ProjectGalleryForm)

in the template you would do something like:

{% for photo_form in photo_formset %}
    <tr><td>
    {% if photo_form.instance.pk %}
        <input type="radio" id="id_cover_image_{{ forloop.counter }}" name="cover_image" value="{{ photo_form.instance.pk }}">
        <label for="id_cover_image_{{ forloop.counter }}">Use as cover image</label>
    {% endif %>
    </td><td>{{ photo_form.as_p }}</td>
    </tr>
{% endfor %}



回答2:


I like to have the a neat template file and therefore, I made a custom widget for this purpose.

class SingleRadioInput(Input):

    input_type = 'radio'
    def render(self, value, checked, attrs=None):
        output = []
        if value:
            is_cover = ''
            if checked : is_cover = 'checked'
            output.append(
                ('<input type="radio" name="inline" value="%s" %s/>') 
                % (value, is_cover)
            )

        return mark_safe(u''.join(output))

Hope it can help someone




回答3:


Based on @Mikou answer, here is my more comprehensive solution.

In order to keep my template clean and pretty, I used a custom widget

class SingleRadioInput(forms.widgets.Input):
input_type = 'radio'
def render(self, name, value, attrs=None):
    final_attrs = self.build_attrs(attrs, type=self.input_type)
    output = []
    if name:
        is_checked = ''
        if value:
            is_checked = 'checked'
        output.append(
            ('<input id="%s" type="radio" name="%s" value="%s" %s/>')
            % (final_attrs['id'], final_attrs['name'], final_attrs['instance_id'], is_checked )
        )
    return mark_safe(u''.join(output))

My object form looks like that, it will auto select the object if the field default == True

class ObjectForm(forms.ModelForm):

def __init__(self, *args, **kwargs):
    super(ObjectForm, self).__init__(*args, **kwargs)
    self.fields['default'].widget.attrs.update({'instance_id': self.instance.id, 'name': 'default'})
    if self.instance.default:
        self.fields['default'].widget.attrs.update({'value': True})


class Meta:
    model = MyModel
    fields = ['default']
    widgets = {
        'default': SingleRadioInput(),
    }

Here is my formset

ProductReferenceFormset = inlineformset_factory(ParentModel, MyModel,
                                            form=ObjectForm,
                                            extra=0, can_delete=False, can_order=False)

I gave up handling the save part in the form, it is really not worth the complexity I think... So the save part is in the form_valid() in the View

def form_valid(self, form, price_form):
    form.save()
    # save the default radio
    MyModel.objects.filter(parent=self.object).update(default=False)
    MyModel.objects.filter(id=self.request.POST.get('default')).update(default=True)

    return HttpResponseRedirect(self.get_success_url())



回答4:


Qualification:

<option value='10th' {% if '10th' in i.qf %} selected='select' {% endif %}>10th</option>
<option value='12th' {% if '12th' in i.qf %} selected='select' {% endif %}>12th</option>
<option value='graduted' {% if 'Graduated' in i.qf %} selected='select' {% endif %}>Graduated</option>
 </select>
<br><br>


来源:https://stackoverflow.com/questions/4730161/django-using-radio-select-box-on-model-formsets

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!