2010-08-18 28 views
43

Tài liệu hơi thiếu một chút so với tính năng này.Làm cách nào để sử dụng MultiWidget của Django?

from django import forms 

class TwoInputWidget(forms.MultiWidget): 
    """An example widget which concatenates two text inputs with a space""" 
    def __init__(self, attrs=None): 
     widgets = [forms.TextInput, forms.TextInput] 

Tôi có thể thấy tôi cần tạo thuộc tính "tiện ích con" với danh sách các tiện ích khác, nhưng sau đó nó có một chút Sherlock Holmes.

Có ai đó vui lòng giải thích cho tôi cách sử dụng tiện ích MultiWidget không?

+0

Giải pháp này hơi bị hack, nhưng nội tuyến hơn với cách chúng tôi mong đợi truy cập các trường con trong mẫu. http://stackoverflow.com/questions/24866936/render-only-one-part-of-a-multiwidget-in-django – farthVader

Trả lời

51

Câu hỏi thú vị và tôi nghĩ có lẽ đáng được chú ý hơn một chút trong tài liệu.

Dưới đây là một ví dụ từ a question I've just asked:

class DateSelectorWidget(widgets.MultiWidget): 
    def __init__(self, attrs=None, dt=None, mode=0): 
     if dt is not None: 
      self.datepos = dt 
     else: 
      self.datepos = date.today()  

     # bits of python to create days, months, years 
     # example below, the rest snipped for neatness. 

     years = [(year, year) for year in year_digits] 

     _widgets = (
      widgets.Select(attrs=attrs, choices=days), 
      widgets.Select(attrs=attrs, choices=months), 
      widgets.Select(attrs=attrs, choices=years), 
      ) 
     super(DateSelectorWidget, self).__init__(_widgets, attrs) 

    def decompress(self, value): 
     if value: 
      return [value.day, value.month, value.year] 
     return [None, None, None] 

    def format_output(self, rendered_widgets): 
     return u''.join(rendered_widgets) 

What've tôi thực hiện?

  • subclassed django.forms.widgets.MultiWidget
  • thực hiện một constructor tạo ra nhiều widgets.WidgetName widget trong một tuple . Điều này rất quan trọng vì lớp siêu sử dụng sự tồn tại của bộ dữ liệu này để xử lý một số thứ cho bạn.
  • Đầu ra định dạng của tôi là thông qua, nhưng ý tưởng là bạn có thể thêm html tùy chỉnh tại đây nếu bạn muốn
  • Tôi cũng đã thực hiện decompress vì bạn phải - bạn sẽ được chuyển các giá trị từ cơ sở dữ liệu trong một đối tượng value. decompress ngắt kết nối này để hiển thị trong tiện ích. Làm thế nào và những gì bạn làm ở đây là tùy thuộc vào bạn và phụ thuộc vào widget.

Những điều tôi không có, nhưng có thể có, overriden:

  • render, đây là thực sự chịu trách nhiệm về render widget, vì vậy bạn chắc chắn cần phải gọi siêu Phương thức render nếu bạn phân lớp này. Bạn có thể thay đổi cách mọi thứ được hiển thị ngay trước khi kết xuất bằng cách phân lớp này.

Ví dụ, django markitup 's làm cho phương pháp:

def render(self, name, value, attrs=None): 
    html = super(MarkItUpWidget, self).render(name, value, attrs) 

    if self.auto_preview: 
     auto_preview = "$('a[title=\"Preview\"]').trigger('mouseup');" 
    else: auto_preview = '' 

    html += ('<script type="text/javascript">' 
      '(function($) { ' 
      '$(document).ready(function() {' 
      ' $("#%(id)s").markItUp(mySettings);' 
      ' %(auto_preview)s ' 
      '});' 
      '})(jQuery);' 
      '</script>' % {'id': attrs['id'], 
          'auto_preview': auto_preview }) 
    return mark_safe(html) 
  • value_from_datadict - Xem câu hỏi của tôi here. value_from_datadict kéo giá trị được liên kết với tiện ích này ra khỏi từ điển dữ liệu của tất cả dữ liệu được gửi cùng với biểu mẫu này. Trong trường hợp multiwidget đại diện cho một trường duy nhất, bạn cần phải tạo lại giá trị đó từ nhiều tiện ích con của bạn, đó là cách dữ liệu sẽ được gửi.
  • _get_media có thể hữu ích cho bạn nếu bạn muốn truy xuất phương tiện bằng cách sử dụng phương tiện truyền thông đại diện của django. Các chu trình thực hiện mặc định mà các widget yêu cầu cho media; nếu bạn phân lớp nó và đang sử dụng bất kỳ vật dụng ưa thích nào bạn cần gọi là siêu; nếu tiện ích của bạn cần bất kỳ phương tiện nào thì bạn cần thêm nó bằng cách sử dụng nó.

Ví dụ, django phụ tùng markitup 's thực hiện điều này:

def _media(self): 
     return forms.Media(
      css= {'screen': (posixpath.join(self.miu_skin, 'style.css'), 
          posixpath.join(self.miu_set, 'style.css'))}, 
      js=(settings.JQUERY_URL, 
       absolute_url('markitup/jquery.markitup.js'), 
       posixpath.join(self.miu_set, 'set.js'))) 
    media = property(_media) 

Một lần nữa, nó đang tạo ra một tuple các đường dẫn đến vị trí chính xác, cũng giống như phụ tùng của tôi đã tạo ra một tuple của widget trong __init__.

Tôi nghĩ rằng hãy bao gồm nó cho các phần quan trọng của lớp MultiWidget. Những gì bạn đang cố gắng làm phụ thuộc vào những gì bạn đã tạo ra/vật dụng bạn đang sử dụng, đó là lý do tại sao tôi không thể đi vào chi tiết dễ dàng. Tuy nhiên, nếu bạn muốn xem các lớp cơ sở cho chính mình và hãy xem các ý kiến, hãy xem the source.

+1

Chắc chắn là hướng dẫn chủ đề tốt nhất về việc tạo các trường biểu mẫu đa tiện ích mà tôi đã thấy cho đến nay, và tôi tin rằng tôi đã thấy một số ít! –

+0

Bạn có thể cung cấp ví dụ về cách sử dụng tiện ích đa trong một mẫu mô hình cho hai trường trong biểu mẫu đó không? Hoặc là đa widget được thiết kế để chia nhỏ các trường không kết hợp chúng? –

+0

Phương thức 'format_output' không còn được dùng nữa và không còn tồn tại trong lớp Widget. – Cerin

0

Đọc qua số blog entry và liên kết Django snippet này. Hy vọng điều này sẽ cho bạn một số ý tưởng.

+0

Cảm ơn. Đoạn trích cung cấp nhiều manh mối hơn. Nhưng nó vẫn là công việc thám tử. Tôi đang lượm lặt cách sử dụng nó bằng cách đọc mã và xem các mẫu. Tôi vẫn hy vọng một người nào đó đã giải được bí ẩn này có thể hướng dẫn một chút hướng dẫn cách chúng ta tiêu thụ. –

Các vấn đề liên quan