2011-01-18 2 views
1

Привет, Я использую модельный набор, позволяющий моим пользователям редактировать свой фотоальбом. Я хочу поставить поле выбора радио на каждую фотографию с надписью «Установить как обложка», чтобы я мог обрабатывать все фотографии и находить того, кто должен быть обложкой альбома. Проблема в том, как я могу использовать поле с радиоприемником в составе набора форм и все еще держать его мутатором с остальными фотографиями? Это мой текущий код:Django: Использование окна выбора радиоприемника на модельных наборах моделей

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' 
     ) 

ответ

2

Я думаю, что ключевым здесь является то, что радио-кнопка не является фактически частью formset: это часть родительской формы. Это фактическая модель альбома, которая должна знать, какой из объектов Фото является обложкой. Итак, что вы хотите сделать, это отобразить каждый параметр из переключателя рядом со своей соответствующей строкой в ​​Photo formet - и это сложный бит, потому что Django не может отображать поля формы таким образом. Вам нужно будет создать HTML для каждой опции вручную.

Таким образом, учитывая эти формы, и предполагая, что модель Альбом имеет cover_image, которая является OneToOneField Фотографии:

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

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

в шаблоне вы могли бы сделать что-то вроде:

{% 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 %} 
1

Мне нравится чтобы иметь опрятный файл шаблона, и поэтому для этой цели я создал собственный виджет.

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)) 

Надеется, что это может помочь кому-то

0

На основе @Mikou ответа, вот мое более комплексное решение.

Для того, чтобы сохранить мой шаблон чистой и красивой, я использовал свой собственный виджет

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)) 

Моя форма объекта выглядит так, он будет автоматически выбирать объект, если поле 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(), 
    } 

Вот мой набор форм

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

Я отказался от обработки сохраненной части в форме, это действительно не стоит сложность, я думаю ... Таким образом, запасная часть находится в form_valid() в 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()) 
Смежные вопросы