Poprzedni wpis (Cron nie odpala zadań z crontaba? Mamy cię!) | Następny wpis (Django feeds (twisted way))

django.forms mnie pokonało (przynajmniej trochę)

Robiąc ostanio w Django trafiłem na pewien problem, którego nie jestem w stanie rozwiązać (przynajmniej elegancko) do dziś.

Załóżmy, że mamy klasę, reprezentującą formularz. Ma ona sobie jakieś pola, powiedzmy:

class MyForm(forms.Form):
    name = forms.CharField(label='name')
    description = forms.CharField(label='description', widget=forms.Textarea)
    
    class Media:
        js = ('js/jquery.js', )

Jak widać, będziemy używać jakiegoś JavaScriptu. Problem polega teraz na tym, że chcę dodać trochę dynamiki do wyrenderowanego formularza — na przykład przy polu name dodać link, po którego kliknięciu pojawi się wiersz z polem description, a sam wiersz z polem description ma być początkowo ukryty, na przykład przy użyciu reguły CSS display: none;. Niestety, o ile można dodać definicję atrybutów do widgetu, to, jak się okazuje, nie ma możliwości określenia dodatkowych atrybutów dla całego pola (co wydaje się logiczne, ponieważ pole jest pewnym abstraktem i nie ma własnej warstwy prezentacji). Takich atrybutów, które na przykład mogłyby określić klasę CSS dla elementu obejmującego zarówno label, jak i widget, czy może nawet coś, co mogłoby być dodatkowym tekstem, wyświetlanym oprócz etykiety i widgetu.

Próbowałem paru podejść i żadne nie było zadowalające — albo powodowało, że cały dokument się nie walidował (dodawanie własnego atrybutu do widgetu i następnie wyświetlanie całego wiersza z klasą, będącą wartością tego atrybutu), albo było potwornie brzydkie (słownik z konfiguracją dodatowych atrybutów dla każdego z pól, któremu chcę coś dodać lub przedefiniowanie wszystkich wbudowanych klas pól, żeby akceptowały dodatkowe argumenty). Inne sposoby, których nie próbowałem, ale też przychodziły mi do głowy, były o wiele bardziej hackerskie, np. klasa domieszkowa do wstrzyknięcia w klasy pól wbudowanych przy użyciu jakiegoś rodzaju monkey patchingu. Nie wiem, może i by to zadziałało, ale moje upodobanie do prostych rozwiązań mocno by ucierpiało.

Efekt jest taki, że robię to nieelegancko i wciąż szukam inspiracji, żeby wymyślić sposób zrobienia tego ładnie. Każda sugestia mile widziana.

Komentarze (3)

#1 Tomek skomentował(-a) 8 października 2008 o 14:23

Może unobtrusive js? nadaj klasę formularzowi. Potem w $.ready() ukryj description i dodaj (z js) link z handlerem na onclick.

W ten sposób ludzie bez js też będą mieli używalny formularz.

A co do wstrzykiwania dodatkowego tekstu... Przy dziwnych, niestandardowych formularzach, dobrze jest samemu zadbać o wyświetlanie, czyli każde pole renderować osobno.

#2 Tomek skomentował(-a) 8 października 2008 o 14:30

Gwoli uzupełnienia poprzedniego komentarza link do dokumentacji:
http://docs.djangoproject.com/en/dev/topics/forms/#customizing-the-form-template

#3 jarek skomentował(-a) 8 października 2008 o 14:42

Widzisz, Twoje propozycje sprowadzają się do ręcznej rzeźby w przypadku każdego formularza (tu ukryj to, a tam co innego), a ja chcę mieć mechanizm działający bardziej generycznie, bo mam w apliakcji kilkadziesiąt formularzy.

I właśnie zaświtało mi, że może dałoby się ustawić instancji formularza (albo od razu jego klasie) atrybut, zawierający to, co przydałoby mi się podczas renderowania pojednyńczego pola. Trochę kombinowania, ale mniej hackersko.

Skomentujesz?

* 


* 


* oznacza pole wymagane

Technikalia

  • XP-Dev.com: Free Subversion Hosting
  • A Django joint.
  • Python powered