2012-05-13 3 views
1

自分のDjangoアプリケーション用のカスタムウィジェットを書いて、選択した複数のウィジェット(決してそれらのものが気に入らなかった)でTwitter Bootstrapのボタングループに接続しました。 1つのことを除いては、うまく動作します。データベースオブジェクトからフォームをインスタンス化すると、値は塗りつぶされません。django:私のカスタムウィジェットがデータベースオブジェクトからの値で埋められないのはなぜですか?

実際に困惑しているのは、request.POSTをコンストラクタに渡してフォームを作成するときに、これらのウィジェットを作成するということです。これは、データベースオブジェクトからPOSTオブジェクトを除いてフォームが埋められる方法とは異なりますが、そこからどこに行くのかは分かりません。

がここにウィジェットです:あなたが混乱している場合には

from itertools import chain 
from django.forms.util import flatatt 
from django.forms.widgets import CheckboxSelectMultiple 
from django.utils.encoding import force_unicode 
from django.utils.html import conditional_escape 
from django.utils.safestring import mark_safe 

# todo-devon Values are not preserved with object instances 
class BootstrapButtonSelect(CheckboxSelectMultiple): 

    def __init__(self, attrs=None, all=False, none=False, classes=[], layout='horizontal'): 
     """ 
     Optional arguments for creating a BootstrapButtonSelect widget. Default settings are in brackets. 

     all=True/[False] 
     Adds a button to select all options when set to True. 

     none=True[False] 
     Adds a button to select none of the options when set to True. 

     classes=[] 
     A list of strings which adds CSS classes to the buttons making up the button select widget. The btn class is already included. Examples: 'btn-large', 'btn-primary' 

     layout=['horizontal'] 
     Sets the layout of the button select widget to 'horizontal' or 'vertical' (Not yet implemented. All groups are currently vertical.) 
     """ 
     super(BootstrapButtonSelect, self).__init__(attrs) 
     self.all = all 
     self.none = none 
     self.layout = layout 

     if classes: 
      self.classes = u' %s' % u' '.join(classes) 
     else: 
      self.classes = u'' 


    def render(self, name, value, attrs=None, choices=()): 
     """ 
     Builds button group and select list for widget 
     """ 
     # todo-devon Add code for horizontal layout 
     if value is None: value = [] 
     has_id = attrs and 'id' in attrs 
     final_attrs = self.build_attrs(attrs, name=name) 

     # Create the select multiple widget 
     select_output = [u'<select class="button-toggles" id="%s" multiple="multiple"%s>' % (name, flatatt(final_attrs),)] 
     for i, (option_value, option_label) in enumerate(chain(self.choices, choices)): 
      # If an ID attribute was given, add a numeric index as a suffix, 
      # so that the checkboxes don't all have the same ID attribute. 
      if has_id: 
       final_attrs = dict(final_attrs, id='%s_%s' % (attrs['id'], i,)) 
      option_value = force_unicode(option_value) 
      option_label = conditional_escape(force_unicode(option_label)) 
      if option_value in value: 
       select_output.append(u'<option value="%s" selected="selected">%s</label>' % (option_value, option_label)) 
      else: 
       select_output.append(u'<option value="%s">%s</label>' % (option_value, option_label)) 
     select_output.append('</select>') 
     select_output = u'\n'.join(select_output) 

     # Create the button group 
     button_output = [u'<div class="btn-select-vertical span3 hidden-phone" id="%s" data-toggle="buttons-checkbox">' % name] 
     for i, (option_value, option_label) in enumerate(chain(self.choices, choices)): 
      # If an ID attribute was given, add a numeric index as a suffix, 
      # so that the checkboxes don't all have the same ID attribute. 
      if has_id: 
       final_attrs = dict(final_attrs, id='%s_%s' % (attrs['id'], i,)) 
       label_for = u' for="%s"' % final_attrs['id'] 
      else: 
       label_for = '' 
      option_value = force_unicode(option_value) 
      option_label = conditional_escape(force_unicode(option_label)) 
      button_output.append(u'<label%s class="btn%s" id="btn-%s-%s" data-name="%s,%s">%s</label>' % (label_for, self.classes, name, option_value, name, option_value, option_label)) 
     button_output.append(u'</div>') 
     button_output = u'\n'.join(button_output) 

     # Buttons for select all or none 
     if self.all or self.none: 
      select_all_none_button_output = [u'<div class="btn-group all-none-buttons" data-toggle="buttons-radio" data-name="%s">' % name] 
      if self.all: 
       select_all_none_button_output.append(u'<button class="select-all btn%s" type="button" data-name="%s">All</button>' % (self.classes, name,)) 
      if self.none: 
       select_all_none_button_output.append(u'<button class="select-none btn%s" type="button" data-name="%s">None</button>' % (self.classes, name,)) 
      select_all_none_button_output.append(u'</div>') 
      select_all_none_button_output = u'\n'.join(select_all_none_button_output) 

     # Full output 
     if select_all_none_button_output: 
      output = "%s\n%s\n%s" % (select_output, button_output, select_all_none_button_output) 
     else: 
      output = "%s\n%s" % (select_output, button_output) 

     return mark_safe(output) 

    class Media: 
     js = ('/static/bootstrap-button-multiselect.js',) 
     css = { 
      'all': ('/static/bootstrap-button-multiselect.css',) 
     } 

