<?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-8560211453511692375</id><updated>2012-02-16T06:04:01.877-03:00</updated><category term='Json'/><category term='Newforms'/><category term='Xchat'/><category term='Glade'/><category term='python'/><category term='Django'/><category term='Settings'/><category term='Feedparser'/><category term='PyGTK'/><category term='systemd'/><category term='dbus'/><category term='News'/><category term='Serialization'/><title type='text'>Pythonidae</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://pythonidae.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://pythonidae.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Wiliam Alves de Souza</name><uri>http://www.blogger.com/profile/03875589378985971879</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>13</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8560211453511692375.post-2675473800389816602</id><published>2011-04-07T10:35:00.005-03:00</published><updated>2011-04-07T10:55:59.210-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='systemd'/><category scheme='http://www.blogger.com/atom/ns#' term='python'/><category scheme='http://www.blogger.com/atom/ns#' term='dbus'/><title type='text'>Receiving systemd dbus signals</title><content type='html'>It demonstrates how to connect to systemd dbus signal. run this and stop/start crond using systemctl.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;import dbus&lt;br /&gt;import dbus.mainloop.glib&lt;br /&gt;dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)&lt;br /&gt;&lt;br /&gt;bus = dbus.SystemBus()&lt;br /&gt;&lt;br /&gt;proxy = bus.get_object(&lt;br /&gt;       'org.freedesktop.systemd1',&lt;br /&gt;       '/org/freedesktop/systemd1'&lt;br /&gt;   )&lt;br /&gt;&lt;br /&gt;interface = dbus.Interface(proxy, 'org.freedesktop.systemd1.Manager')&lt;br /&gt;&lt;br /&gt;interface.Subscribe()&lt;br /&gt;&lt;br /&gt;def on_properties_changed(*args, **kargs):&lt;br /&gt;   print 'Status Changed....'&lt;br /&gt;   print args&lt;br /&gt;   print kargs&lt;br /&gt;&lt;br /&gt;properties_proxy = bus.get_object(&lt;br /&gt;   'org.freedesktop.systemd1',&lt;br /&gt;   interface.GetUnit('crond.service'))&lt;br /&gt;&lt;br /&gt;properties_interface = dbus.Interface(properties_proxy, 'org.freedesktop.DBus.Properties')&lt;br /&gt;&lt;br /&gt;properties_interface.connect_to_signal('PropertiesChanged', on_properties_changed)&lt;br /&gt;&lt;br /&gt;import gobject&lt;br /&gt;&lt;br /&gt;loop = gobject.MainLoop()&lt;br /&gt;loop.run()&lt;br /&gt;&lt;code&gt;&lt;/code&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8560211453511692375-2675473800389816602?l=pythonidae.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythonidae.blogspot.com/feeds/2675473800389816602/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8560211453511692375&amp;postID=2675473800389816602' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/2675473800389816602'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/2675473800389816602'/><link rel='alternate' type='text/html' href='http://pythonidae.blogspot.com/2011/04/receiving-systemd-dbus-signals.html' title='Receiving systemd dbus signals'/><author><name>Wiliam Alves de Souza</name><uri>http://www.blogger.com/profile/03875589378985971879</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-8560211453511692375.post-8998922359544707147</id><published>2007-10-18T13:59:00.000-03:00</published><updated>2007-10-18T16:01:23.521-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Xchat'/><category scheme='http://www.blogger.com/atom/ns#' term='Feedparser'/><title type='text'>Recently played tracks from last.fm</title><content type='html'>&lt;code&gt;&lt;br /&gt;import xchat&lt;br /&gt;import feedparser&lt;br /&gt;&lt;br /&gt;LASTFM_USER = 'wiliamsouza83'&lt;br /&gt;URL = 'http://ws.audioscrobbler.com/1.0/user/%s/recenttracks.rss' % LASTFM_USER&lt;br /&gt;&lt;br /&gt;def do_request(word, word_eol, userdata):&lt;br /&gt;....if len(word) &lt; 2:&lt;br /&gt;........xchat.command('help LISTEN')&lt;br /&gt;....elif not isinstance(int(word[1]), int):&lt;br /&gt;........print 'Second arg must be an int!'&lt;br /&gt;....else:&lt;br /&gt;........rss = feedparser.parse(URL)&lt;br /&gt;........for n in range(int(word[1])):&lt;br /&gt;........xchat.command('me listen %s' % rss['entries'][n]['link'])&lt;br /&gt;....return xchat.EAT_ALL&lt;br /&gt;&lt;br /&gt;xchat.hook_command('LISTEN',&lt;br /&gt;...................do_request,&lt;br /&gt;...................help='/LISTEN [number]. Show the latest played track from last.fm.')&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/8560211453511692375-8998922359544707147?l=pythonidae.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythonidae.blogspot.com/feeds/8998922359544707147/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8560211453511692375&amp;postID=8998922359544707147' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/8998922359544707147'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/8998922359544707147'/><link rel='alternate' type='text/html' href='http://pythonidae.blogspot.com/2007/10/recently-played-tracks-from-lastfm.html' title='Recently played tracks from last.fm'/><author><name>Wiliam Alves de Souza</name><uri>http://www.blogger.com/profile/03875589378985971879</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-8560211453511692375.post-7624503416950515214</id><published>2007-04-09T17:50:00.000-03:00</published><updated>2007-04-09T18:11:04.983-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Serialization'/><category scheme='http://www.blogger.com/atom/ns#' term='Django'/><category scheme='http://www.blogger.com/atom/ns#' term='Json'/><title type='text'>Django serialization.</title><content type='html'>Bastante usado em &lt;a href="http://www.djangoproject.com/documentation/testing/#writing-unittests"&gt;unittest&lt;/a&gt; e &lt;a href="http://www.djangoproject.com/documentation/testing/#writing-doctests"&gt;doctests&lt;/a&gt;.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;wiliam@wiliam:~/dev/myapp$ python manage.py shell&lt;br /&gt;&gt;&gt;&gt; from &lt;/code&gt;&lt;code&gt;myapp&lt;/code&gt;&lt;code&gt;.purchase.models import Country&lt;br /&gt;&gt;&gt;&gt; from django.core import serializers&lt;br /&gt;&gt;&gt;&gt; f = open('countries.json', 'w')&lt;br /&gt;&gt;&gt;&gt; data = serializers.serialize("json", Country.objects.all())&lt;br /&gt;&gt;&gt;&gt; f.write(data)&lt;br /&gt;&gt;&gt;&gt; f.close()&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Você pode carregar manualmente usando &lt;code&gt;python manage.py loaddata&lt;/code&gt;:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;wiliam@wiliam:&lt;/code&gt;&lt;code&gt;~/dev/myapp$&lt;/code&gt;&lt;code&gt; python manage.py loaddata fixtures/countries.json&lt;br /&gt;Loading 'fixtures/countries' fixtures...&lt;br /&gt;Installing json fixture 'fixtures/countries' from absolute path.&lt;br /&gt;Installed 242 object(s) from 1 fixture(s)&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/8560211453511692375-7624503416950515214?l=pythonidae.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythonidae.blogspot.com/feeds/7624503416950515214/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8560211453511692375&amp;postID=7624503416950515214' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/7624503416950515214'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/7624503416950515214'/><link rel='alternate' type='text/html' href='http://pythonidae.blogspot.com/2007/04/django-serialization.html' title='Django serialization.'/><author><name>Wiliam Alves de Souza</name><uri>http://www.blogger.com/profile/03875589378985971879</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-8560211453511692375.post-6987693024763654483</id><published>2007-03-31T11:52:00.000-03:00</published><updated>2007-04-03T09:07:09.674-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='News'/><category scheme='http://www.blogger.com/atom/ns#' term='Django'/><category scheme='http://www.blogger.com/atom/ns#' term='Newforms'/><title type='text'>Ticket #3882 (closed: fixed)</title><content type='html'>Já está disponível na &lt;a href="http://code.djangoproject.com/browser/django/trunk/"&gt;versão de desenvolvimento&lt;/a&gt; do &lt;a href="http://www.djangoproject.com/"&gt;Django&lt;/a&gt; o localflavor BR.&lt;br /&gt;&lt;br /&gt;Ticket: &lt;a href="http://code.djangoproject.com/ticket/3882"&gt;#3882&lt;/a&gt;&lt;br /&gt;Changeset &lt;a href="http://code.djangoproject.com/changeset/4874"&gt;4874&lt;/a&gt; e &lt;a href="http://code.djangoproject.com/changeset/4908"&gt;4908&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8560211453511692375-6987693024763654483?l=pythonidae.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythonidae.blogspot.com/feeds/6987693024763654483/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8560211453511692375&amp;postID=6987693024763654483' title='3 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/6987693024763654483'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/6987693024763654483'/><link rel='alternate' type='text/html' href='http://pythonidae.blogspot.com/2007/03/ticket-3882-closed-fixed.html' title='Ticket #3882 (closed: fixed)'/><author><name>Wiliam Alves de Souza</name><uri>http://www.blogger.com/profile/03875589378985971879</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-8560211453511692375.post-2832016345335774500</id><published>2007-03-29T17:47:00.000-03:00</published><updated>2007-04-03T08:55:11.769-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Django'/><category scheme='http://www.blogger.com/atom/ns#' term='Newforms'/><title type='text'>django.contrib.localflavor.br</title><content type='html'>Primeira versão implementada, agora vem os teste.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;"""&lt;br /&gt;BR-specific Form helpers&lt;br /&gt;"""&lt;br /&gt;&lt;br /&gt;from django.newforms import ValidationError&lt;br /&gt;from django.newforms.fields import Field, RegexField, Select, EMPTY_VALUES&lt;br /&gt;from django.newforms.util import smart_unicode&lt;br /&gt;from django.utils.translation import gettext&lt;br /&gt;import re&lt;br /&gt;&lt;br /&gt;phone_digits_re = re.compile(r'^(\d{2})[-\.]?(\d{4})[-\.]?(\d{4})$')&lt;br /&gt;&lt;br /&gt;class BRZipCodeField(RegexField):&lt;br /&gt;..def __init__(self, *args, **kwargs):&lt;br /&gt; ....super(BRZipCodeField, self).__init__(r'^\d{5}-\d{3}$',&lt;br /&gt;....max_length=None, min_length=None,&lt;br /&gt;....error_message=gettext(u'Enter a zip code in the format XXXXX-XXX.'),&lt;br /&gt;....*args, **kwargs)&lt;br /&gt;&lt;br /&gt;class BRPhoneNumberField(Field):&lt;br /&gt;..def clean(self, value):&lt;br /&gt; ....super(BRPhoneNumberField, self).clean(value)&lt;br /&gt;....if value in EMPTY_VALUES:&lt;br /&gt;......return u''&lt;br /&gt;....value = re.sub('(\(|\)|\s+)', '', smart_unicode(value))&lt;br /&gt;....m = phone_digits_re.search(value)&lt;br /&gt;....if m:&lt;br /&gt;......return u'%s-%s-%s' % (m.group(1), m.group(2), m.group(3))&lt;br /&gt;....raise ValidationError(u'Phone numbers must be in XX-XXXX-XXXX format.')&lt;br /&gt;&lt;br /&gt;class BRStateSelect(Select):&lt;br /&gt;.."""&lt;br /&gt;..A Select widget that uses a list of brazilian states/territories&lt;br /&gt;..as its choices.&lt;br /&gt;.."""&lt;br /&gt;..def __init__(self, attrs=None):&lt;br /&gt;....from br_states import STATE_CHOICES # relative import&lt;br /&gt;....super(BRStateSelect, self).__init__(attrs, choices=STATE_CHOICES)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Coisas pra resolver:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; from django.contrib.localflavor.br.forms import BRZipCodeField, BRPhoneNumberField, BRStateField, BRStateSelect&lt;br /&gt;&gt;&gt;&gt; from django import newforms as forms&lt;br /&gt;&gt;&gt;&gt; class BRForms(forms.Form):&lt;br /&gt;...   zipcode = BRZipCodeField()&lt;br /&gt;...   phone = BRPhoneNumberField()&lt;br /&gt;...   statef = BRStateField()&lt;br /&gt;...   statec = forms.ChoiceField(widget=BRStateSelect)&lt;br /&gt;...&lt;br /&gt;&gt;&gt;&gt; brf = BRForms()&lt;br /&gt;&gt;&gt;&gt; print brf.as_table()&lt;br /&gt;...&lt;br /&gt;&gt;&gt;&gt;&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;O widget &lt;code&gt;BRStateSelect&lt;/code&gt; ainda não é renderizado corretamente, isso acontece com os fields que tem &lt;code&gt;Select&lt;/code&gt; como classe base. A solução que vem sendo adotada usa o método &lt;code&gt;__init__&lt;/code&gt;, que nesse caso não fica elegante pois teríamos que importa &lt;code&gt;STATE_CHOICES&lt;/code&gt; de &lt;code&gt;br_states.py&lt;/code&gt;. Bom o tempo está apertado, tenho que ir, &lt;a href="http://pythonidae.blogspot.com/2007/03/django-e-o-quebra-cabea-com-newforms_27.html"&gt;aqui&lt;/a&gt; tem um exemplo de como usar o &lt;code&gt;__init__&lt;/code&gt;, a única diferença e que os dados vem da banco de dados.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8560211453511692375-2832016345335774500?l=pythonidae.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythonidae.blogspot.com/feeds/2832016345335774500/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8560211453511692375&amp;postID=2832016345335774500' title='4 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/2832016345335774500'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/2832016345335774500'/><link rel='alternate' type='text/html' href='http://pythonidae.blogspot.com/2007/03/djangocontriblocalflavorbr.html' title='django.contrib.localflavor.br'/><author><name>Wiliam Alves de Souza</name><uri>http://www.blogger.com/profile/03875589378985971879</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>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8560211453511692375.post-9176307340778130413</id><published>2007-03-28T17:53:00.000-03:00</published><updated>2007-03-28T18:01:11.680-03:00</updated><title type='text'>Qual o tamanho da comunidade Django?</title><content type='html'>Qual o tamanho da comunidade Django? essa pergunta foi feita e respondida &lt;a href="http://www.jacobian.org/writing/2007/mar/22/circles-of-django/"&gt;aqui&lt;/a&gt; por Jacob Kaplan-Moss.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8560211453511692375-9176307340778130413?l=pythonidae.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythonidae.blogspot.com/feeds/9176307340778130413/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8560211453511692375&amp;postID=9176307340778130413' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/9176307340778130413'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/9176307340778130413'/><link rel='alternate' type='text/html' href='http://pythonidae.blogspot.com/2007/03/qual-o-tamanho-da-comunidade-django.html' title='Qual o tamanho da comunidade Django?'/><author><name>Wiliam Alves de Souza</name><uri>http://www.blogger.com/profile/03875589378985971879</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-8560211453511692375.post-2972550605069785515</id><published>2007-03-28T17:27:00.000-03:00</published><updated>2007-03-28T17:49:38.766-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Django'/><category scheme='http://www.blogger.com/atom/ns#' term='Settings'/><title type='text'>Ajuste inteligente do settings.py</title><content type='html'>Com &lt;a href="http://mccormac.org/blog/2007/mar/28/localized-settings-django/"&gt;essa&lt;/a&gt; dica, teremos dois arquivos de configuração que revezam entre versão de desenvolvimento e produção, o arquivo &lt;code&gt;local_settings.py&lt;/code&gt; contém nossa configuração de desenvolvimento, assim não precisamos nos preocupar com &lt;code&gt;settings.py&lt;/code&gt; na hora da distribuição, pois &lt;code&gt;settings.py&lt;/code&gt; sabe quando deve dar passagem as configurações do arquivo &lt;code&gt;local_settings.py&lt;/code&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8560211453511692375-2972550605069785515?l=pythonidae.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythonidae.blogspot.com/feeds/2972550605069785515/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8560211453511692375&amp;postID=2972550605069785515' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/2972550605069785515'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/2972550605069785515'/><link rel='alternate' type='text/html' href='http://pythonidae.blogspot.com/2007/03/ajuste-inteligente-do-settingspy.html' title='Ajuste inteligente do settings.py'/><author><name>Wiliam Alves de Souza</name><uri>http://www.blogger.com/profile/03875589378985971879</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-8560211453511692375.post-4352428123435193120</id><published>2007-03-27T17:48:00.000-03:00</published><updated>2007-03-28T09:01:26.393-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='News'/><title type='text'>2 terabytes de video e audio sobre Python</title><content type='html'>Trabalho duro! Mais de 2 terabytes de vídeo e áudio gravados na PyCon devem estar editados de forma profissional só no final de junho. Mas segundo Doug Napoleon o material vai ser liberado em partes. Para mais detalhes veja a &lt;a href="http://pycon.blogspot.com/2007/03/status-of-pycon-videoaudio.html"&gt;notícia&lt;/a&gt; completa no &lt;a href="http://pycon.blogspot.com/"&gt;blog&lt;/a&gt; da &lt;a href="http://us.pycon.org/TX2007/HomePage"&gt;PyCon&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8560211453511692375-4352428123435193120?l=pythonidae.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythonidae.blogspot.com/feeds/4352428123435193120/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8560211453511692375&amp;postID=4352428123435193120' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/4352428123435193120'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/4352428123435193120'/><link rel='alternate' type='text/html' href='http://pythonidae.blogspot.com/2007/03/2-terabytes-de-video-e-audio-sobre.html' title='2 terabytes de video e audio sobre Python'/><author><name>Wiliam Alves de Souza</name><uri>http://www.blogger.com/profile/03875589378985971879</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-8560211453511692375.post-4859296079088392110</id><published>2007-03-27T17:00:00.001-03:00</published><updated>2007-03-27T17:09:40.532-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Django'/><category scheme='http://www.blogger.com/atom/ns#' term='Newforms'/><title type='text'>Django e o quebra cabeça com newforms</title><content type='html'>Basicamente temos duas formas para usar o newforms a primeira  consiste em usar as funções &lt;code&gt;form_for_model()&lt;/code&gt; e &lt;code&gt;form_for_instance()&lt;/code&gt;, para a primeira função você deve passar a classe que define seu modelo e para segunda você passa a instância desta classe e o newforms encarrega-se de gerar o formulário para você. Na segunda forma você define seu formulário como uma classe que herda de &lt;code&gt;Form&lt;/code&gt;. Considere a definição do modelo abaixo:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;class Product(models.Model):&lt;br /&gt;..description = models.CharField(maxlength=200)&lt;br /&gt;..category = models.ForeignKey(Category)&lt;br /&gt;..quantity = models.IntegerField()&lt;br /&gt;..cost = models.FloatField(max_digits=10, decimal_places=2)&lt;br /&gt;..detail = models.TextField(maxlength=400, blank=True)&lt;br /&gt;&lt;br /&gt;Usando form_for_model:&lt;br /&gt;&lt;br /&gt;&gt;&gt;&gt; from django import newforms as form&lt;br /&gt;&gt;&gt;&gt; from warehouse.models import Product&lt;br /&gt;&gt;&gt;&gt; ProductForm = form.form_for_model(Product)&lt;br /&gt;&gt;&gt;&gt; pf = ProductForm()&lt;br /&gt;&gt;&gt;&gt; print pf.as_table() # retorna nosso formulário como tabela, em branco.&lt;br /&gt;&lt;br /&gt;Usando form_for_instance:&lt;br /&gt;&lt;br /&gt;&gt;&gt;&gt; from django import newforms as form&lt;br /&gt;&gt;&gt;&gt; from warehouse.models import Product&lt;br /&gt;&gt;&gt;&gt; p = Product.objects.get(pk=1)&lt;br /&gt;&gt;&gt;&gt; ProductForm = form.form_for_instance(p)&lt;br /&gt;&gt;&gt;&gt; pf = ProductForm()&lt;br /&gt;&gt;&gt;&gt; pf.as_table() # retorna nosso formulário como tabela, com valores.&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Acompanhe agora a segunda forma de uso do newforms. O método &lt;code&gt;__init__&lt;/code&gt; serve para carrega todas as categorias disponíveis no banco. Considere a definição do formulário abaixo:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;class ProductForm(forms.Form):&lt;br /&gt;..def __init__(self, *args, **kwargs):&lt;br /&gt;....super(ProductForm, self).__init__(*args, **kwargs)&lt;br /&gt;....self.fields['category'].choices = [('', '----------')] + [&lt;br /&gt;.......(c.id, c.name) for c in Category.objects.all()]&lt;br /&gt;&lt;br /&gt;..description = forms.CharField(max_length=200)&lt;br /&gt;..detail = forms.CharField(max_length=400)&lt;br /&gt;..category = forms.ChoiceField(choices=())&lt;br /&gt;..quantity = forms.IntegerField()&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Testando 123:&lt;code&gt;&lt;br /&gt;&lt;br /&gt;Mesmo conceito usado com form_for_model:&lt;br /&gt;&gt;&gt;&gt; from warehouse.forms import ProductForm&lt;br /&gt;&gt;&gt;&gt; pf =  ProductForm()&lt;br /&gt;&gt;&gt;&gt; pf.as_table()# retorna nosso formulário como tabela, em branco.&lt;br /&gt;&lt;br /&gt;Mesmo conceito usado com form_for_instance:&lt;br /&gt;&gt;&gt;&gt; p = Product.objects.get(pk=1)&lt;br /&gt;&gt;&gt;&gt; pf = ProductForm(p.__dict__)&lt;br /&gt;&gt;&gt;&gt; pf.as_table() # retorna nosso formulário como tabela, com valores.&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Agora vamos usar nossa imaginação, imagine que o produto retornado por &lt;code&gt;Product.objects.get(pk=1)&lt;/code&gt; faça parte do categoria "Keyboards", e que naturalmente essa opção deveria estar selecionada no campo &lt;code&gt;category&lt;/code&gt;, infelizmente não é isso que acontece. Mas espere com &lt;code&gt;form_for_model()&lt;/code&gt; e &lt;code&gt;form_for_instance()&lt;/code&gt; funciona! Aqui está o &lt;a href="http://code.djangoproject.com/browser/django/trunk/django/newforms"&gt;código&lt;/a&gt; do newforms de uma olhada tente achar o erro:) Brincadeira! é uma boa leitura, eu li varias vezes. Essa falha acontece pela diferença entre o nome do campo &lt;code&gt;category&lt;/code&gt; definido em nossa classe &lt;code&gt;ProductForm&lt;/code&gt; e o dicionário retornado por &lt;code&gt;p.__dict__ &lt;/code&gt;que retorna uma chave de nome &lt;code&gt;category_id&lt;/code&gt; representando a categoria em vez de &lt;code&gt;category&lt;/code&gt;, o que gera uma &lt;code&gt;ValidationError&lt;/code&gt;.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; p.__dict__&lt;br /&gt;{'description': 'Turtle', 'detail': 'ABNT2', 'cost': 46.73, 'category_id': 2, 'id': 1, 'quantity': 1}&lt;br /&gt;&gt;&gt;&gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Temos duas soluções, a primeira e renomear todos os campos &lt;code&gt;foreignkey&lt;/code&gt; para  uma nomenclatura &lt;code&gt;nome + _id&lt;/code&gt; e a segunda foi passada pelo &lt;a href="http://groups.google.com/groups/profile?enc_user=5mVZYxMAAAA1-va76P3ter6spmfPToouWMj6vob75xS36mXc24h6ww"&gt;Daniel Vaz&lt;/a&gt; (sniper_cool) que consiste em passar a categoria que deve ser selecionada usando a propriedade &lt;code&gt;initial&lt;/code&gt;.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&gt;&gt;&gt; p = Product.objects.get(pk=1)&lt;br /&gt;&gt;&gt;&gt; pf.fields['category'].initial= p.id&lt;br /&gt;&gt;&gt;&gt; pf.as_table() # retorna nosso formulário como tabela, com valores corretos.&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Qual das soluções escolher?&lt;br /&gt;Isso vai depender de você. Qual você preferer?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8560211453511692375-4859296079088392110?l=pythonidae.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythonidae.blogspot.com/feeds/4859296079088392110/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8560211453511692375&amp;postID=4859296079088392110' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/4859296079088392110'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/4859296079088392110'/><link rel='alternate' type='text/html' href='http://pythonidae.blogspot.com/2007/03/django-e-o-quebra-cabea-com-newforms_27.html' title='Django e o quebra cabeça com newforms'/><author><name>Wiliam Alves de Souza</name><uri>http://www.blogger.com/profile/03875589378985971879</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-8560211453511692375.post-4167628741473444461</id><published>2007-03-26T13:42:00.001-03:00</published><updated>2007-03-28T08:51:48.020-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PyGTK'/><title type='text'>PyGTK widget usando Cairo e Pango</title><content type='html'>Abaixo um widget em &lt;a href="http://www.pygtk.org/"&gt;PyGTK&lt;/a&gt; usando &lt;a href="http://cairographics.org/"&gt;Cairo&lt;/a&gt; e &lt;a href="http://www.pango.org/"&gt;Pango&lt;/a&gt; com Scroll de texto, a ideia é colocar esse widget em um applet Gnome, para que ele fique passando noticias agregadas com o &lt;a href="http://www.gnome.org/projects/straw/"&gt;Straw&lt;/a&gt;.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;import gobject&lt;br /&gt;import pango&lt;br /&gt;import gtk&lt;br /&gt;from gtk import gdk&lt;br /&gt;&lt;br /&gt;class ScrolledTextWidget(gtk.Widget):&lt;br /&gt;..def __init__(self):&lt;br /&gt;....gtk.Widget.__init__(self)&lt;br /&gt; ....self.__start = True&lt;br /&gt; ....self.set_font()&lt;br /&gt; ....self.set_text('Caio Eduardo Canestraro de Souza',&lt;br /&gt;               ..................'Ana Julia Canestraro de Souza')&lt;br /&gt;....# update once a milisecond - time.sleep(0.010)&lt;br /&gt; ....gobject.timeout_add(30, self.do_redraw)&lt;br /&gt;&lt;br /&gt;..def set_font(self, font='Sans', size=10):&lt;br /&gt; ....font = '%s %s' % (font, size)&lt;br /&gt; ....self._font = pango.FontDescription(font)&lt;br /&gt;&lt;br /&gt;..def set_text(self, t, tt):&lt;br /&gt; ....self.p = self.create_pango_layout(t)&lt;br /&gt;....self.p.set_font_description(self._font)&lt;br /&gt;....self.pp = self.create_pango_layout(tt)&lt;br /&gt;....self.pp.set_font_description(self._font)&lt;br /&gt;&lt;br /&gt;..def do_realize(self):&lt;br /&gt;....self.set_flags(self.flags() | gtk.REALIZED)&lt;br /&gt;....self.window = gdk.Window(&lt;br /&gt;....self.get_parent_window(),&lt;br /&gt;....width=self.allocation.width,&lt;br /&gt;....height=self.allocation.height,&lt;br /&gt;....window_type=gdk.WINDOW_CHILD,&lt;br /&gt;....wclass=gdk.INPUT_OUTPUT,&lt;br /&gt;....event_mask=self.get_events() | gdk.EXPOSURE_MASK)&lt;br /&gt;....self.window.set_user_data(self)&lt;br /&gt;....self.style.attach(self.window)&lt;br /&gt;....self.style.set_background(self.window, gtk.STATE_NORMAL)&lt;br /&gt;....self.window.move_resize(*self.allocation)&lt;br /&gt;&lt;br /&gt;..def do_unrealize(self):&lt;br /&gt;....self.window.set_user_data(None)&lt;br /&gt;&lt;br /&gt;..def do_size_request(self, requisition):&lt;br /&gt;....width, height = self.p.get_size()&lt;br /&gt;....requisition.width = 150 # Fixed width&lt;br /&gt;....requisition.height = height // pango.SCALE&lt;br /&gt;&lt;br /&gt;..def do_size_allocate(self, allocation):&lt;br /&gt;....self.allocation = allocation&lt;br /&gt;....if self.flags() &amp;amp; gtk.REALIZED:&lt;br /&gt;....self.window.move_resize(*allocation)&lt;br /&gt;&lt;br /&gt;..def do_expose_event(self, event):&lt;br /&gt;....# Create first context&lt;br /&gt;....c = self.window.cairo_create()&lt;br /&gt;....c.rectangle(event.area.x, event.area.y,&lt;br /&gt;....event.area.width, event.area.height)&lt;br /&gt;....c.clip()&lt;br /&gt;....# Create second context&lt;br /&gt;....cc = self.window.cairo_create()&lt;br /&gt;....cc.rectangle(event.area.x, event.area.y,&lt;br /&gt;....event.area.width, event.area.height)&lt;br /&gt;....cc.clip()&lt;br /&gt;....fw, fh = self.p.get_pixel_size() # First text size&lt;br /&gt;....fww, fhh = self.pp.get_pixel_size() # Second text size&lt;br /&gt;....x, y, h, w = self.get_allocation() # Window size&lt;br /&gt;....if self.__start:&lt;br /&gt;......self.x = h&lt;br /&gt;......self.y = 3 # Fixed value&lt;br /&gt;......self.xx = h + fw + 5&lt;br /&gt;......self.yy = self.y&lt;br /&gt;....# First context&lt;br /&gt;....c.move_to(self.x, self.y)&lt;br /&gt;....c.update_layout(self.p)&lt;br /&gt;....c.show_layout(self.p)&lt;br /&gt;....# Second context &lt;br /&gt;....cc.move_to(self.xx, self.yy)&lt;br /&gt;....cc.update_layout(self.pp)&lt;br /&gt;....cc.show_layout(self.pp)&lt;br /&gt;....if self.x == -fw:&lt;br /&gt;......self.x = self.xx + fww + 5&lt;br /&gt;....elif self.xx == -fw:&lt;br /&gt;......self.xx = self.x + fw + 5&lt;br /&gt;....else:&lt;br /&gt;......self.x = self.x - 1&lt;br /&gt;......self.xx = self.xx - 1&lt;br /&gt;......self.__start = False&lt;br /&gt;&lt;br /&gt;..def do_redraw(self):&lt;br /&gt;....if self.window:&lt;br /&gt;......alloc = self.get_allocation()&lt;br /&gt;......rect = gdk.Rectangle(alloc.x, alloc.y,&lt;br /&gt;...........................alloc.width, alloc.height)&lt;br /&gt;......self.window.invalidate_rect(rect, True)&lt;br /&gt;......self.window.process_updates(True)&lt;br /&gt;....# keep running this event&lt;br /&gt;....return True&lt;br /&gt;gobject.type_register(ScrolledTextWidget)&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/8560211453511692375-4167628741473444461?l=pythonidae.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythonidae.blogspot.com/feeds/4167628741473444461/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8560211453511692375&amp;postID=4167628741473444461' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/4167628741473444461'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/4167628741473444461'/><link rel='alternate' type='text/html' href='http://pythonidae.blogspot.com/2007/03/im-trying-to-make-widget-that-roll.html' title='PyGTK widget usando Cairo e Pango'/><author><name>Wiliam Alves de Souza</name><uri>http://www.blogger.com/profile/03875589378985971879</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-8560211453511692375.post-2033092606846255288</id><published>2007-03-26T13:27:00.000-03:00</published><updated>2007-03-26T13:49:39.291-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Glade'/><category scheme='http://www.blogger.com/atom/ns#' term='PyGTK'/><title type='text'>Widget personalizado usando Glade3 e PyGTK</title><content type='html'>Tutorial escrito por Ali Afshar, mostra como podemos ter nossos widgets feitos com PyGTK disponíveis dentro do Glade3.&lt;br /&gt;&lt;a href="http://unpythonic.blogspot.com/2007/03/custom-pygtk-widgets-in-glade3.html"&gt;Custom pygtk widgets in glade3&lt;/a&gt;&lt;br /&gt;&lt;a href="http://unpythonic.blogspot.com/2007/03/custom-pygtk-widgets-in-glade3-part-2.html"&gt;Custom pygtk widgets in glade3 part 2&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8560211453511692375-2033092606846255288?l=pythonidae.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythonidae.blogspot.com/feeds/2033092606846255288/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8560211453511692375&amp;postID=2033092606846255288' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/2033092606846255288'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/2033092606846255288'/><link rel='alternate' type='text/html' href='http://pythonidae.blogspot.com/2007/03/widget-personalizado-usando-glade3-e.html' title='Widget personalizado usando Glade3 e PyGTK'/><author><name>Wiliam Alves de Souza</name><uri>http://www.blogger.com/profile/03875589378985971879</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-8560211453511692375.post-3639984668274473180</id><published>2007-03-22T13:24:00.000-03:00</published><updated>2007-03-26T13:26:02.591-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Django'/><title type='text'>Django permissões</title><content type='html'>O Django tem um esquema de autenticação onde podemos definir diferentes permissões, todos os modelos definidos em &lt;code&gt;models.py&lt;/code&gt; por padrão tem três &lt;code&gt;add, change e delete&lt;/code&gt;. No exemplo abaixo temos um modelo &lt;code&gt;Pessoa&lt;/code&gt; como um único campo &lt;code&gt;nome&lt;/code&gt; e através do uso do atributo &lt;code&gt;permissions&lt;/code&gt; da classe &lt;code&gt;Meta&lt;/code&gt; definimos duas novas permissões &lt;code&gt;dirrigir_carro e dirrigir_moto&lt;/code&gt;.&lt;br /&gt;&lt;code&gt;&lt;br /&gt;models.py:&lt;br /&gt;&lt;br /&gt;class Pessoa(models.Model):&lt;br /&gt;..nome = models.charField(maxlength=30)&lt;br /&gt;..class Meta:&lt;br /&gt;....permissions = (&lt;br /&gt;......("dirigir_carro", "Pode dirigir caro"),&lt;br /&gt;......("dirigir_moto", "Pode dirigir moto"),&lt;br /&gt;......)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Quando definir novas permissões não esqueça de atualizar a base de dados usando o comando &lt;code&gt; python manage.py syncdb&lt;/code&gt;. Podemos checar por permissões de duas maneiras diferentes, veja abaixo:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;views.py:&lt;br /&gt;&lt;br /&gt;def moto(request):&lt;br /&gt;..if request.user.has_perm('empresa.dirigir_moto'):&lt;br /&gt;....return HttpResponse("Você pode dirigir moto.")&lt;br /&gt;..else:&lt;br /&gt;....return HttpResponse("Tire sua carteira de moto antes")&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;@permission_required('empresa.dirigir_carro')&lt;br /&gt;def carro(request):&lt;br /&gt;..return HttpResponse("Voce pode dirigir carro.")&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;A função &lt;code&gt;moto&lt;/code&gt; usa &lt;code&gt;request.user.has_perm()&lt;/code&gt; para checar se o usuário tem permissão, a parte antes do &lt;code&gt;.dirigir_moto&lt;/code&gt; é o nome da aplicação e não o nome da classe "&lt;code&gt;Pessoa&lt;/code&gt;". Usando uma função como essa você pode redirecionar o usuário para uma página de mais erro explicativa.&lt;br /&gt;A função &lt;code&gt;carro&lt;/code&gt; usa o decorator &lt;code&gt;@permission_required() &lt;/code&gt;para checar por permissão e em casso negativo  redireciona para  página de login normalmente &lt;code&gt;/accounts/login/.&lt;code&gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8560211453511692375-3639984668274473180?l=pythonidae.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythonidae.blogspot.com/feeds/3639984668274473180/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8560211453511692375&amp;postID=3639984668274473180' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/3639984668274473180'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/3639984668274473180'/><link rel='alternate' type='text/html' href='http://pythonidae.blogspot.com/2007/03/django-autenticao.html' title='Django permissões'/><author><name>Wiliam Alves de Souza</name><uri>http://www.blogger.com/profile/03875589378985971879</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-8560211453511692375.post-1263387976537308878</id><published>2007-03-16T15:21:00.000-03:00</published><updated>2007-03-28T08:50:33.800-03:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Django'/><title type='text'>Convertendo a documentação do Django em HTML</title><content type='html'>A documentação do &lt;a href="http://www.djangoproject.com/"&gt;Django&lt;/a&gt; é escrita em formato &lt;a href="http://docutils.sourceforge.net/rst.html"&gt;reST&lt;/a&gt; (ReStructured Text). Então podemos gerar páginas HTML para uma leitura mais divertida, o script &lt;a href="http://code.djangoproject.com/browser/djangoproject.com/django_website/apps/docs/parts/build_documentation.py?rev=3025"&gt;build_documentation.py&lt;/a&gt;  é quem faz isso em djangoproject.com e pode fazer para você também, você só precisa criar um arquivo settings.py  na mesma pasta do script contendo as variáveis DJANGO_DOCUMENT_ROOT_PATH e DJANGO_TESTS_PATH que indica onde  estão seus arquivos reST e o diretório de testes do Django respectivamente .&lt;br /&gt;&lt;br /&gt;Conteúdo de settings.py:&lt;br /&gt;DJANGO_TESTS_PATH='/home/wiliam/dev/django/tests'&lt;br /&gt;DJANGO_DOCUMENT_ROOT_PATH='/home/wiliam/dev/django/docs'&lt;br /&gt;&lt;br /&gt;Dicas:&lt;br /&gt;Rode o comando svn update antes para atualizar seu código.&lt;br /&gt;Mantenha separados os arquivo .txt dos arquivos .html, crie uma pasta html dentro da pasta doc do Django e modifique &lt;a href="http://code.djangoproject.com/browser/djangoproject.com/django_website/apps/docs/parts/build_documentation.py?rev=3025"&gt;build_documentation.py&lt;/a&gt; nas linhas 50 e 51 para fiquem com um + 'html' apos DJANGO_DOCUMENT_ROOT_PATH:&lt;br /&gt;&lt;br /&gt;50 - out_file = os.path.join(settings.DJANGO_DOCUMENT_ROOT_PATH + 'html', os.path.splitext(fname)[0] + ".html")&lt;br /&gt;51 - toc_file = os.path.join(settings.DJANGO_DOCUMENT_ROOT_PATH + 'html', os.path.splitext(fname)[0] + "_toc.html")&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8560211453511692375-1263387976537308878?l=pythonidae.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pythonidae.blogspot.com/feeds/1263387976537308878/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8560211453511692375&amp;postID=1263387976537308878' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/1263387976537308878'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8560211453511692375/posts/default/1263387976537308878'/><link rel='alternate' type='text/html' href='http://pythonidae.blogspot.com/2007/03/documentao-do-django-de-rest-para-html.html' title='Convertendo a documentação do Django em HTML'/><author><name>Wiliam Alves de Souza</name><uri>http://www.blogger.com/profile/03875589378985971879</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></feed>
