<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6518460238029135110</id><updated>2011-11-25T22:37:11.808+01:00</updated><category term='linux'/><category term='apache'/><category term='muzyka'/><category term='propel'/><category term='postgres'/><category term='konsola'/><category term='gotowce'/><category term='arch'/><category term='php'/><category term='fluxbox'/><category term='ajax'/><category term='wzorce obiektowe'/><category term='bazy danych'/><category term='tinymce'/><category term='organizer'/><category term='oop'/><category term='django'/><category term='przeglądarki'/><category term='programowanie'/><category term='gnome'/><category term='drukarka'/><category term='mvc'/><category term='firefox'/><category term='webdeveloper'/><category term='python'/><category term='cms'/><category term='smarty'/><category term='tips'/><category term='rss'/><category term='sterowniki'/><category term='orm'/><category term='xfce'/><category term='debian'/><category term='video'/><category term='microsoft'/><category term='forms'/><category term='kdm'/><category term='symfony'/><category term='przemyślenia'/><category term='narzędzia'/><category term='koncert'/><category term='ioc'/><category term='humor'/><category term='galeria'/><title type='text'>Marcin Nowak</title><subtitle type='html'>Tak czy owak jestem Nowak.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>36</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-6339762131262785279</id><published>2010-10-31T11:34:00.000+01:00</published><updated>2010-10-31T11:34:50.762+01:00</updated><title type='text'>Blog całkowicie przeniesiony na pep20.net</title><content type='html'>Blog całkowicie przeniesiony na nowy adres: &lt;a href="http://pep20.net"&gt;pep20 - blog programisty Python&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-6339762131262785279?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/6339762131262785279/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=6339762131262785279' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/6339762131262785279'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/6339762131262785279'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2010/10/blog-cakowicie-przeniesiony-na-pep20net.html' title='Blog całkowicie przeniesiony na pep20.net'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-3313432405735955794</id><published>2010-04-28T20:00:00.000+02:00</published><updated>2010-04-29T11:38:31.066+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='forms'/><category scheme='http://www.blogger.com/atom/ns#' term='django'/><category scheme='http://www.blogger.com/atom/ns#' term='tips'/><title type='text'>Symfony forms vs Django forms</title><content type='html'>&lt;p&gt;Mam okazję pracować z obydwoma frameworkami i mogę je porównać w praktyce. &lt;br /&gt;   Django zacząłem używać jakieś dwa lata temu, a Symfony nieco wcześniej (od&lt;br /&gt;   wydania stabilnej wersji 1.0).&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Ostatnimi czasy, z braku możliwości upgrade Symfony w projekcie, przeportowałem&lt;br /&gt;   mechanizm formularzy z wersji 1.1 do 1.0.20. &lt;br /&gt;&lt;/p&gt; &lt;br /&gt;&lt;h2&gt;Piersze wrażenie&lt;/h2&gt;&lt;p&gt;Mechanika formularzy w Symfony mocno przypomina newforms z Django. Powszechnie&lt;br /&gt;   wiadomo, że Fabien jest fanem Django, więc nie zdziwiło mnie zbyt specjalnie, że&lt;br /&gt;   wzorował się właśnie na nim.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Mamy do dyspozycji podstawową klasę formularza sfForm (django.forms.Form), oraz&lt;br /&gt;   klasę dedykowaną do modelu Propela sfPropelForm (django.forms.ModelForm).&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Jest do dyspozycji zbiór widgetów w klasach sfWidgetForm (django.forms.widgets) do&lt;br /&gt;   renderingu pól oraz zestaw walidatorów w klasach sfValidator (w Django&lt;br /&gt;   sprawdzanie poprawności danych jest rozwiązane przez wywoływanie metod&lt;br /&gt;   clean_FIELDNAME() formularza, o ile zostały zdefiniowane, oraz metody clean()&lt;br /&gt;   każdego pola). W Symfony jest możliwość napisania własnych specyficznych widgetów &lt;br /&gt;   i walidatorów.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Używanie formularzy jest podobne - w widoku (sf: akcji), najczęściej przy requescie wysłanym&lt;br /&gt;   POST-em instancjonujemy formularz i wypelniamy go danymi z requestu, sprawdzamy&lt;br /&gt;   czy jest prawidlowy (sfForm::is_valid()). W przypadku sfPropelForm (ModelForm)&lt;br /&gt;   po walidacji wywołujemy save().&lt;br /&gt;&lt;/p&gt; &lt;br /&gt;&lt;h2&gt;Definiowanie formularzy&lt;/h2&gt;&lt;p&gt;W Django używamy class properties i zagnieżdżonej klasy Meta.&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;class MyForm(forms.Form):&lt;br /&gt;  name = forms.CharField()&lt;br /&gt;  birthdate = formd.DateField()&lt;br /&gt; &lt;br /&gt;  class Meta:&lt;br /&gt;    exclude = ('birthdate',)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;W Symfony formularz konfigurowany jest w&lt;br /&gt;   metodzie sfForm::configure(), która uruchamiana jest domyslnie w&lt;br /&gt;   konstruktorze.&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;class MyForm extends sfForm&lt;br /&gt;{&lt;br /&gt;  protected function configure() {&lt;br /&gt;    $this-&amp;gt;setWidgets(array(&lt;br /&gt;        'name' =&amp;gt; new sfWidgetFormInput(array('required'=&amp;gt;true,)),&lt;br /&gt;        'birthdate' =&amp;gt; new sfWidgetFormDate(array('required'=&amp;gt;true,)),&lt;br /&gt;        ));&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ops, ale.. jak wykluczyć datę urodzin?&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Google dają odpowiedź:&lt;br /&gt;&lt;/p&gt;&lt;ul&gt; &lt;li&gt; &lt;br /&gt;     &lt;strong&gt;Q:&lt;/strong&gt; How to exclude a field?&lt;br /&gt; &lt;/li&gt;   &lt;li&gt; &lt;br /&gt;     &lt;strong&gt;A:&lt;/strong&gt; You have to remove the widget and the validator.&lt;br /&gt; &lt;/li&gt; &lt;/ul&gt;&lt;p&gt;W Symfony zwykle kończy się to na klasie pochodnej, przeciążeniu configure() z&lt;br /&gt;   serią unset na widgetSchema i validators. Możliwe jest (wszystko jest możlwie&lt;br /&gt;   do realizacji, ale z różną efektywnością i poziomem trudności), ale trochę uciążliwe.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Django-Symfony 1:0&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Uważny czytelnik zwróci uwagę, że w Symfony nie definiujemy pół formularza&lt;br /&gt;   (sic!) tylko oddzielnie widgety i validatory. Mimo, że istnieje klasa&lt;br /&gt;   sfFormField, jest ona używana już po bindingu (zawiera w sobie wartość pola - w&lt;br /&gt;   Django jest BoundField, które opakowuje Field i dostarcza wartość).&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Jaka jest zatem kolejna wada formularzy Symfony? Nie ma zdefiniowanych klas pól&lt;br /&gt;   formularzy, które naturalnie łączą widgety i walidaję danych, np. CharField związane&lt;br /&gt;   jest domyślnie z widgetem TextInput i posiada domyślną walidację w metodzie&lt;br /&gt;   CharField.clean(). W Symfony trzeba dodać walidację samodzielnie:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;class MyForm extends sfForm&lt;br /&gt;{&lt;br /&gt;  protected function configure() {&lt;br /&gt;    $this-&amp;gt;setWidgets(array(&lt;br /&gt;        'name' =&amp;gt; new sfWidgetFormInput(array('required'=&amp;gt;true,)),&lt;br /&gt;        'birthdate' =&amp;gt; new sfWidgetFormDate(array('required'=&amp;gt;true,)),&lt;br /&gt;        ));&lt;br /&gt; &lt;br /&gt;    $this-&amp;gt;setValidators(array(&lt;br /&gt;        'name' =&amp;gt; new sfValidatorString(array('required'=&amp;gt;true)),&lt;br /&gt;        ));&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Walidacja pola jest zwykle specyficzna. W Symfony trzeba napisać dedykowaną&lt;br /&gt;   klasę walidatora. W Django implementujemy metodę clean_FIELDNAME w&lt;br /&gt;   klasie formularza. Można też przygotować dedykowaną klasę Field.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Django-Symfony 2:0&lt;br /&gt;&lt;/p&gt; &lt;br /&gt;&lt;h2&gt;I18n (czyli formularze po polsku)&lt;/h2&gt;&lt;p&gt;W Django etykiety i komunikaty walidacji muszą być opakowane w wywołanie funkcji&lt;br /&gt;   gettext. W komunikatach podstawowych pól używany jest ugettext_lazy. Etykiety&lt;br /&gt;   musimy zdefiniować ręcznie (za pomocą argumentu label przy definiowaniu pola&lt;br /&gt;   formularza).&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;class MyForm(forms.Form):&lt;br /&gt;  name = forms.CharField(label=_('Name'))&lt;br /&gt;  birthdate = formd.DateField(label=_('Birth date'))&lt;br /&gt; &lt;br /&gt;  class Meta:&lt;br /&gt;    exclude = ('birthdate',)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Po stronie Symfony zrealizowano to nieco inaczej - przez nastawienie funkcji&lt;br /&gt;   callbacka do funkcji translate:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  protected function configure() {&lt;br /&gt;      $this-&amp;gt;widgetSchema-&amp;gt;getFormFormatter()-&amp;gt;setTranslationCallable(&lt;br /&gt;          array(sfContext::getInstance()-&amp;gt;getI18N(), '__'));&lt;br /&gt;      /* ... */&lt;br /&gt;  }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Pełny kod formularza w Symfony:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;class MyForm extends sfForm&lt;br /&gt;{&lt;br /&gt;  protected function configure() {&lt;br /&gt; &lt;br /&gt;    $this-&amp;gt;widgetSchema-&amp;gt;setNameFormat('my_form[%s]');&lt;br /&gt;    $this-&amp;gt;widgetSchema-&amp;gt;getFormFormatter()-&amp;gt;setTranslationCallable(&lt;br /&gt;        array(sfContext::getInstance()-&amp;gt;getI18N(), '__'));&lt;br /&gt; &lt;br /&gt;    $this-&amp;gt;setWidgets(array(&lt;br /&gt;        'name' =&amp;gt; new sfWidgetFormInput(array('required'=&amp;gt;true,)),&lt;br /&gt;        'birthdate' =&amp;gt; new sfWidgetFormDate(array('required'=&amp;gt;true,)),&lt;br /&gt;        ));&lt;br /&gt; &lt;br /&gt;    $this-&amp;gt;setValidators(array(&lt;br /&gt;        'name' =&amp;gt; new sfValidatorString(array('required'=&amp;gt;true)),&lt;br /&gt;        'birthdate' =&amp;gt; new sfValidatorDate(array('required'=&amp;gt;true)),&lt;br /&gt;        ));&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Pamiętacie jeszcze, że w Django ten sam opis formularza składa się tylko 5 linii&lt;br /&gt;   kodu? :)&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Mimo innego sposobu używania gettext(), to zarówno Django, jak i w Symfony dają&lt;br /&gt;   radę. Remis. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Django-Symfony  3:1&lt;br /&gt;&lt;/p&gt; &lt;br /&gt;&lt;h2&gt;Domyślne dane (initial parameters)&lt;/h2&gt;&lt;p&gt;Django:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  data = {'name': 'Stranger',}&lt;br /&gt;  form = MyForm(initial=data)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Symfony:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  $form = new MyForm();&lt;br /&gt;  $form-&amp;gt;setDefaults(array('name'=&amp;gt;'Stranger'));&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Praktycznie to samo.  Jednak zauważyłem, że pomimo nastawienia wartości domyślnych w formularzu&lt;br /&gt;   sfPropelForm, pusta wartość pola modelu napisuje to, co przekazujemy w defaults.&lt;br /&gt;   Jest to dość duży problem, ale może dotyczyć tylko wersji formularzy z Symfony&lt;br /&gt;   1.1. Remis.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Django-Symfony  4:2&lt;br /&gt;&lt;/p&gt; &lt;br /&gt;&lt;h2&gt;Binding&lt;/h2&gt;&lt;p&gt;Formularze Django w konstruktorze przyjmują parametr data, do którego zwykle&lt;br /&gt;   przekazuje się request.POST. Analogicznie jest z przesłanymi plikami -&lt;br /&gt;   request.FILES. Przykład:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;def my_form(request):&lt;br /&gt;  if request.method == 'POST':&lt;br /&gt;      form = MyForm(request.POST, request.FILES)&lt;br /&gt;      if form.is_valid():&lt;br /&gt;          model = form.save()&lt;br /&gt;          return redirect(model)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;W Symfony jest dość podobnie, aczkolwiek binding należy wykonać oddzielną&lt;br /&gt;   metodą bind():&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;public function executeMy_form() {&lt;br /&gt;  $form = new MyForm();&lt;br /&gt;  if($this-&amp;gt;getRequest()-&amp;gt;getMethod() == sfWebRequest::POST) {&lt;br /&gt;      $form-&amp;gt;bind($this-&amp;gt;getRequestParameter('my_form'),&lt;br /&gt;        $this-&amp;gt;getRequest()-&amp;gt;getFiles('my_form'));&lt;br /&gt;      if($form-&amp;gt;isValid()) {&lt;br /&gt;          $form-&amp;gt;save();&lt;br /&gt;          $this-&amp;gt;redirect('/somewhere/');&lt;br /&gt;      }&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Należy też pamiętać o użyciu prawidłowej zmiennej z requestu - w klasie&lt;br /&gt;   formularza definiujemy name format (setNameFormat) i te obydwie części muszą się&lt;br /&gt;   zgadzać. W ten sposób złamano DRY i nie jestem, czy w Symfony da się ten problem&lt;br /&gt;   jakoś ominąć. Remis.&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Django-Symfony  5:3&lt;br /&gt;&lt;/p&gt; &lt;br /&gt;&lt;h2&gt;Częste problemy/tips&lt;/h2&gt;&lt;ul&gt; &lt;li&gt;&lt;p&gt;Własny rendering formularzy. W Symfony musicie pamiętać o jawnym używaniu gettext(),&lt;br /&gt;     jeśli nie używacie metod render*() pól/formularza.&lt;br /&gt;&lt;/p&gt; &lt;br /&gt; &lt;/li&gt;   &lt;li&gt;&lt;p&gt;Dostosowywanie formularzy do potrzeb projektu. Django daje duże możliwości&lt;br /&gt;     dzięki przestrzeniom nazw Pythona i konfiguracji urls/settings. Zwykle&lt;br /&gt;     w projekcie dodaje się dedykowaną aplikację z modułem zawierającym&lt;br /&gt;     dostosowane formularze i najczęściej zmienia się konfigurację urls (w&lt;br /&gt;     reusable apps mamy zwykle do dyspozycji parametr form_class w widokach).&lt;br /&gt;     Symfony, przynajmniej w wersji 1.0.X, nie daje mechanizmu zbliżonego do&lt;br /&gt;     urls, chociaż można użyć &lt;a href="http://www.symfony-project.org/book/1_0/17-Extending-Symfony#chapter_17_factories"&gt;factories&lt;/a&gt;&lt;br /&gt;     albo innych rozwiązań (ja stosowałem własny kontener IoC). Warto o tym&lt;br /&gt;     pamiętać, bo we wdrożeniach bardzo często dostosowuje się właśnie formularze.&lt;br /&gt;&lt;/p&gt; &lt;br /&gt; &lt;/li&gt;   &lt;li&gt;&lt;p&gt;Odpowiednik klasy ModelForm w Symfony nie potrafi "w locie" zbudować&lt;br /&gt;     definicji formularza. Bazowe klasy dla poszczególnych modeli muszą być&lt;br /&gt;     wygenerowane (sic!). Zatem użyteczność sfPropelForm bez wygenerowanych&lt;br /&gt;     bazowych klas jest niewielka i ogranicza się do zaimplementowanej metody save().&lt;br /&gt;&lt;/p&gt; &lt;br /&gt; &lt;/li&gt; &lt;/ul&gt; &lt;br /&gt;&lt;h2&gt;Fantazje Fabiena&lt;/h2&gt;&lt;p&gt;Na koniec, jako ciekawostkę, dodam krótkie podsumowanie tego, co Fabien zaimplementował będąc albo&lt;br /&gt;   przemęczonym, albo na kacu ;)&lt;br /&gt;&lt;/p&gt;&lt;ul&gt; &lt;li&gt;&lt;p&gt;schemat widgetów/validatorów (kontener/dict) dziedziczy bezpośrednio po klasie&lt;br /&gt;   Widget/Validator (znakomity przykład do czego nie używać dziedziczenia)&lt;br /&gt;&lt;/p&gt; &lt;br /&gt; &lt;/li&gt;   &lt;li&gt;&lt;p&gt;forms embedding (formularze w formularzach) - przyznam, że nie mogę tego&lt;br /&gt;   pojąć. Nie mamy formsetow, ale możemy zagnieżdżać formularze w sobie. &lt;br /&gt;&lt;/p&gt; &lt;br /&gt; &lt;/li&gt;   &lt;li&gt;&lt;p&gt;form merging (łączenie formularzy) - nie widze zastosowania (formularz&lt;br /&gt;   hermetyzuje logikę, sprawdzanie poprawności i sposób prezentacji - po co&lt;br /&gt;   łączyć, użyjmy kilku formularzy lub Formsetu)&lt;br /&gt;&lt;/p&gt; &lt;br /&gt; &lt;/li&gt;   &lt;li&gt;&lt;p&gt;I18N w kontekście translacji (gettext) - zahermetyzowane wewnątrz formularza,&lt;br /&gt;   lecz z możliwością wymiany callable na dowolny; trudne/każdorazowe definiowanie&lt;br /&gt;   domyślnego callable; gettext powinien być używany, nie zawarty wewnątrz&lt;br /&gt;   klasy formularza&lt;br /&gt;&lt;/p&gt; &lt;br /&gt; &lt;/li&gt; &lt;/ul&gt; &lt;br /&gt;&lt;h2&gt;Podsumowanie&lt;/h2&gt;&lt;p&gt;Formularze w Symfony są, a to już lepsze niż nic, które było w wersji 1.0.X.&lt;br /&gt;   Ostateczny wynik rozgrywki Django-Symfony 5:3. Jeśli ktoś nie używał formularzy&lt;br /&gt;   w Symfony, to gorąco polecam. Jeśli ktoś ma dylemat co wybrać, polecam Django z&lt;br /&gt;   racji szerszych możliwości i skrócenia czasu realizacji zadań.&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-3313432405735955794?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/3313432405735955794/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=3313432405735955794' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/3313432405735955794'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/3313432405735955794'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2010/04/symfony-forms-vs-django-forms.html' title='Symfony forms vs Django forms'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-5365689202872614167</id><published>2010-03-27T17:29:00.006+01:00</published><updated>2010-03-27T17:34:14.295+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='arch'/><category scheme='http://www.blogger.com/atom/ns#' term='drukarka'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='sterowniki'/><title type='text'>Instalacja sterownika drukarki Canon IP1900 na Arch Linux 64bit</title><content type='html'>Miałem kilkanaście minut rozgryzania, zanim udało mi się zainstalować sterownik. Dlatego w krótkich punktach napiszę, jak przez ten proces przebrnąć sprawnie.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Zaktualizuj system do najnowszej wersji&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;pacman -Syu&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Zainstaluj pakiet&amp;nbsp;&lt;a href="http://aur.archlinux.org/packages.php?ID=28122"&gt;cups-canon-3.00&lt;/a&gt;&amp;nbsp;znajdujący się w repozytorium AUR.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Uwaga!&lt;/b&gt;&amp;nbsp;Podczas instalacji (np. za pomocą yaourt) musiałem wyłączyć kilka zależności, gdyż pacman nie mógł ich rozwiązać (dwa pakiety znajdują się w AUR). Wyłączyłem wszystkie biblioteki lib32 po prostu kasując je z wiersza dependencies.&lt;/li&gt;&lt;li&gt;Nie zapomnij zainstalować bibliotek lib32:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;lib32-popt z AUR&lt;/li&gt;&lt;li&gt;lib32-libpng12 z AUR&lt;/li&gt;&lt;li&gt;pacman -S lib32-libxml2&amp;nbsp;&lt;/li&gt;&lt;li&gt;pacman -S lib32-libpng &amp;nbsp;lib32-gtk2&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;Po kompilacji i instalacji powinieneś mieć plik /usr/bin/cifip1900. Sprawdź:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;marcin]# file /usr/bin/cifip1900&lt;br /&gt;/usr/bin/cifip1900: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.2.5, stripped&lt;/blockquote&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Sprawdź także, czy nie brakuje innych bibliotek:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;marcin]# ldd32 /usr/bin/cifip1900&lt;/blockquote&gt;&lt;br /&gt;Jeśli wszystko gra, powinieneś mieć output podobny do:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;linux-gate.so.1 =&amp;gt; &amp;nbsp;(0xf775f000)&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;libcnbpcmcm346.so =&amp;gt; /usr/lib/libcnbpcmcm346.so (0xf772a000)&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;libcnbpess346.so =&amp;gt; /usr/lib/libcnbpess346.so (0xf76da000)&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;libm.so.6 =&amp;gt; /opt/lib32/lib/libm.so.6 (0xf76b4000)&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;libdl.so.2 =&amp;gt; /opt/lib32/lib/libdl.so.2 (0xf76b0000)&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;libtiff.so.3 =&amp;gt; /opt/lib32/usr/lib/libtiff.so.3 (0xf7656000)&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;libpng12.so.0 =&amp;gt; /opt/lib32/usr/lib/libpng12.so.0 (0xf7631000)&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;libcnbpcnclapi346.so =&amp;gt; /usr/lib/libcnbpcnclapi346.so (0xf762d000)&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;libcnbpcnclbjcmd346.so =&amp;gt; /usr/lib/libcnbpcnclbjcmd346.so (0xf7629000)&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;libcnbpcnclui346.so =&amp;gt; /usr/lib/libcnbpcnclui346.so (0xf7623000)&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;libpopt.so.0 =&amp;gt; /opt/lib32/usr/lib/libpopt.so.0 (0xf7618000)&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;libc.so.6 =&amp;gt; /opt/lib32/lib/libc.so.6 (0xf74d1000)&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;libpthread.so.0 =&amp;gt; /opt/lib32/lib/libpthread.so.0 (0xf74b8000)&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;/lib/ld-linux.so.2 (0xf7760000)&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;libjpeg.so.8 =&amp;gt; /opt/lib32/usr/lib/libjpeg.so.8 (0xf7483000)&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt; &lt;/span&gt;libz.so.1 =&amp;gt; /opt/lib32/usr/lib/libz.so.1 (0xf746e000)&amp;nbsp;&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Zainstaluj CUPS i wsparcie HAL&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;pacman -S cups&amp;nbsp;hal-cups-utils&lt;/blockquote&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Dodając drukarkę do CUPS wybierz tę znalezioną przez HAL, a następnie wskaż plik PPD.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_3L0U9hzJIZw/S64xobErbOI/AAAAAAAAAfE/NLZv7b6I3bo/s1600/print1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_3L0U9hzJIZw/S64xobErbOI/AAAAAAAAAfE/NLZv7b6I3bo/s320/print1.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Odpowiedni plik PPD znajdziesz poleceniem:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;pacman -Ql cups-canon-3.00 | grep ppd&lt;/blockquote&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Strona testowa powinna wydrukować się poprawnie.&lt;br /&gt;Powodzenia!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-5365689202872614167?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/5365689202872614167/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=5365689202872614167' title='Komentarze (1)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/5365689202872614167'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/5365689202872614167'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2010/03/instalacja-sterownika-drukarki-canon.html' title='Instalacja sterownika drukarki Canon IP1900 na Arch Linux 64bit'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_3L0U9hzJIZw/S64xobErbOI/AAAAAAAAAfE/NLZv7b6I3bo/s72-c/print1.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-3892772323566228474</id><published>2009-10-20T00:17:00.009+02:00</published><updated>2009-10-20T01:20:19.569+02:00</updated><title type='text'>Fotogaleria w Django</title><content type='html'>Kilka dni temu zakończyłem wdrożenie projektu galerii fotograficznej. Realizacja była bardzo przyjemna. Użyłem:&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://docs.djangoproject.com/en/dev/ref/contrib/flatpages/"&gt;flatpages&lt;/a&gt; - treść statyczna&lt;/li&gt;&lt;li&gt;&lt;a href="http://github.com/marcinn/django-imageprocessor"&gt;django-imageprocessor&lt;/a&gt; - wsadowe przetwarzanie grafiki do miniatur oraz dużych zdjęć&lt;/li&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/django-watermark/"&gt;django-watermark&lt;/a&gt; - nakładanie znaków wodnych na duże zdjęcia&lt;/li&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/django-tagging/"&gt;django-tagging&lt;/a&gt;&lt;/li&gt;&lt;li&gt;własna aplikacja photogallery&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;Sercem galerii jest aplikacja mojego autorstwa, którą wzbogaciłem o własne widoki CRUD (na bazie widoków generycznych), gdyż panel administracyjny Django w swej niezmodyfikowanej formie jest niewygodny dla przeciętnego użytkownika. Szczerze mówiąc rozwijałem to oprogramowanie tylko dlatego, żeby poszerzyć umiejętności programowania reusable apps. Aplikacja jest wyposażona w replikator albumów i zdjęć z galerii Coppermine. Replikacja odbywa się za pomocą xml-rpc (po stronie Coppermine napisałem prosty rpc server w Pythonie). &lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Nie jestem jeszcze zdecydowany na uwolnienie kodu mojej galerii - najpierw zweryfikuję istniejące aplikacje, które zapewne są bardziej rozbudowane. Natomiast skłaniam się ku wydaniu paczki importującej fotki i albumy z Coppermine.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Przy okazji realizacji tego projektu wydałem aplikację &lt;a href="http://github.com/marcinn/django-imageprocessor"&gt;django-imageprocessor&lt;/a&gt;.  Można powiedzieć, że jest to lżejsza wersja &lt;a href="http://bitbucket.org/jdriscoll/django-imagekit/"&gt;django-imagekit&lt;/a&gt;. Imageprocessor ewoluował od czasów Pylons, a nawet PHP (od ponad roku). Na chwile obecną usunąłem większość kodu - okazał się zbędny. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;django-imageprocessor zastosowałem do generowania miniatur oraz dużych zdjęć ze znakami wodnymi. Czym się rożni od pozostałych implementacji generatorów miniatur?  Głównie możliwością zarejestrowania presetów pod unikalnymi nazwami, za pomocą których będzie odbywał się rendering docelowych obrazków. W realizowanym projekcie użyłem presetu z procesorem skalującym obrazek źródłowy do 800x600 z nałożeniem znaku wodnego, oraz helpera do generowania miniatur (dedykowany template tag). Imageprocessor jest jeszcze w alpha stage (szczególnie boli brak testów). Mimo wszystko zachęcam do zapoznania się z aplikacją i czekam na Wasze opinie.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Dla zainteresowanych efektem finalnym: &lt;a href="http://obiettiva.pl/"&gt;http://obiettiva.pl/&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-3892772323566228474?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/3892772323566228474/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=3892772323566228474' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/3892772323566228474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/3892772323566228474'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2009/10/fotogaleria-w-django.html' title='Fotogaleria w Django'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-1924068566822993192</id><published>2009-10-04T19:42:00.006+02:00</published><updated>2009-10-04T19:56:59.639+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='arch'/><category scheme='http://www.blogger.com/atom/ns#' term='bazy danych'/><category scheme='http://www.blogger.com/atom/ns#' term='narzędzia'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='postgres'/><title type='text'>Arch linux - aktualizacja Postgresql 8.3 do 8.4</title><content type='html'>Po aktualizacji systemu server postgres nie startuje wskutek niekompatybilności formatu plików danych. Skrócony przepis na aktualizację:&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;a href="http://wiki.archlinux.org/index.php/Downgrade_packages"&gt;zainstaluj poprzednią wersję&lt;/a&gt; postgresql&lt;br /&gt;&lt;blockquote&gt;pacman -U /var/cache/pacman/pgk/postgresql-8.3-X.pkg.tar.gz&lt;/blockquote&gt;&lt;/li&gt;&lt;li&gt;uruchom usługę, wykonaj dump bazy:&lt;br /&gt;&lt;blockquote&gt;pg_dumpall -oU postgres &gt;~/postgres_83.dump.sql&lt;/blockquote&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;zastopuj usługę&lt;br /&gt;&lt;blockquote&gt;pg_ctl stop&lt;/blockquote&gt;&lt;/li&gt;&lt;li&gt;zmień nazwę katalogu z danymi wersji 8.3&lt;br /&gt;&lt;blockquote&gt;mv /var/lib/postgres/data /var/lib/postgres/data_8.3&lt;br /&gt;mkdir /var/lib/postgres/data&lt;br /&gt;chown postgres:postgrss /var/lib/postgres/data&lt;br /&gt;chmod 0700 /var/lib/postgres/data&lt;/blockquote&gt;&lt;/li&gt;&lt;li&gt;wykonaj upgrade postgresql, np. przez pacman -Syu&lt;/li&gt;&lt;li&gt;wykonaj init katalogu danych&lt;br /&gt;&lt;blockquote&gt;initdb -D /var/lib/postgres/data&lt;/blockquote&gt;&lt;/li&gt;&lt;li&gt;sprawdź/uaktualnij konfigurację - niektóre opcje nie są kompatybilne&lt;br /&gt;&lt;blockquote&gt;vimdiff /var/lib/postgres/data_8.3/pg_hba.conf /var/lib/postgres/data/pg_hba.conf&lt;br /&gt;vimdiff /var/lib/postgres/data_8.3/postgresql.conf /var/lib/postgres/data/postgresql.conf&lt;/blockquote&gt;&lt;/li&gt;&lt;li&gt;uruchom usługę postgres&lt;/li&gt;&lt;li&gt;zaimportuj backup&lt;br /&gt;&lt;blockquote&gt;psql -U postgres -d postgres -f ~/postgres_83.dump.sql&lt;/blockquote&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Więcej informacji: &lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.postgresql.org/docs/current/static/install-upgrading.html"&gt;http://www.postgresql.org/docs/current/static/install-upgrading.html&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://wiki.archlinux.org/index.php/PostgreSQL#Upgrading_Postgresql"&gt;http://wiki.archlinux.org/index.php/PostgreSQL#Upgrading_Postgresql&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-1924068566822993192?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/1924068566822993192/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=1924068566822993192' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/1924068566822993192'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/1924068566822993192'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2009/10/arch-linux-aktualizacja-postgresql-83.html' title='Arch linux - aktualizacja Postgresql 8.3 do 8.4'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-6268232003567065776</id><published>2009-07-22T07:00:00.000+02:00</published><updated>2009-07-22T08:01:30.266+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='forms'/><category scheme='http://www.blogger.com/atom/ns#' term='django'/><category scheme='http://www.blogger.com/atom/ns#' term='tips'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programowanie'/><title type='text'>Django forms tips</title><content type='html'>&lt;span style="font-size:180%;"&gt;Rendering bez widgetów - dane pól formularzy&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;W ostatnim czasie mocno ingerowałem w formularze aplikacji django.contrib.admin&lt;br /&gt;i potrzebowałem kilku rozwiązań, które nie bardzo pasowały do konwencji field&lt;-&gt;widget.&lt;br /&gt;Potrzebowałem wyświetlić miniatury zdjęć produktów w formularzu inline.&lt;br /&gt;Rozwiązanie, które stosowałem dotychczas (custom widget) nie do końca mnie satysfakcjonowało.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;class AdminImageFieldWithThumbWidget(FileInput):&lt;br /&gt;&lt;br /&gt;def __init__(self, thumb_width=50, thumb_height=50):&lt;br /&gt;self.width = thumb_width&lt;br /&gt;self.height = thumb_height&lt;br /&gt;super(AdminImageFieldWithThumbWidget, self).__init__({})&lt;br /&gt;&lt;br /&gt;def render(self, name, value, attrs=None):&lt;br /&gt;thumb_html = ''&lt;br /&gt;if value and hasattr(value, "url"):&lt;br /&gt;    thumb_html = '&amp;lt;a href="http://www.blogger.com/%s"&amp;gt;&amp;lt;img src="http://www.blogger.com/%s" width="%s" /&amp;gt;&amp;lt;/a&amp;gt;' % (value.url, value.url, self.width, self.height)&lt;br /&gt;return mark_safe("%s%s" % (thumb_html,&lt;br /&gt;    super(AdminImageFieldWithThumbWidget, self).render(name, value, attrs)))&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Wadą rozwiązania opartego na widget`cie jest osadzenie miniatury między label a file-input.&lt;br /&gt;Potrzebowałem wydostać się poza div`a klasy form-row. Stanąłem przed problemem wydobycia danych formularza.&lt;/p&gt;&lt;p&gt;Próbowałem kolejno:&lt;/p&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;form.myfield&lt;/code&gt; - zwraca output renderowania przez widget&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;form.myfield.as_text&lt;/code&gt; (i pochodne) - używa metody as_widget() do renderowania pola&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;form.myfield.value&lt;/code&gt; - nie istnieje, intensywnie pracują nad łatą &lt;a href="http://code.djangoproject.com/ticket/10427"&gt;#10247&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;code&gt;form.myfield.data&lt;/code&gt; - jest to property read-only, w moim przypadku nie działało&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;p&gt;Do czasu zakończenia ticketu #10427 dobrym rozwiązaniem jest dostęp do initial data formularza za pomocą:&lt;br /&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;span style="font-size:130%;"&gt;&lt;code style="font-weight: bold;"&gt;form.initial.myfield&lt;/code&gt;&lt;/span&gt;&lt;/blockquote&gt;Trzeba pamiętać, że zmienna &lt;span style="font-family:courier new;"&gt;form.initial&lt;/span&gt; zawiera dane początkowe formularza.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;Nie zapomnij o non-form errors&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Jeśli rendering formularza przeniosłeś do własnego szablonu, nie zapomnij o wyświetleniu błędów walidacji nie związanych z polami formularza (np. własna walidacja). Unikniesz czasu straconego na debugowanie walidacji.&lt;/p&gt;&lt;code&gt;&lt;br /&gt;{% for error in form.non_form_errors %}&lt;br /&gt;&amp;lt;li&amp;gt;{{ error }}&amp;lt;/li&amp;gt;&lt;br /&gt;{% endfor %}&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:180%;"&gt;Wyłączanie pól formularza&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Django svn/1.0.2 zawiera irytujący &lt;a href="http://code.djangoproject.com/ticket/8620"&gt;błąd&lt;/a&gt;, który uniemożliwia wyłączanie niektórych pól z formularza, jeśli je redefiniowano za pomocą class properties klasy dziedziczącej. Pisałem o tym szerzej &lt;a href="http://marcinnowak.blogspot.com/2009/05/django-bug-8620-modelform-i-exclude.html"&gt;nieco wcześniej&lt;/a&gt;. Jeśli masz problem z deaktywacją wybranych pól za pomocą właściwości &lt;span style="font-family:courier new;"&gt;exclude&lt;/span&gt;, użyj w klasie bazowej formularza własnej &lt;a href="http://marcinnowak.blogspot.com/2009/05/django-bug-8620-modelform-i-exclude.html"&gt;metaklasy&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-6268232003567065776?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/6268232003567065776/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=6268232003567065776' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/6268232003567065776'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/6268232003567065776'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2009/07/django-forms-tips.html' title='Django forms tips'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-6784839703917099666</id><published>2009-07-08T23:19:00.003+02:00</published><updated>2009-07-08T23:25:29.248+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='video'/><category scheme='http://www.blogger.com/atom/ns#' term='webdeveloper'/><category scheme='http://www.blogger.com/atom/ns#' term='django'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programowanie'/><title type='text'>James Bennett - Django reusable apps at DjangoCon 2008</title><content type='html'>&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;object height="344" width="425"&gt;&lt;param name="movie" value="http://www.youtube.com/v/A-S0tqpPga4&amp;amp;hl=en&amp;amp;fs=1&amp;amp;"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/A-S0tqpPga4&amp;amp;hl=en&amp;amp;fs=1&amp;amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="344" width="425"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-6784839703917099666?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/6784839703917099666/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=6784839703917099666' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/6784839703917099666'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/6784839703917099666'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2009/07/james-bennett-django-reusable-apps-at.html' title='James Bennett - Django reusable apps at DjangoCon 2008'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-7570006166500762273</id><published>2009-05-07T08:06:00.003+02:00</published><updated>2009-05-07T08:14:00.179+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='django'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programowanie'/><title type='text'>django bug #8620 - ModelForm i exclude</title><content type='html'>Django svn/1.0.2 zawiera irytujący &lt;a href="http://code.djangoproject.com/ticket/8620"&gt;błąd&lt;/a&gt;, który uniemożliwia wyłączanie niektórych pól z formularza, jeśli je redefiniowano za pomocą class properties klasy dziedziczącej:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;class RegisterForm(ModelForm):&lt;br /&gt;   email = forms.EmailField()&lt;br /&gt;   password = forms.CharField(widget=widgets.PasswordInput)&lt;br /&gt;   name = forms.CharField()&lt;br /&gt;   birthdate = forms.DateField(widget=widgets.DateTimeInput,required=False)&lt;br /&gt;   class Meta:&lt;br /&gt;       model = models.Person&lt;br /&gt;       fields = ('email','password','name','birthdate')&lt;br /&gt;&lt;br /&gt;class CustomRegisterForm(RegisterForm):&lt;br /&gt;   class Meta(RegisterForm.Meta):&lt;br /&gt;       exclude = ['birthdate']&lt;br /&gt;       fields = ['email','password','name']&lt;br /&gt;&lt;/blockquote&gt;&lt;br /&gt;W powyższym przypadku "birthdate" zmieni tylko swoje położenie - pojawi się na końcu formularza.&lt;br /&gt;&lt;br /&gt;Tymczasowym rozwiązaniem jest utworzenie własnego modułu forms.py:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;from django.forms.models import ModelForm as BaseModelForm&lt;br /&gt;&lt;br /&gt;class FixedModelFormMetaclass(ModelFormMetaclass):&lt;br /&gt;   """&lt;br /&gt;   meta class for model forms with fixed ticket #8620&lt;br /&gt;   """&lt;br /&gt;   def __new__(cls, name, bases, attrs):&lt;br /&gt;       formfield_callback = attrs.pop('formfield_callback',&lt;br /&gt;               lambda f: f.formfield())&lt;br /&gt;       try:&lt;br /&gt;           parents = [b for b in bases if issubclass(b, ModelForm)]&lt;br /&gt;       except NameError:&lt;br /&gt;           # We are defining ModelForm itself.&lt;br /&gt;           parents = None&lt;br /&gt;       declared_fields = get_declared_fields(bases, attrs, False)&lt;br /&gt;       new_class = super(FixedModelFormMetaclass, cls).__new__(cls, name, bases,&lt;br /&gt;               attrs)&lt;br /&gt;       if not parents:&lt;br /&gt;           return new_class&lt;br /&gt;&lt;br /&gt;       if 'media' not in attrs:&lt;br /&gt;           new_class.media = media_property(new_class)&lt;br /&gt;       opts = new_class._meta = ModelFormOptions(getattr(new_class, 'Meta', None))&lt;br /&gt;       if opts.model:&lt;br /&gt;           # If a model is defined, extract form fields from it.&lt;br /&gt;           fields = fields_for_model(opts.model, opts.fields,&lt;br /&gt;                                     opts.exclude, formfield_callback)&lt;br /&gt;           # Override default model fields with any custom declared ones&lt;br /&gt;           # (plus, include all the other declared fields).&lt;br /&gt;       # 8620 fix:&lt;br /&gt;       if opts.fields:&lt;br /&gt;       [declared_fields.pop(f) for f in declared_fields.keys() if f not in opts.fields]&lt;br /&gt;       if opts.exclude:&lt;br /&gt;       [declared_fields.pop(f) for f in declared_fields.keys() if f in opts.exclude]&lt;br /&gt;           fields.update(declared_fields)&lt;br /&gt;       else:&lt;br /&gt;           fields = declared_fields&lt;br /&gt;       new_class.declared_fields = declared_fields&lt;br /&gt;       new_class.base_fields = fields&lt;br /&gt;       return new_class&lt;br /&gt;&lt;br /&gt;class ModelForm(BaseModelForm):&lt;br /&gt;   """&lt;br /&gt;   same as django model form but using FixedModelFormMetaclass&lt;br /&gt;   """&lt;br /&gt;   __metaclass__ = FixedModelFormMetaclass&lt;/blockquote&gt;&lt;br /&gt;Teraz wystarczy użyć własnej klasy z myproject.forms.ModelForm zamiast django.forms.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-7570006166500762273?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/7570006166500762273/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=7570006166500762273' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/7570006166500762273'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/7570006166500762273'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2009/05/django-bug-8620-modelform-i-exclude.html' title='django bug #8620 - ModelForm i exclude'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-4418325440127074405</id><published>2009-04-30T06:56:00.005+02:00</published><updated>2009-04-30T07:52:56.771+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='arch'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><title type='text'>Arch Linux zamiast Ubuntu</title><content type='html'>Dawno temu używałem RedHat 7. To był pierwszy linux na moim desktopie.  Później Fedora - 1,2. Następnie załamanie - powrót do Windows (z lenistwa i podobno lepszego plug-and-play). Dalej Debian (testing, unstable), Kubuntu 6, Ubuntu 7, 8 i... Nabyłem doświadczenia w linuxie i uświadomiłem sobie - cholera, to idzie w kierunku Windows. Aktualizacje 1,5-2GB, auto-magiczne działanie (puste pliki konfiguracyjne, a działa!), spowolnienie po dłuższym użytkowaniu, gigabajty zbędnych danych/pakietów na dysku, rozruch ok 1-2 minuty, a community zalewa newsami o wyższości tapety Intrepida nad Jaunty.&lt;br /&gt;&lt;br /&gt;Czas na zmianę. Za źródło wyboru nowego distro użyłem tego &lt;a href="http://en.wikipedia.org/wiki/Comparison_of_Linux_distributions"&gt;porównania dystrybucji&lt;/a&gt;. Główne kryteria to:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;czas ostatniej aktualizacji, aby zweryfikować czy maintainer nie dał sobie spokoju;&lt;/li&gt;&lt;li&gt;częstość aktualizacji, aby nie czekać trzech lat na upgrade (debian stable)&lt;/li&gt;&lt;li&gt;wiek distro (jak wino - im starszy, tym lepszy), aby nie wybrać "nowotworu" przygotowanego na podstawie Ubuntu przez jakiegoś nastolatka.&lt;/li&gt;&lt;/ol&gt;Następnie wybór wspomogłem za pomocą ciekawego &lt;a href="http://polishlinux.org/choose/quiz/"&gt;quizu&lt;/a&gt;. Sugerował mi Ubuntu, Debiana lub Fedorę, ale to na pewno skutek zaznaczenia odpowiedzi "chcę mieć wszystko na talerzu, nie ważne jak". Zatem z przekory nie wybrałem tego, co otrzymałem w odpowiedzi. :)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Padło na &lt;a href="http://www.archlinux.org/"&gt;Arch Linux&lt;/a&gt;.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Kilka uwag odnośnie instalacji:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;to nie jest distro dla początkujących&lt;/li&gt;&lt;li&gt;do testów można użyć VirtualBox, ale u mnie nie działał prawidłowo XFCE;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;instalacja "ftp" dostarcza tylko kilkadziesiąt niezbędnych pakietów - zostajesz z terminalem i kontem roota sam na sam&lt;/li&gt;&lt;li&gt;pacman (manager pakietów)  świetnie sobie radzi z zależnościami, pakiety .tgz instalują się błyskawicznie&lt;/li&gt;&lt;li&gt;trzeba spędzić trochę czasu na konfiguracji środowiska, bo instaluje się tylko to, czego się potrzebuje; może to potrwać łącznie kilka dni, mimo że sama instalacja podstawowa (core + X + XFCE + Firefox) to ok 2h roboty (jeszcze uważając, żeby poprzednie distro w razie czego też działało)&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Użytkowanie:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;szybki jak cholera (ext4 + paczki skompilowane pod nowszą architekturę 686/x64), startup do gdm`a to ok 15s (bootchart z moimi custom usługami wskazuje 19s), XFCE startuje ok 5s z Guake i Gajim; gdyby nie softy gnome, to jeszcze byłoby szybciej, ale potrzebuję ich.&lt;/li&gt;&lt;li&gt;wybrane usługi można odpalać równolegle (w tle)&lt;/li&gt;&lt;li&gt;konfiguracja systemu leży w /etc/; wrócił stary, dobry rc.conf, rc.d i inittab&lt;/li&gt;&lt;li&gt;xfce wyraźnie szybsze od Ubuntu, nawet Firefox reaguje żwawiej.&lt;/li&gt;&lt;li&gt;jeśli chcę, używam Alsy, nikt nie wciska mi PulseAudio i problemów z nim związanych&lt;/li&gt;&lt;/ol&gt;Wady (?):&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;przyzwyczaiłem się, że dziś niemal każdy soft dostępny jest do instalacji w deb`ach lub ma swoje repa; tu zostaje kompilacja, ale mało używam takiego "nietypowego" softu, a poza tym kompilacja nie jest straszna.&lt;/li&gt;&lt;li&gt;prostota, szybkość, pełna kontrola nad konfiguracją uzależnia&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-4418325440127074405?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/4418325440127074405/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=4418325440127074405' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/4418325440127074405'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/4418325440127074405'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2009/04/arch-linux-zamiast-ubuntu.html' title='Arch Linux zamiast Ubuntu'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-2637494272678584258</id><published>2009-04-23T21:10:00.006+02:00</published><updated>2009-04-30T06:54:36.178+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='django'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programowanie'/><title type='text'>Django - ciągle zaskakuje</title><content type='html'>Przejście z PHP/Symfony na Python/Django wymusza inne spojrzenie na architekturę aplikacji i projektów. Na każdym kroku wyzbywam się złych przyzwyczajeń i uczę się nowej filozofii.&lt;br /&gt;Dziś chcę podzielić się kilkoma istotnymi uwagami, tak z punktu widzenia newbie. Jednocześnie zaznaczam, że tekst nie jest skierowany do wyjadaczy Django, a dla ludzi przechodzących na jasną stronę mocy.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Aplikacje Django&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Nie są aplikacjami w rozumieniu aplikacji Symfony. Są to swego rodzaju pluginy, które dostarczają elementów całemu projektowi. Tymi elementami (klockami) są: widoki (kontrolery), szablony, formularze, widgety, helpery, modele danych, katalogi tłumaczeń.&lt;br /&gt;W przeciwieństwie do Symfony można używać ich z poziomu innych aplikacji (w końcu rozumiem termin reusable apps ;).&lt;br /&gt;&lt;br /&gt;Projekt Django może być odpowiednikiem aplikacji Symfony, jednakże są pewne różnice. Główna to taka, że projekt może dostarczać i używać innych aplikacji.&lt;br /&gt;&lt;br /&gt;Moje nowe projekty buduję po prostu z pakietów zawierających aplikacje Django i inne potrzebne do działania systemu pakiety/moduły.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Szablony&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Nie ma potrzeby wpisywania ręcznie ścieżek do szablonów. Django ma wbudowany resolver &lt;span style="font-weight: bold;"&gt;django.template.loaders.app_directories.load_template_source&lt;/span&gt;, który dodaje ścieżki poszukiwań szablonów na podstawie wpisów w &lt;span style="font-weight: bold;"&gt;settings.INSTALLED_APPS&lt;/span&gt; (uwaga, kolejność ma znaczenie!)&lt;br /&gt;&lt;br /&gt;Ponad to Django dostarcza loader szablonów z paczek egg &lt;span style="font-weight: bold;"&gt;django.template.loaders.eggs.load_template_source&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Batchadmin i Grappelli.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Grappeli to aplikacja modyfikująca i rozszerzająca aplikację panelu administracyjnego.&lt;br /&gt;Dostarcza własne szablony przesłaniając szablony bazowe.&lt;br /&gt;&lt;br /&gt;Gdy używałem jeszcze aplikacji batchadmin (operacje grupowe na listach), to miałem problem z pogodzeniem tych dwóch rozwiązań. Batchadmin używa własnego szablonu "batchadmin/change_list.html". Dopiero niedawno zrozumiałem, jak mogę rozszerzyć ten szablon w widoku dla moich modeli.&lt;br /&gt;&lt;br /&gt;Rozwiązanie jest proste - należy ustawić class property "change_list_template" twojej klasy ModelAdmin na wlasny szablon, w którym umieszcza się na początku dyrektywę &lt;blockquote&gt;{% extends "batchadmin/change_list.html" %}&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Settings&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;strike&gt;W aplikacji Grappelli zauważyłem plik settings.py. Wygląda na to, że Django samo wciąga settings.py z zarejestrowanych aplikacji.&lt;/strike&gt;&lt;br /&gt;&lt;br /&gt;Sprawdziłem. Grappelli używa swoich ustawień z modułu grappelli.settings, a nie django.settings. Użyto ciekawej konwencji:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;from django import settings&lt;br /&gt;&lt;br /&gt;FOO = getattr(settings, 'FOO', 'bar')&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Panel admina django&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To jest "tylko" kolejna aplikacja, która jedynie wykonuje swoje konkretne zadanie - umożliwia przeglądanie, wyszukiwanie i modyfikację danych. Nie jest częscią Django w rozumieniu frameworka, dlatego umieszczono ją w katalogu contrib. Używa po prostu mechanizmów samego frameworka (mvc, orm, formy, walidacja, itd) do generowania widoków. Sama dostarcza&lt;br /&gt;kilka widgetów, plikow css, templates i templatetags.&lt;br /&gt;&lt;br /&gt;Dlatego nie można patrzec na nią, jak na admin-generator z Symfony, który jest jego&lt;br /&gt;integralną częscią. I w koncu dlatego też można aplikacje admina&lt;br /&gt;Django dowolnie rozszerzać i rozwijać - projektujesz własną aplikację panelu administracyjnego&lt;br /&gt;używają aplikacji &lt;span style="font-weight: bold;"&gt;django.contrib.admin&lt;/span&gt;, albo jej nie używasz pisząć swoją aplikację panelu od nowa.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;django.contrib&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Po powyższych wnioskach sprawdziłem zawartość pakietu &lt;span style="font-weight: bold;"&gt;django.contrib&lt;/span&gt;. Doznałem lekkiego szoku. Zawarte są w nim ciekawe i użyteczne aplikacje. Tu wspomnę jedynie o kilku:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;flatpages - proste, edytowalne strony, jakie zwykle osadza się w prostych websites&lt;/li&gt;&lt;li&gt;formtools - narzędzia do pracy z formularzami na wyższym poziomie abstrakcji, głównie &lt;span style="font-weight: bold;"&gt;wizard&lt;/span&gt; i podgląd formularza&lt;/li&gt;&lt;li&gt;localflavor - baza krajów wg normy ISO, formattery wg locales (L10N)&lt;/li&gt;&lt;li&gt;sitemaps - integracja z google sitemaps&lt;/li&gt;&lt;li&gt;syndication - RSS feeds&lt;/li&gt;&lt;li&gt;webdesign - dostarcza generator loremipsum :)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;Życzę wszystkim sukcesów na nowej drodze!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-2637494272678584258?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/2637494272678584258/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=2637494272678584258' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/2637494272678584258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/2637494272678584258'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2009/04/django-ciagle-zaskakuje.html' title='Django - ciągle zaskakuje'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-5005665341988386920</id><published>2009-03-01T18:29:00.005+01:00</published><updated>2010-03-27T17:51:03.273+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='humor'/><category scheme='http://www.blogger.com/atom/ns#' term='programowanie'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>CMS Made Simple - kontynuacja</title><content type='html'>Chyba poświęcę cały dział dla CMSMS.&lt;br /&gt;&lt;br /&gt;1. (nie)-zdecydowanie? &lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;* Insert the content in the db&lt;br /&gt;:TODO: This function should return something&lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;2. Polecam zagłębić się w sposób obsługiwania hierarchii.&lt;br /&gt;&lt;br /&gt;Model Content ma ku temu kilka właściwości: parent_id, hierarchy, id_hierarchy, hierarchy_path. O ile parent_id i id_hierarchy to rozwiązanie w postaci ścieżki zmaterializowanej, to reszta jest absolutnym nadmiarem.&lt;br /&gt;&lt;br /&gt;hierarchy_path to ścieżka aliasów - może być, żeby zminimalizować lookup do bazy, ale nonses przy użyciu ORM-a z instance poolingiem.&lt;br /&gt;&lt;br /&gt;Kompletnym nieporozumieniem jest kolumna hierarchy - zawiera index wpisu w hierarchii. Każda zmiana kolejności, miejsca w hierarchii jakiegokolwiek elementu wymaga przeliczenia indexów. Co gorsza pole hierarchy jest używane przez frontend do wybierania elementów podrzędnych. Toteż dwa rekordy z identyczną zawartością hierarchy powodują błędy wyświetlania. W moim przypadku kategoria bluzy zawierała również produkty z kategorii t-shirty. &lt;br /&gt;&lt;br /&gt;Nie miałbym żadnych zastrzeżeń, gdyby:&lt;br /&gt;- oprogramowanie miało jakiekolwiek end-user api&lt;br /&gt;- baza danych posiadała by odpowiednie procedury lub triggery&lt;br /&gt;- autorzy dowiedzieli się, czym są indexy unique (i klucze główne)&lt;br /&gt;&lt;br /&gt;W tej chwili wynajduję funkcje "naprawiające" content i przepisuję je do mojego api w python, aby integracja przebiegała sprawnie.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-5005665341988386920?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/5005665341988386920/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=5005665341988386920' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/5005665341988386920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/5005665341988386920'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2009/03/cms-made-simple-kontynuacja.html' title='CMS Made Simple - kontynuacja'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-724413381313045975</id><published>2009-01-30T02:05:00.005+01:00</published><updated>2009-04-30T06:35:04.046+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='programowanie'/><title type='text'>Dlaczego Python</title><content type='html'>1. bo prosto, szybko, wygodnie, logicznie, wydajnie, obiektowo, modularnie&lt;br /&gt;2. bo django, turbogears, sqlalchemy&lt;br /&gt;3. bo pep-y, kiss, dry&lt;br /&gt;4. bo w końcu język programowania...&lt;br /&gt;&lt;br /&gt;good bye php forever&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-724413381313045975?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/724413381313045975/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=724413381313045975' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/724413381313045975'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/724413381313045975'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2009/01/dlaczego-python.html' title='Dlaczego Python'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-1006252388464236878</id><published>2009-01-30T01:53:00.004+01:00</published><updated>2009-01-30T02:03:41.038+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gotowce'/><category scheme='http://www.blogger.com/atom/ns#' term='cms'/><category scheme='http://www.blogger.com/atom/ns#' term='programowanie'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>Cms Made Simple</title><content type='html'>Wspominałem już kiedyś o tym dziadostwie.&lt;br /&gt;Teraz mam nieprzyjemność integrować moje narzędzie z projektem postawionyn na CmsMadeSimple.&lt;br /&gt;Api toto nie posiada, więc trzeba ryć do bazy. Wszystko szło ok, aż do czasu dodawania nowych rekordów. Pojawił się kłopot z kluczami głównymi (których swoją drogą czasem w ogóle nie ma)&lt;br /&gt;&lt;br /&gt;Znalazłem ciekawy wątek w tym temacie:&lt;br /&gt;&lt;a href="http://forum.cmsmadesimple.org/index.php/topic,7131.0.html"&gt;http://forum.cmsmadesimple.org/index.php/topic,7131.0.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Gratuluję pomysłowości. Powinienem się śmiać, ale tracę czas. Dobrze, że mi za tę robotę płacą...&lt;br /&gt;&lt;br /&gt;Nara.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-1006252388464236878?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/1006252388464236878/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=1006252388464236878' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/1006252388464236878'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/1006252388464236878'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2009/01/cms-made-simple.html' title='Cms Made Simple'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-7802963460995927076</id><published>2008-09-13T13:37:00.006+02:00</published><updated>2008-09-13T13:50:03.163+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='narzędzia'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='xfce'/><category scheme='http://www.blogger.com/atom/ns#' term='tips'/><category scheme='http://www.blogger.com/atom/ns#' term='gnome'/><title type='text'>Ubuntu 8.04 - XFCE i Tilda 0.9.6 (konsola quake)</title><content type='html'>&lt;a href="http://tilda.sourceforge.net/wiki/index.php/Main_Page"&gt;Tilda&lt;/a&gt; to konsola w stylu Quake idealna dla Gnome/XFCE. Dotychczas używałem Yakuake i jest ok, ale ja nie chciałem używac softu dla KDE ze wzgledu na minimalizację zużycia pamięci.&lt;br /&gt;&lt;br /&gt;Tilda znajduje się defaultowo w distro Ubuntu, niestety w wersji 0.9.5pre, która ma irytujący bug związany z brakiem focusa okna - uaktywniasz konsolę, ale piszesz nadal w poprzednio używanym oknie.&lt;br /&gt;Na szczęście bug usunięto w wersji 0.9.6, której niestety nie ma w repo Ubuntu.&lt;br /&gt;&lt;br /&gt;Na szczęście kompilacja nie jest problematyczna:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;$ wget http://downloads.sourceforge.net/tilda/tilda-0.9.6.tar.gz&lt;br /&gt;$ sudo apt-get install libglib2.0-dev libgtk2.0-dev libvte-dev libconfuse-dev flex libglade2-dev build-essential&lt;br /&gt;&lt;br /&gt;$ ./configure --prefix=/usr/local&lt;br /&gt;$ make&lt;br /&gt;$ sudo make install&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-7802963460995927076?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/7802963460995927076/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=7802963460995927076' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/7802963460995927076'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/7802963460995927076'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2008/09/ubuntu-804-xfce-i-tilda-konsola-quake.html' title='Ubuntu 8.04 - XFCE i Tilda 0.9.6 (konsola quake)'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-6422748015747923882</id><published>2008-09-11T22:14:00.003+02:00</published><updated>2008-09-11T22:20:46.029+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='wzorce obiektowe'/><category scheme='http://www.blogger.com/atom/ns#' term='webdeveloper'/><category scheme='http://www.blogger.com/atom/ns#' term='ioc'/><category scheme='http://www.blogger.com/atom/ns#' term='programowanie'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='oop'/><title type='text'>Symfony IoC container - sfIocPlugin</title><content type='html'>Implementując logikę biznesową mojej aplikacji nie mogłem już wytrzymać bez jakiegoś kontenera IoC. Marzył mi się IoC ze &lt;a href="http://www.springframework.org/"&gt;Springa&lt;/a&gt;. Nie znalazłem jakiegoś sensownego odpowiednika, więc postanowiłem zrobić własną implementację jakiejś jego drobnej części. A ponieważ jeszcze używam Symfony, utworzyłem plugin do tego frameworka.&lt;br /&gt;&lt;br /&gt;Jeśli jeszcze nie znasz IoC, to na początek polecam zapoznać się z &lt;a href="http://en.wikipedia.org/wiki/Inversion_of_control"&gt;definicją IoC&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://code.google.com/p/sfiocplugin/"&gt;Odwiedź stronę projektu sfIoCPlugin&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-6422748015747923882?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/6422748015747923882/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=6422748015747923882' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/6422748015747923882'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/6422748015747923882'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2008/09/symfony-ioc-container-sfiocplugin.html' title='Symfony IoC container - sfIocPlugin'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-3110793365816705359</id><published>2008-07-04T08:11:00.001+02:00</published><updated>2008-07-04T08:13:13.404+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='firefox'/><category scheme='http://www.blogger.com/atom/ns#' term='przeglądarki'/><title type='text'>Firefox - rekord Guinessa pobity</title><content type='html'>Ponad 8mln pobrań Firefoxa 3 w ciągu 24h - ustanowiony rekord. Gratuluję.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-3110793365816705359?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/3110793365816705359/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=3110793365816705359' title='Komentarze (1)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/3110793365816705359'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/3110793365816705359'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2008/07/firefox-rekord-guinessa-pobity.html' title='Firefox - rekord Guinessa pobity'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-2958992139435039363</id><published>2008-07-04T08:06:00.002+02:00</published><updated>2008-07-04T08:11:21.433+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='webdeveloper'/><category scheme='http://www.blogger.com/atom/ns#' term='programowanie'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>PHP - wycieki pamięci</title><content type='html'>Ostatni release PHP (5.2.6) przychodzi z fixami cieknących błędów:&lt;br /&gt;&lt;br /&gt;- Fixed bug #43450 (Memory leak on some functions with implicit object __toString() call).&lt;br /&gt;- Fixed bug #41562 (SimpleXML memory issue)&lt;br /&gt;- Fixed bug #42369 (Implicit conversion to string leaks memory)&lt;br /&gt;- Fixed bug #44069 (Huge memory usage with concatenation using . instead of .=)&lt;br /&gt;&lt;br /&gt;Cieszy, ale też straszy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-2958992139435039363?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/2958992139435039363/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=2958992139435039363' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/2958992139435039363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/2958992139435039363'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2008/07/php-wycieki-pamici.html' title='PHP - wycieki pamięci'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-4774108917237209324</id><published>2008-07-04T07:46:00.006+02:00</published><updated>2010-03-27T17:51:47.066+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='przemyślenia'/><category scheme='http://www.blogger.com/atom/ns#' term='narzędzia'/><category scheme='http://www.blogger.com/atom/ns#' term='programowanie'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>PHP6 dla aplikacji klasy enterprise</title><content type='html'>A g.... prawda. Kiedy czytam noty o funkcjonalności PHP6, a szczególnie z czego zrezygnowano, utwierdzam się w przekonaniu o migracji do normalnego języka programowania (Java/Python).&lt;br /&gt;&lt;br /&gt;Rozwijanie dużego softu przy użyciu PHP kojarzy mi się ze świadczeniem usług transportowych przy użyciu furmanki - niby zawsze możesz zwiększyć zaprzęg, ale gówna i tak się nie pozbędziesz&lt;br /&gt;&lt;br /&gt;Co mnie wkurzyło:&lt;br /&gt;- KISS - autorzy PHP są święcie przekonani, że rozumieją zasadę KISS (gdyby rozumieli, PHP nie byłby tak bałaganiarski)&lt;br /&gt;- zapomnijmy o named parameters - autorzy uważają, że to bzdura (naczytali się o KISS)&lt;br /&gt;- fatal errors nie będą wyjątkami - tu autorzy też nie są wyjątkowi (trzymają się KISS); z resztą co im to by dało, skoro informacje o błędach przy łączeniu przez ftp_open() trzeba zeskrobywać z ekranowych warningów&lt;br /&gt;- blok finally { } nie zostanie wprowadzony do sekwencji try..catch (KISS, bo wyjątki dla autorów to temat trudny przecież)&lt;br /&gt;- nie poprawią GC dla długo wykonywanych skryptów&lt;br /&gt;- zwalony unicode (uparli się na UTF-16)&lt;br /&gt;- nie uporządkują API standardowych funkcji (a mogliby - na rzecz pakietów obiektowych)&lt;br /&gt;&lt;br /&gt;Cóż, nie chce mi się stawiać PHP6 dla napisania website-u z pięcioma stronami. Java czeka.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-4774108917237209324?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/4774108917237209324/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=4774108917237209324' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/4774108917237209324'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/4774108917237209324'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2008/07/php6-dla-aplikacji-klasy-enterprise.html' title='PHP6 dla aplikacji klasy enterprise'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-4766789181344792044</id><published>2008-01-27T16:16:00.000+01:00</published><updated>2008-01-27T16:30:23.651+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='propel'/><category scheme='http://www.blogger.com/atom/ns#' term='webdeveloper'/><category scheme='http://www.blogger.com/atom/ns#' term='orm'/><category scheme='http://www.blogger.com/atom/ns#' term='oop'/><title type='text'>Symfony - Propel class table inheritance</title><content type='html'>Doszukałem się dość ciekawego rozwiązania realizującego dziedziczenie na wielu tabelach.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.symfony-project.org/snippets/snippet/218"&gt;propel behavior to extend classes with separate tables&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-4766789181344792044?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/4766789181344792044/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=4766789181344792044' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/4766789181344792044'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/4766789181344792044'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2008/01/symfony-propel-class-table-inheritance.html' title='Symfony - Propel class table inheritance'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-3122553252472227490</id><published>2008-01-21T19:30:00.000+01:00</published><updated>2008-01-21T19:38:38.167+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='webdeveloper'/><category scheme='http://www.blogger.com/atom/ns#' term='narzędzia'/><category scheme='http://www.blogger.com/atom/ns#' term='programowanie'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>PHP 5.2.5 - zabawy autorów z glob()</title><content type='html'>Najnowsza odsłona PHP przynosi kolejny feature z kategorii niekompatybilności.&lt;br /&gt;&lt;br /&gt;Widocznie po rozwaleniu strtotime() od wersji 5.2.3 autorom było mało i postanowili dodać życiu smaczek zmieniając api funkcji glob().&lt;br /&gt;&lt;br /&gt;W przypadku nieznalezienia plików pasujących do wzorca funkcja glob() zwracała pustą tablicę, teraz zwraca false. Nie tylko generejue to warningi, ale w efekcie paraliżuje projekty, których core opiera się m.in. na tej funkcji.&lt;br /&gt;&lt;br /&gt;Poprawka jest szybka - zwrot z glob() wystarczy castować do tablicy.&lt;br /&gt;&lt;br /&gt;Do tego funkcja niemiłosiernie się wlecze. Prawdopodobnie efekt ten występuje tylko w połączeniu z safe_mode, ale jednak.&lt;br /&gt;&lt;br /&gt;Dziękujemy autorom za kolejny zestaw wrażeń. Za "float + locale z przecinkiem" - też.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-3122553252472227490?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/3122553252472227490/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=3122553252472227490' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/3122553252472227490'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/3122553252472227490'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2008/01/php-525-zabawy-autorw-z-glob.html' title='PHP 5.2.5 - zabawy autorów z glob()'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-6926463984481836578</id><published>2008-01-07T20:06:00.000+01:00</published><updated>2008-01-07T20:22:20.296+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='webdeveloper'/><category scheme='http://www.blogger.com/atom/ns#' term='gotowce'/><category scheme='http://www.blogger.com/atom/ns#' term='cms'/><category scheme='http://www.blogger.com/atom/ns#' term='programowanie'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='oop'/><title type='text'>Gdzie się podziało OOP</title><content type='html'>Szukam softu, na którym postawię prosty site z możliwością dalszej rozbudowy. Wygodnej, prostej, logicznej rozbudowy. Chyba zaczynam żałować, że jestem programistą... ;)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Drupal - index.php (fragment)&lt;/h4&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;[...]&lt;br /&gt;$return = menu_execute_active_handler();&lt;br /&gt;&lt;br /&gt;// Menu status constants are integers; page content is a string.&lt;br /&gt;if (is_int($return)) {&lt;br /&gt;    switch ($return) {&lt;br /&gt;        case MENU_NOT_FOUND:&lt;br /&gt;            drupal_not_found();&lt;br /&gt;            break;&lt;br /&gt;        case MENU_ACCESS_DENIED:&lt;br /&gt;            drupal_access_denied();&lt;br /&gt;            break;&lt;br /&gt;        case MENU_SITE_OFFLINE:&lt;br /&gt;            drupal_site_offline();&lt;br /&gt;            break;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;[...]&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;ezPublish 4.0.0 index.php&lt;/h4&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;marcin@debian:~/Desktop/ezpublish-4.0.0$ wc index.php&lt;br /&gt;1160  3798 40501 index.php&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;    marcin@debian:~/Desktop/ezpublish-4.0.0$ egrep "function [^(]+\(" index.php&lt;br /&gt;    function eZUpdateDebugSettings()&lt;br /&gt;    function eZUpdateTextCodecSettings()&lt;br /&gt;    function eZAppendWarningItem( $parameters = array() )&lt;br /&gt;    function eZDBCleanup()&lt;br /&gt;    function eZFatalError()&lt;br /&gt;    function eZDisplayDebug()&lt;br /&gt;    function eZDisplayResult( $templateResult )&lt;br /&gt;    function fetchModule( $uri, $check, &amp;$module, &amp;$module_name, &amp;$function_name, &amp;$params )&lt;br /&gt;    function eZSessionBasketDestroy( $db, $key, $escapedKey )&lt;br /&gt;    function eZSessionBasketGarbageCollector( $db, $time )&lt;br /&gt;    function eZSessionBasketEmpty( $db&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;Typolight 2.5 index.php:&lt;/h4&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * Run the controller&lt;br /&gt; */&lt;br /&gt;public function run()&lt;br /&gt;{&lt;br /&gt;global $objPage;&lt;br /&gt;&lt;br /&gt;[..]&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;h4&gt;CmsMadeSimple 1.2.3 - index.php:&lt;/h4&gt;&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;if ($page == '')&lt;br /&gt;{&lt;br /&gt;    global $gCms;&lt;br /&gt;  [...]&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Emulacja klasy Request:&lt;/p&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;$params = array_merge($_GET, $_POST);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;View layer:&lt;/p&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;$smarty = &amp;$gCms-&gt;smarty;&lt;br /&gt;$smarty-&gt;params = $params;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;"P... nie robie" ;)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-6926463984481836578?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/6926463984481836578/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=6926463984481836578' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/6926463984481836578'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/6926463984481836578'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2008/01/gdzie-si-podziao-oop.html' title='Gdzie się podziało OOP'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-8586845251867485091</id><published>2008-01-06T14:30:00.000+01:00</published><updated>2008-01-06T15:25:02.811+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='symfony'/><category scheme='http://www.blogger.com/atom/ns#' term='propel'/><category scheme='http://www.blogger.com/atom/ns#' term='webdeveloper'/><category scheme='http://www.blogger.com/atom/ns#' term='mvc'/><category scheme='http://www.blogger.com/atom/ns#' term='programowanie'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='oop'/><title type='text'>Symfony - kandydat na najlepszy framework PHP?</title><content type='html'>&lt;h4&gt;Mija rok, a tu ciągle Symfony...&lt;/h4&gt;&lt;br /&gt;&lt;p&gt;Niedługo minie rok, od kiedy zacząłem zaznajamiać się z &lt;a href="http://symfony-project.com"&gt;Symfony&lt;/a&gt;.&lt;br /&gt;Framework dostarcza znakomicie zrealizowaną implementację MVC oraz ORM oparty na &lt;a href="http://propel.phpdb.org/"&gt;Propelu&lt;/a&gt;&lt;br /&gt;(dostępna jest też wtyczka &lt;a href="http://trac.symfony-project.com/wiki/sfDoctrinePlugin"&gt;sfDoctrinePlugin&lt;/a&gt; dla &lt;a href="http://www.phpdoctrine.net/"&gt;Doctrine&lt;/a&gt;).&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Do tego czasu miałem dreszcze, kiedy przeglądałem rozwiązania open-source dla PHP. Obiektowość na poziomie PHP4 była rarytasem, nie wspominając o wielkich oporach korzystania z dobrodziejstw OOP z PHP5. Uważam, że Fabien Potencier dokonał przełomu.&lt;/p&gt;&lt;br /&gt;&lt;h4&gt;Propel&lt;/h4&gt;&lt;br /&gt;&lt;p&gt;Wcześniej nie znałem tak elastycznego rozwiązania dla PHP, więc żyłem w świadomości, że najlepszy framework zrobię sam.&lt;br /&gt;Miałem już ciekawe rozwiązanie, w którym jednak najdotkliwiej kulał ORM. Na szczęście Fabien wydał stabilną wersję Symfony&lt;br /&gt;i nie musiałem już tracić czasu na debug i poprawki. Z resztą i tak mój ORM miał się nijak do znakomicie zaprojektowanego Propela.&lt;br /&gt;&lt;p&gt;Jego architektura umożliwia budowanie logicznie skonstruowanego API. Klasy modeli danych są początkowo puste, dziedzicząc&lt;br /&gt;jednocześnie po klasach automatycznie wygenerowanych na podstawie schematu bazy danych. W tym miejscu programsta ma pole do popisu - zaczyna implementować interfejsy, przeciążać wygenerowane metody, pisać metody pomocnicze. Dodatkowo Propel umożliwia bardzo łatwe wykonanie transparentnej implementacji wzorca fabryki.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;O wykorzystaniu Propela jako podstawy do zaprojektowania dobrego API napiszę niedługo w innym wpisie.&lt;/P&gt;&lt;br /&gt;&lt;h4&gt;Wydajność&lt;/h4&gt;&lt;br /&gt;&lt;p&gt;Największe zarzuty do Symfony dotyczyły wydajności. Jednak framework opiera się na zasadzie cache`owania wszystkiego, co się da - począwszy od konfiguracji, aż po cache wygenerowanych klas automatycznych. Ponadto istnieje sporo wtyczek z działu "&lt;a href="http://trac.symfony-project.com/wiki/SymfonyPlugins#Performance"&gt;performance&lt;/a&gt;". Na dokładkę &lt;a href="http://propel.phpdb.org/trac/wiki/Users/Documentation/1.3"&gt;Propel 1.3&lt;/a&gt;, w wyniku przejścia z Creole na PDO, osiąga wg benchmarków dwukrotny zysk wydajności w stosunku do wersji 1.2. Nie znam rozwiązania oferującego tak wiele i będącego jednocześnie wystarczająco wydajnym (no może Python + django, ale zostańmy przy PHP).&lt;/p&gt;&lt;br /&gt;&lt;h4&gt;Ciekawe wtyczki&lt;/h4&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://trac.symfony-project.com/wiki/sfPropelActAsTaggableBehaviorPlugin"&gt;sfPropelActAsTaggableBehaviorPlugin&lt;/a&gt; - umożliwia tago&lt;br /&gt;wanie modeli danych, dodaje możliwość generowania tag-cloud&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://trac.symfony-project.com/wiki/sfPropelParanoidBehaviorPlugin"&gt;sfPropelParanoidBehaviorPlugin&lt;/a&gt; - wyłącza rzeczywiste usuw&lt;br /&gt;anie obiektów poprzez wprowadzenie flagi &lt;code&gt;deleted_at&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://trac.symfony-project.com/wiki/sfPropelVersionableBehaviorPlugin"&gt;sfPropelVersionableBehaviorPlugin&lt;/a&gt; - dostarcza mechaniz&lt;br /&gt;m wersjonowania modeli danych&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://trac.symfony-project.com/wiki/sfPropel13Plugin"&gt;sfPropel13Plugin&lt;/a&gt; - umożliwia użycie Propela w wersji 1.3 bez koniecznoś&lt;br /&gt;ci zmian core-owych w Symfony&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://trac.symfony-project.com/wiki/sfModelTestPlugin"&gt;sfModelTestPlugin&lt;/a&gt; - już nie będziesz miał problemów z uruchomieniem un&lt;br /&gt;it testów dla modeli danych&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p&gt;Ponad to testowałem wtyczki udostępniające gotowe rozwiązania, jak blog, prosty cms, forum (admin nie działał), newsy. Wszystkie (z małym wy&lt;br /&gt;jątkiem z forum) działały od razu i bez problemów. Jedyny mankament to brak spójności - wymienione pluginy nie korzystają ze wspólnych szablonó&lt;br /&gt;w i wdrażając bardziej rozbudowany projekt trzeba zająć się szablonami dla każdego modułu z osobna.&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Więcej wtyczek znajdziesz na &lt;a href="http://trac.symfony-project.com/wiki/SymfonyPlugins"&gt;http://trac.symfony-project.com/wiki/SymfonyPlugi&lt;br /&gt;ns&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;h4&gt;Warto odwiedzić&lt;/h4&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.symfony.pl/"&gt;Symfony framework po polsku&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://pl.wikipedia.org/wiki/Symfony"&gt;Wikipedia o Symfony&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.symfony-project.org/book/1_1/"&gt;Dokumentacja Symfony 1.1&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.symfony-project.org/api/1_1/"&gt;Symfony API&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-8586845251867485091?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/8586845251867485091/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=8586845251867485091' title='Komentarze (3)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/8586845251867485091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/8586845251867485091'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2008/01/symfony-kandydat-na-najlepszy-framework.html' title='Symfony - kandydat na najlepszy framework PHP?'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-6342404516579608236</id><published>2007-08-19T22:37:00.001+02:00</published><updated>2007-08-19T22:47:46.539+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='narzędzia'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='konsola'/><category scheme='http://www.blogger.com/atom/ns#' term='rss'/><title type='text'>Newsbeuter - czytnik RSS w konsoli</title><content type='html'>Kolejny mały program umilający życie :)&lt;br /&gt;&lt;br /&gt;Czytnik RSS pracujący w konsoli, a co równie ważne - umożliwia czytanie newsów z zabezpieczonych hasłem kanałów (wystarczy podać URL z loginem i hasłem).&lt;br /&gt;&lt;br /&gt;Konfiguracja jest prosta. Wystarczy utworzyć plik ~/.newsbeuter/urls i wpisać do niego co najmniej jeden adres. Bez tego pliku program się nie uruchomi.&lt;br /&gt;&lt;br /&gt;Newsbeuter ma intuicyjną obsługę wg standardu znanego z mutt. Cud, malina, miód. :)&lt;br /&gt;&lt;br /&gt;&lt;a href="http://freshmeat.net/projects/newsbeuter/?branch_id=68056&amp;amp;release_id=259782"&gt;Opis programu na freshmeat.net (homepage nie odpowiada)&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-6342404516579608236?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/6342404516579608236/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=6342404516579608236' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/6342404516579608236'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/6342404516579608236'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2007/08/newsbeuter-czytnik-rss-w-konsoli.html' title='Newsbeuter - czytnik RSS w konsoli'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-5468435621575469148</id><published>2007-08-19T22:12:00.000+02:00</published><updated>2007-08-19T22:25:01.978+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='organizer'/><category scheme='http://www.blogger.com/atom/ns#' term='narzędzia'/><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='konsola'/><title type='text'>Calcurse - kalendarz i lista to-do w konsoli</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_3L0U9hzJIZw/RsimU8uEjlI/AAAAAAAAAA0/rg-lvsVQHBQ/s1600-h/calcurse.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: none; cursor: pointer;" src="http://2.bp.blogspot.com/_3L0U9hzJIZw/RsimU8uEjlI/AAAAAAAAAA0/rg-lvsVQHBQ/s320/calcurse.jpg" alt="" id="BLOGGER_PHOTO_ID_5100509456824045138" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Prosty kalendarz z eventami (calodniowe lub w wyznaczonym przedziale czasowym) oraz z listą to-do. Intuicyjna obsługa (kto lubi Vim-a, ten sie odnajdzie od razu), konfigurowanie layoutu, kolorów i typowych zachowań (auto-save, pytanie przy wyjściu). Gotowy do pracy bez zaglądania w pliki konfiguracyjne.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://culot.org/calcurse/"&gt;http://culot.org/calcurse/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Instalacja (debian)&lt;br /&gt;&lt;blockquote&gt;apt-get install calcurse&lt;br /&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-5468435621575469148?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/5468435621575469148/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=5468435621575469148' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/5468435621575469148'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/5468435621575469148'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2007/08/calcurse-kalendarz-i-lista-to-do-w.html' title='Calcurse - kalendarz i lista to-do w konsoli'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_3L0U9hzJIZw/RsimU8uEjlI/AAAAAAAAAA0/rg-lvsVQHBQ/s72-c/calcurse.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-3286781719988197774</id><published>2007-08-17T22:32:00.001+02:00</published><updated>2010-03-27T17:50:38.473+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='koncert'/><category scheme='http://www.blogger.com/atom/ns#' term='muzyka'/><title type='text'>Offfestival 2007 Mysłowice - prawdziwa alternatywa</title><content type='html'>Off'2006 był zaskoczeniem. Nieznani wykonawcy, niska cena biletów, relatywnie ogromna ilość zaproszonych zespołów  i oczywiście znajomość twórzczości zespołu Myslowitz (lider, Artur Rojek, jest dyrektorem artystycznym festiwalu) - to czynniki, które wpłynęły na moje sceptyczne nastawienie do imprezy. Wrazenia byly jednak niesamowite.&lt;br /&gt;Poznałem repertuar wielu wykonawców, zacząłem przedzierać się przez nieznane wcześniej gatunki muzyczne.  Byłem wdzięczny Rojkowi zawykonany kawał dobrej roboty. Banco de Gaia, Sofa Surfers, rodzimy Skalpel to nie jedyni wykonawcy, którzy swoją muzyką i oprawą sceniczną wywołali u mnie syndrom tak zwanego "opadu szczęki", a Mitch&amp;Mitch powodowali nieustanne ataki bólu pęcherza i problemy ze złapaniem tchu.&lt;br /&gt;&lt;br /&gt;Tegoroczny Festiwal jest rownież zaskoczeniem. Odwrotnym. Ale od początku.&lt;br /&gt;&lt;br /&gt;Przy wejściu otrzymaliśmy "rozkład jazdy" festiwalu. Skrupulatnie go przeanalizowałem i zapoznałem się z notkami o artystach. Sformułowania "ambient-jazz", "kochają ich krytycy, kochają ich fani", "grupa okrzyknięta rewelacją" powodowały rosnące w tempie huraganu natężenie wypieków na mojej twarzy.  Podczas gdy moja kochana partnerka sączyła piwo z sokiem, nie mogłem się doczekać momentu, kiedy ruszymy na podbój scen i utopimy się w zalewie nieodkrytych wcześniej aranżacji, brzmień, kompozycji.&lt;br /&gt;&lt;br /&gt;Ruszamy.  Scena leśna. Na podeście Starzy Singers. Jak donosi przewodnik off-festiwalowca, artyści udzielają się m.in. we wspomnianej grupie Mitch&amp;amp;Mitch. Po roku czasu ogłuchli. Wokalista darł się w niebogłosy, jakby go ze skóry obdzierano. Z fragmentów tekstu, który w tym zgiełku udało mi się zrozumieć wywnioskowałem, że obdziera go ze skóry jego kobieta życia. Mogę się mylić, ale jeśli właśnie to przekazał mi artysta, to powinien zapoznać się z terminem "rozwód". Nie tylko z kobietą. Słyszałem też, że w budowlance brakuje ludzi do roboty.&lt;br /&gt;Grupka młodzieży, która "tańczyła" w rytm bębnów nawołujących dziczyznę zamieszkującą okoliczne lasy, to chyba znajomi panienki, którą to niemal w trupa zaćpaną wynosili wcześniej ochroniarze.&lt;br /&gt;&lt;br /&gt;Na głównej scenie pustki, przygotowuje się zespół Ścianka. Jest trochę czasu, to gdzie właściwie jest ta trzecia scena? Kieruję się mapką z przewodnika off-festiwalowca. Dotarłem do budek Toi-Toi. Chyba podawano tam piwo. Albo przyjmowano z powrotem - nie zaglądałem. Minąwszy szereg plastikowych pomieszczeń dotarłem do końca festiwalu, a raczej jego terenu. O, przepraszam! To jakiś ochroniarz zasłonił strzałeczkę do sceny i za drugim razem trafiłem bez problemu na miejsce.&lt;br /&gt;&lt;br /&gt;Przewodnik zachęcał mnie występem Punk.Discorporation, ale nie było żadnej wzmianki o tej formacji. Scena trzecia okazała się salą w budynku mysłowickiego Muzeum Pożarnictwa. Niezły pomysł, bo to jedyna scena, na której równolegle z pozostałymi dwiema odbywały się występy. Przynajmniej miejsca te nie zakłócały się wzajemnie.&lt;br /&gt;Trzy rzutniki, wizualizacje, dwóch czy trzech kolegów za konsoletami, jeden z gitarą i jeden... wokalista. Prawie jak wokalista. Wtórował samplom pędzocym z głośników, ale co najmniej z różnicą połowy tonu. Widać, że młodzi zaczynają, więc im się daruje, ale dlaczego gibał się nierównomiernie, i to w sandałach?&lt;br /&gt;Pomijając różnice w naszych gustach muzycznych odniosłem wrażenie, że ktoś udusił realizatora dźwięku i posadził tam jego siostrzeńca-operatora młota pneumatycznego. Za głośno, lub co najmniej za dużo basu. Dźwięki z niskiego zakresu częstotliwości nie brzmiały. One pierdziały. Wychodzimy. Wrócimy na ambient-jazz.&lt;br /&gt;&lt;br /&gt;W tym samym czasie gra Ścianka. Podeszliśmy zrobić zdjęcie. Tylko zdjęcie. Trzech muzyków, jeden rąbiący polkę na bębach i dwóch wiecznie strojących swe rozjechane po każdym utworze gitary, odebrali nam ochotę na dzielenie z nimi naszego czasu. Dodam, że wokalista wpierwej wydawał nieartykułowane dźwięki, następnie wył jako wilk (lub wilczyca), aby ostatecznie śpiewać. Lepiej było jednak, kiedy wył.&lt;br /&gt;&lt;br /&gt;Na scenę leśną wchodzi kapela Dick4Dick. Notka o artystach była humorystyczna i sugerowała, że będzie dynamicznie i wesoło. Tym bardziej, że ich muzyka to "piorunująca mieszanka punk rocka, disco, electro i country". Pierwszy utwór - łomot. Drugi spokojniejszy, ale nie pamiętam go, bo nie zdążyłem pozbierać się po pierwszym. Później było disco. Następnie znowu trochę disco czy electro. Nawet przypominało mi nieco leciwy kawałek Blue Monday brytyjczyków z formacji New Order. Plagiatu nie znoszę, więc się podirytowałem. Kiedy artyści przeszli do beatu składającego się z rytmicznej stopy w tempie ok 160bpm oraz wlepionymi tu i ówdzie riffami z Master Of Puppets  zespołu Metallica, i samplami przypominającymi nieco utwór Lombardu, to mój poziom zażenowania przekroczył dopuszczalny dzienny limit. Może to dlatego, że spodziewałem się czegoś innego. Choćby mieszania styli, nowych muzycznych kreacji, niecodziennych prób i łączenia sprzeczności (punk-disco). Ale zespół najpierw wyłoił punka, a potem z play-a poszło disco.&lt;br /&gt;Że sztuka? Że młodzi, nowi? Że się uczą? Nie. Moim zdaniem nie mogą się uczyć, bo nie mają za grosz wrażliwości, za grosz estetyki. Dźwięki otaczają nas stale. Tylko wybrane są muzyką. Dick4Dick takich nie emituje.&lt;br /&gt;&lt;br /&gt;Pełni wrażeń nie dotarliśmy na Muariolanza (ambient-jazz). Żałuję, bo może grają ciekawie. Jednak ostatnie nadzieje wiązaliśmy z zagranicznymi wykonawcami i udaliśmy się w pobliże głównej sceny.  Wsłuchani w lekko irytujące transowe dźwięki czekaliśmy na The Low Frequency in Stereo z Norwegii.&lt;br /&gt;Są. Grają. Boże, czy ta kobieta siebie kiedykolwiek słyszała? Muzycznie nieciekawie. Prosto, bez pomysłu. Czekamy na kolejny utwór. Cięzki, dobry beat - jest lepiej.  Pamiętając pierwszy song  słucham już z ulgą - jest to utwór instrumentalny. Ale co jest z tym nagłośnieniem?! Talerze wiercą mi dziury w bębenkach, a gitray rozcinają mi czaszkę! Czy na prawdę wszyscy dźwiękowcy się dzisiaj czegoś "najarali"? Nawet z większej odległości nie dało się słuchać! Za dużo "środka", za głośno perkusja! Na koniec dodam, że aby zostać muzykiem-gitrzystą, nie wystarczy tylko podpiąć wah-wah i telepać stopą!&lt;br /&gt;Zapowiadając norwegów dowiedziałem się, że dyrektor artystyczny, piszący również recenzje muzyczne do jednej z gazet, zaprosił zespół po przesłuchaniu jego płyty.  Poniekąd rozumiem tę decyzję - od słuchania "demówek" całej masy podobnych zespołów można zatracić zmysł orientacji, a sito krytyki robi się niezwykle dziurawe.&lt;br /&gt;&lt;br /&gt;Nie wiem jak grają Architecture in Helsingi i Piano Magic. Uciekliśmy.&lt;br /&gt;&lt;br /&gt;Reasumując - piątkowi wykonawcy (od godz. 18:00, wczesniejszych nie slyszalem) są pozbawieni zmysłu słuchu albo realizatorzy dźwięku byli na środkach psychotropowych. Nie wiem, które z tych stwierdzeń jest prawdą. Na co dzień obcuję ze sporą dawką muzyki, więc wykluczam defekt czy ułomoność mojego słuchu.&lt;br /&gt;&lt;br /&gt;Ufam, że w sobotę będzie dokładnie odwrotnie, tak jak w 2006 roku. I to nie z powodu Nosowskiej, Pogodno czy O.S.T.R. To nie dla nich wybrałem Off Festiwal. Z resztą nie bardzo ich lubię. Nosowska ostatnio wypada jakoś płasko, nieciekawie, a O.S.T.R. reprezentuje scenę hip-hop, którą z trudnością trawię.&lt;br /&gt;Mimo wszystko życzę sobie i wszystkim obecnym na Festiwalu pozytywnych wrażeń muzycznych.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-3286781719988197774?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/3286781719988197774/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=3286781719988197774' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/3286781719988197774'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/3286781719988197774'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2007/08/offfestival-2007-prawdziwa-alternatywa.html' title='Offfestival 2007 Mysłowice - prawdziwa alternatywa'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-2416123446362626154</id><published>2007-04-16T21:21:00.000+02:00</published><updated>2007-04-16T22:06:40.143+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='webdeveloper'/><category scheme='http://www.blogger.com/atom/ns#' term='programowanie'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>lambda function + PHP (create_function) - memory leak</title><content type='html'>&lt;strong&gt;From php.net/create_function&lt;br /&gt;&lt;br /&gt;Dan D&lt;/strong&gt;&lt;br /&gt; &lt;a href="http://pl2.php.net/manual/en/function.create-function.php#70691"&gt;24-Oct-2006 04:22&lt;/a&gt;&lt;code&gt;&lt;span class="html"&gt;&lt;blockquote&gt; Beware when using anonymous functions in PHP as you would in languages like Python, Ruby, Lisp or Javascript.  As was stated previously, the allocated memory is never released; they are not objects in PHP -- they are just dynamically named global functions -- so they don't have scope and are not subject to garbage collection.&lt;br /&gt;&lt;br /&gt;So, if you're developing anything remotely reusable (OO or otherwise), I would avoid them like the plague.  They're slow, inefficient and there's no telling if your implementation will end up in a large loop.  Mine ended up in an iteration over ~1 million records and quickly exhasted my 500MB-per-process limit.&lt;/blockquote&gt;&lt;/span&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-2416123446362626154?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/2416123446362626154/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=2416123446362626154' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/2416123446362626154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/2416123446362626154'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2007/04/lambda-function-php-createfunction.html' title='lambda function + PHP (create_function) - memory leak'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-4680696678355658301</id><published>2007-02-25T00:53:00.000+01:00</published><updated>2007-02-25T01:06:23.962+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='webdeveloper'/><category scheme='http://www.blogger.com/atom/ns#' term='tinymce'/><category scheme='http://www.blogger.com/atom/ns#' term='tips'/><category scheme='http://www.blogger.com/atom/ns#' term='ajax'/><category scheme='http://www.blogger.com/atom/ns#' term='programowanie'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>AJAX: tinyMCE is not defined lub this.settings has no properties</title><content type='html'>Kilka dobrych godzin poświęciłem, aby odpatlić tinyMCE we własnym frameworku. Problemy zaczeły się, gdy dodałem proste wsparcie AJAX za pomocą Ajax.Updater(). Formularze wczytywane dynamicznie za nic w świecie nie były dekorowane tinyMCE. Firebug zgłaszał niezdefioniowany obiekt tinyMCE. Czytając fora, wiki i grupy użyłem manualnego podpięcia tinyMCE dla wybranych pól textarea, zaraz po wyrenderowaniu formularza.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;/blockquote&gt;tinyMCE.execCommand('mceAddControl', true, 'OBJECT_ID');&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Nie pomogło. Firebug zgłaszał błąd "this.settings has no properties". Nie przerawłem poszukiwań. Dopiero na &lt;a href="http://bakery.cakephp.org/articles/view/140"&gt;forum CakePHP&lt;/a&gt; znalazłem rozwiązanie.&lt;br /&gt;&lt;br /&gt;W trzech słowach:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Jeśli używasz scriptaculous, wczytaj skrypt tinyMCE przed nim&lt;/li&gt;&lt;li&gt;W głównym szablonie (nie w dynamicznie wczytywanym fragmencie) zadeklaruj, aby tinyMCE nie zamieniał pól formularzy automatycznie po załadowaniu strony:&lt;br /&gt;   tinyMCE.init({&lt;br /&gt;       theme : "simple",&lt;br /&gt;       mode : "none",&lt;br /&gt;       convert_urls : false&lt;br /&gt;   });&lt;/li&gt;&lt;li&gt;Dla każdego pola formularza, pod które zechcesz podpiąć tinyMCE dopisz:&lt;br /&gt;&lt;blockquote&gt;&lt;/blockquote&gt;tinyMCE.execCommand('mceAddControl', true, 'OBJECT_ID');&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-4680696678355658301?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/4680696678355658301/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=4680696678355658301' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/4680696678355658301'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/4680696678355658301'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2007/02/ajax-tinymce-is-not-defined-lub.html' title='AJAX: tinyMCE is not defined lub this.settings has no properties'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-1639452881191224205</id><published>2007-02-17T11:50:00.000+01:00</published><updated>2007-02-17T11:56:00.865+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='debian'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='apache'/><title type='text'>PHP5 - Apache2 i debian/unstable</title><content type='html'>Czasem zapominam, jak podpiąć php5-cgi pod apache w debianie.&lt;br /&gt;Trzeba zalozyc plik /etc/apache2/mods-available/php5.conf:&lt;br /&gt;&lt;blockquote&gt;AddType application/x-httpd-php5 .php5&lt;br /&gt;ScriptAlias /php/ "/usr/bin/"&lt;br /&gt;Action application/x-httpd-php5 "/php/php5-cgi"&lt;br /&gt;&lt;/blockquote&gt;Należy podlinkowac go do mods-enabled i upewnić się,  czy uruchamiany jest mod_actions.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-1639452881191224205?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/1639452881191224205/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=1639452881191224205' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/1639452881191224205'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/1639452881191224205'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2007/02/php5-apache2-i-debianunstable.html' title='PHP5 - Apache2 i debian/unstable'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-921609142041530446</id><published>2007-02-16T03:04:00.000+01:00</published><updated>2007-02-16T03:18:36.784+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='webdeveloper'/><category scheme='http://www.blogger.com/atom/ns#' term='mvc'/><category scheme='http://www.blogger.com/atom/ns#' term='programowanie'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><category scheme='http://www.blogger.com/atom/ns#' term='smarty'/><title type='text'>Smarty - file name too long</title><content type='html'>Czasem Smarty (sprawdzałem v2.6.14)  generuje zbyt długie nazwy plików w compile_dir. Szczególnie, jeśli używasz string resource. Nie wiedzieć czemu autorzy Smarty w nazwe pliku wrzucają nazwę zasobu, co w przypadku wspomnianego stringa jest fragmentem szablonu.&lt;br /&gt;&lt;br /&gt;Nie znalazłem innego wyjścia, jak modyfikacja samej klasy Smarty (Smarty.class.php), a konkretnie metody  _get_auto_filename(). Nazwę pliku traktujemy md5():&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;function _get_auto_filename($auto_base, $auto_source = null, $auto_id = null)&lt;br /&gt;{&lt;br /&gt;    $_compile_dir_sep =  $this-&gt;use_sub_dirs ? DIRECTORY_SEPARATOR : '^';&lt;br /&gt;    $_return = $auto_base . DIRECTORY_SEPARATOR;&lt;br /&gt;&lt;br /&gt;    if(isset($auto_id)) {&lt;br /&gt;        // make auto_id safe for directory names&lt;br /&gt;        $auto_id = str_replace('%7C',$_compile_dir_sep,(urlencode($auto_id)));&lt;br /&gt;        // split into separate directories&lt;br /&gt;        $_return .= $auto_id . $_compile_dir_sep;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    if(isset($auto_source)) {&lt;br /&gt;        // make source name safe for filename&lt;br /&gt;        //&lt;strike&gt;$_filename = urlencode(basename($auto_source));&lt;br /&gt;&lt;/strike&gt;&lt;strong&gt;$_filename = &lt;span style="color:red;"&gt;md5(&lt;/span&gt;urlencode(basename($auto_source))&lt;span style="color:red;"&gt;)&lt;/span&gt;;&lt;/strong&gt;&lt;br /&gt;        $_crc32 = sprintf('%08X', crc32($auto_source));&lt;br /&gt;        // prepend %% to avoid name conflicts with&lt;br /&gt;        // with $params['auto_id'] names&lt;br /&gt;        $_crc32 = substr($_crc32, 0, 2) . $_compile_dir_sep .&lt;br /&gt;                  substr($_crc32, 0, 3) . $_compile_dir_sep . $_crc32;&lt;br /&gt;        $_return .= '%%' . $_crc32 . '%%' . $_filename;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    return $_return;&lt;br /&gt;}&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-921609142041530446?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/921609142041530446/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=921609142041530446' title='Komentarze (2)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/921609142041530446'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/921609142041530446'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2007/02/smarty-file-name-too-long.html' title='Smarty - file name too long'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-7820495023760875900</id><published>2006-12-07T20:42:00.000+01:00</published><updated>2007-02-16T03:39:53.788+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='wzorce obiektowe'/><category scheme='http://www.blogger.com/atom/ns#' term='webdeveloper'/><category scheme='http://www.blogger.com/atom/ns#' term='mvc'/><category scheme='http://www.blogger.com/atom/ns#' term='programowanie'/><category scheme='http://www.blogger.com/atom/ns#' term='php'/><title type='text'>PHP i Frameworki - czy istnieje ideał? (1)</title><content type='html'>PHP jest językiem programowania zaiste ciekawym. Dzięki swojej prostocie zdobył masę zwolenników. Brak deklaracji typów zmiennych, ogromna ilość wbudowanych funkcji spełniających rozmaite zadania, prosta składnia i w końcu wszechobecność samego PHP przyczyniły się do powstania ogromnego community.  Równie sporą ilością charakteryzuje się grupa ludzi niezadowolonych z "zalet" i uproszczeń tego języka. I tak oto community PHP zrzesza  programistów PHP marnej jakości, amatorów i jak to mawia kolega z pracy - "polonistów" (tu: humanistów) klepiących wieczorami herezje w Notatniku, ale także programistów, że tak określę kolokwialnie, "pełną gębą" - ludzi z powołania, znających się na swoim fachu, i - co chyba przykre - skazanych niejako przez niewidzialną rękę rynku na developement w środowisku PHP. Ci mądrzy ludzie nie tylko nie akceptują wad PHP, ale starają się uczynić programowanie w PHP bardziej przyjemnym, zmierzającym w kierunku określanym mianem Rapid Developement.&lt;br /&gt;&lt;span&gt;&lt;br /&gt;Framework&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Jak podaje &lt;a href="http://pl.wikipedia.org/wiki/Framework"&gt;Wikipedia, framework&lt;/a&gt;&lt;br /&gt;&lt;blockquote&gt;to w &lt;a href="http://pl.wikipedia.org/wiki/Programowanie" title="Programowanie"&gt;programowaniu&lt;/a&gt; struktura wspomagająca tworzenie, rozwój i testowanie powstającej aplikacji. Z reguły na framework składają się programy wspomagające, biblioteki kodu źródłowego i inne podobne narzędzia.&lt;/blockquote&gt;&lt;br /&gt;Niemal każdy programista (pełną gębą ;) popełnił w swoim życiu choćby namiastkę framework-a, choćby poprzez przygotowanie zestawu własnych klas wspierających developement. Ja chciałbym mimo wszystko pokrótce przedstawić kilka rozwiązań, które udało mi się znaleźć w sieci, lub które polecali mi koledzy po fachu. Na końcu przedstawię swoją wizję framework-a, opiszę co udało mi się uczynić w tym kierunku, i jakie są wady i zalety indywidualnych rozwiązań.&lt;br /&gt;&lt;br /&gt;&lt;span&gt;Mojavi&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Spotkałem się z tym framework-iem kilka lat temu. Pisząc tego post-a chciałem odświeżyć sobie o nim wiadomości. Niestety ku mojemu zaskoczeniu strona projektu jest niedostępna. Wspomnę go tylko zatem w kilku zdaniach.&lt;br /&gt;&lt;br /&gt;Mojavi to klasyczny framework implementujący wzorzec MVC (Model-View-Controller)   . Z resztą nazwa Mojavi pochodzi od tego skrótu.&lt;br /&gt;&lt;br /&gt;Zasada projektowania aplikacji MVC jest prosta, a samo programowanie bardzo efektywne i szybkie. Przypomnę tylko, że warstwa modelu odpowiada za opis danych,  warstwa kontrolera odpowiada za obsługę akcji, a widok to część prezentująca dane w przeglądarce. To kontroler spaja logikę z warstwą widoku, której zadaniem jest wyświetlenie tego, co przygotował kontroler z modelami. Dzięki zastosowaniu MVC utrzymanie kodu jest zdecydowanie efektywniejsze. Prawde mówiąc nie potrafię sobie wyobrazić, jak w obecnych czasach można programować klasyczne aplikacje web-owe opierając  je o struktury inne niż MVC, nie wspominając o programowaniu proceduralnym.&lt;br /&gt;&lt;br /&gt;Wracając do Mojavi, na japońskiej stronie projektu udało mi się dowiedzieć tylko tyle, że jest już wersja oznaczona numerem 4. Znalazłem również ciekawy &lt;a href="http://www.peterrobins.co.uk/it/mojavi/tutorial.htm"&gt;tutorial dla początkujących&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Mojavi to klasyczny podział na akcję, kontroler, widok  i model.   Posiada również filtry i łańcuchy filtrów, które najczęściej wykorzystuje się do obsługi procesów logowania czy wylogowania. Filtry różnią się od akcji tym, że mogą być inicjowane przed uruchomieniem kontrolera (pre-filters) i po wykonaniu przez niego pracy (post-filters). Mojavi obsługuje również sprawdzanie poprawności danych, uwierzytelnianie użytkowników.&lt;br /&gt;&lt;br /&gt;Co drażni w Mojavi? Uważam, że nadal za dużo trzeba programować. Niepotrzebne zdaje się tworzenie instancji rendererów w każdej z akcji, czy czasochłonne inicjowanie raczej zbędnych metod. Nie posiada wsparcia dla przestrzeni nazw, a wczytywanie dodatkowych skryptow zmusza do uzywania niewygodnego require.&lt;br /&gt;&lt;br /&gt;Nie zainteresował mnie na tyle, aby poświęcić mu więcej niż 30 minut.&lt;br /&gt;&lt;br /&gt;&lt;span&gt;Prado&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Ciekawie zapowiadający się framework. Przyglądając się temu wynalazkowi odniosłem wrażenie, że już gdzieś to widziałem. I rzeczywiście... Prado to próba implementacji fragmentu środowiska .NET Framework dla PHP. Przeportowane zostały (i to dokładnie!) niektóre namespace-y, jak: System, System.i18n, System.Database. Niestety Prado odziedziczyło również wady pierwowzoru i niektóre przykłady (jeszcze może dwa lata temu) nie działały prawidłowo na innych przeglądarkach niż Internet Explorer. Obecnie implementacja JavaScript-u w browserach znacznie się poprawiła, ale mimo wszystko Prado potrafił mnie zniechęcić.&lt;br /&gt;&lt;br /&gt;Zaletą Prado są szablony, które składa się w języku XML. Prado posiada wiele komponentów,  których parametry i wygląd (na wzór .NET) określa się bezpośrednio w szablonach. Komponenty zamknięte są w swojej przestrzeni nazw, co znacznie ułatwia czytanie i projektowanie kodu.&lt;br /&gt;&lt;br /&gt;Prado posiada wbudowane komponenty kreatora, walidacji, tabel, grid-ów, czyli praktycznie wszystkiego dobrego, co znamy z .NET.  Hermetyzacji zostały poddane dane sesji, żądań HTTP, zarządzania plikami.&lt;br /&gt;&lt;br /&gt;Co mierzi? Wspomniana niemal 100% kompatybilność z pierwowzorem. Również podział na strony, a może przede wszystkim brak O/R mapping-u. Zatem ciekawa propozycja dla związanych emocjonalnie z .NET. Chociaż szczerze mówiąc - wolę projektować w darmowym już Visual Studio, aniżeli męczyć się z klepaniem kodu w PHP.&lt;br /&gt;&lt;br /&gt;Następnym razem opiszę:&lt;br /&gt;&lt;br /&gt;&lt;span&gt;PHP on Trax&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&gt;EZComponents&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;Zend Framework&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;Symfony&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span&gt;Cosine&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Oraz podsumowanie, czyli&lt;br /&gt;&lt;br /&gt;&lt;span&gt;Czy istnieje ideał, i który framework zasługuje na to miano?&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-7820495023760875900?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/7820495023760875900/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=7820495023760875900' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/7820495023760875900'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/7820495023760875900'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2006/12/php-i-frameworki-czy-istnieje-idea.html' title='PHP i Frameworki - czy istnieje ideał? (1)'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-3373461577601492279</id><published>2006-11-24T19:44:00.000+01:00</published><updated>2006-11-24T19:55:26.440+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='fluxbox'/><title type='text'>Fluxbox: tapeta pulpitu</title><content type='html'>Miałem ostatnio kłopot z ustawieniem tapety na pulpicie. Domyślnie ustawiane jest czarne tło przez program &lt;span style="font-weight: bold;"&gt;fbsetroot&lt;/span&gt; wywoływany w skrypcie ~/.fluxbox/startup. Teoretycznie wystarczyło zamienić &lt;span style="font-weight: bold;"&gt;fbsetroot&lt;/span&gt; na &lt;span style="font-weight: bold;"&gt;fbsetbg&lt;/span&gt;. Niestety podczas uruchamiania Fluxbox-a tło zamieniało się z powrotem na domyślnie ustawione w temacie.&lt;br /&gt;&lt;br /&gt;Rozwiązanie podaje manual, którego czasem warto czytać. :) Aby tło nie było nadpisywane przez ustawienia tematu, a ponad to nie chcesz modyfikować jego ustawień, ustaw fbsetbg jako rootCommand w pliku &lt;span style="font-weight: bold;"&gt;~/.fluxbox/init&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;session.screen0.rootCommand:    fbsetbg -f /sciezka/do/twojej/tapety.jpg&lt;/blockquote&gt;&lt;br /&gt;Ja jestem zadowolony :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-3373461577601492279?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/3373461577601492279/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=3373461577601492279' title='Komentarze (1)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/3373461577601492279'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/3373461577601492279'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2006/11/fluxbox-tapeta-na-pulpicie.html' title='Fluxbox: tapeta pulpitu'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-4671573651990576961</id><published>2006-11-22T20:36:00.000+01:00</published><updated>2006-11-22T20:38:16.083+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='firefox'/><category scheme='http://www.blogger.com/atom/ns#' term='przeglądarki'/><category scheme='http://www.blogger.com/atom/ns#' term='microsoft'/><title type='text'>Microsoft Firefox 2007</title><content type='html'>Zdaję sobie sprawę, że to trochę odświeżany news. Jednakże nie wszyscy widzieli, a warto! Choćby dla rewelacyjnego filmu reklamowego. Zapraszam na prezentację nowej przeglądarki &lt;a href="http://www.msfirefox.com/"&gt;Microsoft Firefox 2007&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-4671573651990576961?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/4671573651990576961/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=4671573651990576961' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/4671573651990576961'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/4671573651990576961'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2006/11/microsoft-firefox-2007.html' title='Microsoft Firefox 2007'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-3179236609320082225</id><published>2006-11-21T23:58:00.000+01:00</published><updated>2006-11-22T20:43:48.723+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='webdeveloper'/><category scheme='http://www.blogger.com/atom/ns#' term='galeria'/><category scheme='http://www.blogger.com/atom/ns#' term='programowanie'/><title type='text'>Coppermine Gallery i spam</title><content type='html'>Użytkownicy skryptu &lt;a href="http://coppermine-gallery.net/"&gt;Coppermine Gallery&lt;/a&gt; nie mogą narzekać na nudę. Od dłuższego czasu roboty spamerskie atakują ten nieco dziurawy skrypt dodając do galerii komentarze z linkami, które albo prowadzą do viagry, albo do stron porno.&lt;br /&gt;&lt;br /&gt;Są dwa sposoby obejścia problemu. Pierwszy to dodanie graficznego &lt;a href="http://pl.wikipedia.pl/wiki/Token"&gt;tokena&lt;/a&gt; z serią znaków, które musi odczytać człowiek (lub sprytny robot ;), aby dodać komentarz. Takie rozwiązanie często stosowane jest w bramkach SMS.&lt;br /&gt;&lt;br /&gt;Drugi sposób to zastosowanie skryptu anty-spamerskiego. Ciekawym rozwiązaniem jest system &lt;a href="http://akismet.com/"&gt;Akismet&lt;/a&gt;, którego wspiera m.in. &lt;a href="http://wordpress.com/"&gt;WordPress&lt;/a&gt;. Do użycia skryptu trzeba uzyskać &lt;a href="http://wordpress.com/api-keys/"&gt;klucz (API-KEY)&lt;/a&gt;, a następnie wykonać kilka modyfikacji w skrypcie galerii (plik db_input.php).&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Ściągnij &lt;a href="http://akismet.com/development/"&gt;klasę Akismet&lt;/a&gt; dla swojej wersji PHP (jest dostępna dla PHP4 i PHP5)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Zrób kopię zapasową pliku db_input.php i otwórz do edycji plik db_input.php&lt;/li&gt;&lt;li&gt;Dopisz na początku pliku &lt;blockquote&gt;require_once "Akismet.class.php";&lt;/blockquote&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Znajdź linię zawierającą poniższy kod &lt;blockquote&gt;$insert = db_query("INSERT INTO {$CONFIG['TABLE_COMMENTS']} (pid, msg_author, msg_body, msg_date, author_md5_id, author_id, msg_raw_ip, msg_hdr_ip) VALUES ('$pid', '$msg_author', '$msg_body', NOW(), '{$USER['ID']}', '0', '$raw_ip', '$hdr_ip')");&lt;/blockquote&gt;&lt;/li&gt;&lt;li&gt;Wytnij (lub zamień na komentarz) powyższą linię.&lt;/li&gt;&lt;li&gt;W tym samym miejscu wklej poniższy skrypt:         &lt;blockquote&gt;$WordPressAPIKey =  'KLUCZ-DO-API'';                                                                                                            $MyBlogURL = 'adres internetowy twojej galerii';&lt;br /&gt;$name = $msg_author;                                                                                                                           $comment = $msg_body;&lt;br /&gt;$akismet = new Akismet($MyBlogURL ,$WordPressAPIKey);&lt;br /&gt;$akismet-&gt;setAuthor($name);&lt;br /&gt;$akismet-&gt;setAuthorEmail($email);&lt;br /&gt;$akismet-&gt;setAuthorURL($url);&lt;br /&gt;$akismet-&gt;setContent($comment);&lt;br /&gt;$akismet-&gt;setPermalink('adres/do/artykulu'); // wpisalem tu adres strony&lt;br /&gt;&lt;br /&gt;if($akismet-&gt;isSpam())&lt;br /&gt;{&lt;br /&gt;  cpg_die(ERROR, $lang_errors['perm_denied'], __FILE__, __LINE__);&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt; // tu wstaw linię z punktu 4&lt;br /&gt;}    &lt;/blockquote&gt;&lt;/li&gt;&lt;li&gt;Gratulacje, właśnie zabezpieczyłeś się przed spamem.&lt;/li&gt;&lt;li&gt;Jeśli coś się nie powiodło, możesz usunąć zmiany odzyskując plik db_input.php z kopii zapasowej&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-3179236609320082225?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/3179236609320082225/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=3179236609320082225' title='Komentarze (5)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/3179236609320082225'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/3179236609320082225'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2006/11/coppermine-gallery-i-spam.html' title='Coppermine Gallery i spam'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-7735732937417809471</id><published>2006-11-21T20:27:00.000+01:00</published><updated>2006-11-22T20:48:16.212+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='linux'/><category scheme='http://www.blogger.com/atom/ns#' term='fluxbox'/><category scheme='http://www.blogger.com/atom/ns#' term='kdm'/><title type='text'>Fluxbox sessionstart z kdm (debian)</title><content type='html'>Po szczęśliwej instalacji debiana z moim ulubionym &lt;a href="http://fluxbox.sourceforge.net/"&gt;Fluxbox-em&lt;/a&gt; postanowiłem użyć &lt;a href="http://kde.org/"&gt;kdm&lt;/a&gt; zamiast trochę brzydkawego &lt;a href="http://www.gnome.org/projects/gdm/"&gt;gdm-a&lt;/a&gt;. Wtedy zauważyłem, że przy starcie &lt;a href="http://fluxbox.sourceforge.net/"&gt;Fluxbox-a&lt;/a&gt; ignoruje on zwyczajnie plik startowy &lt;span style="font-weight: bold;"&gt;~/.fluxbox/startup&lt;/span&gt;. Przyczyna jest trywialna - &lt;a href="http://kde.org/"&gt;kdm&lt;/a&gt; odpala binarkę /usr/bin/fluxbox zamiast skryptu /usr/bin/startfluxbox. Aby zmusić &lt;a href="http://kde.org/"&gt;kdm&lt;/a&gt; do odpalenia startfluxbox, otwórz do edycji plik  &lt;b&gt;/usr/share/xsessions/fluxbox.desktop:&lt;/b&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;[Desktop Entry]&lt;br /&gt;Encoding=UTF-8&lt;br /&gt;Name=Fluxbox&lt;br /&gt;Comment=Highly configurable and low resource X11 Window manager&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Exec=/usr/bin/fluxbox&lt;/span&gt;&lt;br /&gt;Terminal=False&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;TryExec=/usr/bin/fluxbox&lt;/span&gt;&lt;br /&gt;Type=Application&lt;br /&gt;&lt;br /&gt;[Window Manager]&lt;br /&gt;SessionManaged=true&lt;/blockquote&gt;&lt;br /&gt;Zmień pogrubione linie wstawiając /usr/bin/startfluxbox zamiast /usr/bin/fluxbox.&lt;br /&gt;Następnie wystarczy zrestartować &lt;a href="http://kde.org/"&gt;kdm-a&lt;/a&gt; i przy ponownym uruchomieniu startfluxbox utworzy plik ~/.fluxbox/startup, którego według własnych upodobań zmodyfikujesz.&lt;br /&gt;&lt;br /&gt;Powodzenia!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-7735732937417809471?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/7735732937417809471/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=7735732937417809471' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/7735732937417809471'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/7735732937417809471'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2006/11/fluxbox-sessionstart-z-kdm-debian.html' title='Fluxbox sessionstart z kdm (debian)'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-6160696760267458338</id><published>2006-11-21T19:56:00.000+01:00</published><updated>2006-11-22T20:50:30.729+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='firefox'/><title type='text'>Firefox i odzyskiwanie sesji</title><content type='html'>Czasami lub nawet często zdarza się, że nawet po prawidłowym zakończeniu pracy &lt;a href="http://www.mozilla-europe.org/pl/products/firefox/"&gt;Firefox 2&lt;/a&gt; zadaje pytanie o przywrócenie ostatniej sesji. Po kilku razach może być to wyjątkowo irytujące dla użytkownika. Na szczęście jest na to prosta rada: zmień (lub utwórz, jeśli nie istnieje) klucz w konfiguracji o nazwie &lt;span style="font-weight: bold;"&gt;browser.sessionstore.enabled&lt;/span&gt; i typie &lt;span style="font-weight: bold;"&gt;boolean&lt;/span&gt;, oraz ustaw jego wartość na false.&lt;br /&gt;&lt;br /&gt;Krok po kroku:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;otwórz adres &lt;blockquote&gt;about:config&lt;/blockquote&gt;&lt;/li&gt;&lt;li&gt;wpisz w filtrze &lt;blockquote&gt;sessionstore&lt;/blockquote&gt;&lt;/li&gt;&lt;li&gt;odszukaj klucz &lt;span style="font-weight: bold;"&gt;browser.sessionstore.enabled&lt;/span&gt; lub dodaj nowy o takiej nazwie&lt;/li&gt;&lt;li&gt;zmień/ustaw jego wartość na &lt;span style="font-weight: bold;"&gt;false&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-6160696760267458338?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/6160696760267458338/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=6160696760267458338' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/6160696760267458338'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/6160696760267458338'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2006/11/firefox-i-odzyskiwanie-sesji.html' title='Firefox i odzyskiwanie sesji'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6518460238029135110.post-6585895469480372256</id><published>2006-11-21T19:51:00.000+01:00</published><updated>2006-11-21T19:53:08.922+01:00</updated><title type='text'>Uroczyste otwarcie</title><content type='html'>.. odbyło się bez większych problemów. Komputer się nie zawiesił, prądu nie brakło, Google działają.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6518460238029135110-6585895469480372256?l=marcinnowak.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://marcinnowak.blogspot.com/feeds/6585895469480372256/comments/default' title='Komentarze do posta'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6518460238029135110&amp;postID=6585895469480372256' title='Komentarze (0)'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/6585895469480372256'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6518460238029135110/posts/default/6585895469480372256'/><link rel='alternate' type='text/html' href='http://marcinnowak.blogspot.com/2006/11/uroczyste-otwarcie.html' title='Uroczyste otwarcie'/><author><name>Marcin Nowak</name><uri>http://www.blogger.com/profile/06875142748530315437</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