、私はその後、携帯電話やタブレット上で選択し、複数のウィジェットに戻っスワップ大画面上のボタンを表示するようにCSSを使用しています。私のビュー機能:

from django.http import HttpResponseRedirect 
from django.shortcuts import render_to_response 
from django.template.context import RequestContext 
from tickets.forms import TicketForm 
from tickets.models import Ticket 

def addEditTicket(request, op='add', encrypted_pk=None, cipher=None): 
    """ 
    Form and processing for new tickets 
    """ 
    if encrypted_pk is not None: 
     pk = int(encrypted_pk)^cipher 
     ticket = Ticket.objects.get(pk=pk) 
     form = TicketForm(instance=ticket) 
     initialData = {'form': form, 'form_action': '/ticket/' + op + '/', 'title': op.capitalize() + ' a ticket'} 
     csrfContext = RequestContext(request, initialData)    # adds CSRF token to form context 
     return render_to_response('form.html', csrfContext)    # pass context with token to form 

    if request.method == 'POST': 
     form = TicketForm(request.POST) 
     if form.is_valid(): 
      new_ticket = form.save() 
      form = TicketForm(instance=new_ticket) 
      # todo-devon Notify user in new form that object was saved 
      # Context includes form object, URL for form action (dynamically generated from argument passed as op), 
      # and a title dynamically generated from operation combined with the object type in question. 
      initialData = {'form': form, 'form_action': '/ticket/edit/', 'title': 'Edit a ticket'} 
      csrfContext = RequestContext(request, initialData)  # adds CSRF token to form context 
      return render_to_response('form.html', csrfContext)  # pass context with token to form 
    else: 
     form = TicketForm() 

    # Context includes form object, URL for form action (dynamically generated from argument passed as op), 
    # and a title dynamically generated from operation combined with the object type in question. 
    initialData = {'form': form, 'form_action': '/ticket/' + op + '/', 'title': op.capitalize() + ' a ticket'} 
    csrfContext = RequestContext(request, initialData)    # adds CSRF token to form context 
    return render_to_response('form.html', csrfContext)    # pass context with token to form 

このコードをすべてここに破棄して申し訳ありません。前もって感謝します。

EDIT:Javascriptを取り出しました。質問にはあまり関係していなかったので、私の質問はもっと難しいように思えました。

答えて

0

解決策が見つかりました。私はそれがなぜ機能するのか分かりません。私は選択された値を反復して、それぞれにユニコードを強制しなければならなかった。私はデータベースからのオブジェクトがユニコードでないと仮定します。ウィジェットが初期化されたときに、なぜこれがマッチして設定されないのか理解できませんが、うまくいきました。私はDjangoのデフォルト選択ウィジェットを使ってこの解決策を見つけました。

ありがとうございます。

関連する問題