-
Blango release coming soon
March 31, 2008 at 00:56:37 CESTI've finally decided how to make the first Blango release: I'm not going to make a release. Instead, I'll be publishing my git repository, so others can pull from it. For now, you'll need to patch Django, altought that will change soon. Keep in mind the database layout will change, so it's not recommended for newbies to start using Blango now. Rule of thumb: use it only if you know how to use ALTER TABLE.
On the other hand, I've registered blango.net, but it still contains the registrar's placeholder page.
-
How to use my patch to the paginator
March 28, 2008 at 02:49:38 CETAs Jiri Barton requested, I'm posting more information about my modifications to the new Django paginator.
First, you'll need to get and apply this patch. It should apply cleanly to current trunk, the 0005 only means it's the fifth change I made in the git repository I use for my patches.
Now, the code. Let's start from urls.py:
urlpatterns = patterns('yourapp.views', (r'^list/(page(?P<page>\d+)/)?$', 'my_list_view'),
So, accordint to urls.py, our function in views.py should have the following prototype:
def my_list_view(request, page):
When an user makes a request to http://www.example.com/list/, page will be None. However, requests made to http://www.example.com/list/page<number>/ will call your function passing number as value for page. Id est, http://www.example.com/page16/ will call my_list_view passing '16' in page.
Now, let's see the prototype for Paginator.__init__() (QuerySetPaginator.__init()__ works in the same way):
def __init__(self, object_list, per_page, orphans=0, allow_empty_first_page=True, base_url=None, page_suffix=None, adjacent_count=2, current=None):
The first four parameters are already defined in the current Django paginator and documented in Django's documentation, so take a look there if you're no familiar with it. The next parameters, defined by this patch are:
- base_url: This is the URL for this request, but without the page suffix. In this example, you'd set it to http://www.example.com/list/ (note the trailing slash).
- page_suffix: This is the suffix you append to base_url when specifying a page number, as a format string containing an integer. In this example, you'd set it to page%d/ (again, note the trailing slash).
- adjacent_count: This defines the number of pages, adjacent to the current page, which are shown in the page list. Aditionally, if first or last page are not included in [current_page - adjacent_count, current_page + adjacent_count], they're also shown with (at most) adjacent_pages next to them. Ok, I'm not very good at explaining things. Let's see some examples.
Let's suppose we have 15 pages and adjacent_count is 2. We have four cases, depending on current page:
- 1: The paginator would show 1 2 3 13 14 15. The start end the end are always shown with adjacent_count pages next to them. In this case, we have no middle block.
- 6: The output would be 1 2 3 4 5 6 7 8 13 14 15. Now, a middle block is added, but since it doesn't include any elements present in the start or the ending block, they contain the same elements as before.
- 2: The output wold be 1 2 3 4 13 14 15. Since the start and middle blocks overlap, the later is omitted but pages are added to the former until current page + adjacent_count is reached.
- 5: The output would be 1 2 3 4 5 6 7 13 14 15. Now the blocks overlap again, but if it were merged, the start would contain more than adjacent_count pages at left of the current page. Instead, elements already present in the middle block are removed from the start block.
So, putting it all together, our view would end in something like:
def my_list_view(request, page): base_url = request.path if page: # Remove page suffix from base_url base_url = base_url[:-1 * len(page) - 1] objects = Objects.filter(foo=bar) paginator = QuerySetPaginator(objects, 5, base_url=base_url, page_suffix='page%d/') page = paginator.page_or_404(page or 1) # If page is None, get first page return render_to_response('list_template.html', { 'page': page })
Now, we're done with the view. Let's move to the template:
<ul> {# iterate over items in this page #} {% for item in page.object_list %} do something with item {% endfor %} </ul> {# show the paginator #} {{ page.paginator.page_list.as_ul }}
That's all. Ok, there's a missing bit: the CSS. Here is an example from this same site:
ul.pagelist, ul.pagelist ul { list-style-type: none; display: inline; float: left; } ul.pagelist { font-size: 0.9em; } ul.pagelist a { display: block; float: left; height: 1.5em; width: 2em; border: 1px solid #00A0E3; text-align: center; margin: 0 0.1em; text-decoration: none; } ul.pagelist a:hover { border-color: #5C3399; } ul.pagelist a.curpage, ul.pagelist a.curpage:hover { background: #00A0E3; border-color: #00A0E3; color: #FFF; } ul.prev-next a { display: block; width: auto; float: left; padding: 0 0.5em; } ul.pagelist ul.start { margin-right: 2em; } ul.pagelist ul.end { margin-left: 2em; } ul.pagelist li { display: inline; margin: 0 0.2em; }
-
New features for Blango
March 27, 2008 at 17:21:37 CETIn first place, let me say I'm really grateful for all your comments. Your input is really appreciated.
I've added a few features to Blango this morning:
- When you're logged in, some links for editing existing entries or adding a new one appear
- Logged in users don't need to specify their name/homepage/email when posting comments
- Comments by staff members have a different background color
- Odd and even comments also have different background colors
- If anonymous users try to post under the name of a registered user, they'll get an error
- Line breaks in comments are kept (thanks Johan for pointing this)
And some fixes as well:
- Time in comments is displayed correctly (it was displaying entry time instead of comment time)
- Don't show drafts in RSS feeds
There's also a new feature in my TODO list, as suggested by Bosco:
- RSS feed including all entries in all languages
On the other hand, as William pointed out, there's already a project named Blango consisting in a blog based in Django. However, looking at its Sourceforge project page it seems the project stalled in the planning stage. Anyway, I'll try to contact the author, so we can find a solution.
-
Blog + Django = Blango
March 26, 2008 at 00:21:06 CETThat's the name I've choosen for the blogging software I'm currently developing and powers this site.
Currently, you'll need a patched Django to run it, but all the changes could be moved to the blog code. However, I think some of them could be usefull for other people, so I submitted the patches to the ticket tracker. I'll be waiting until all of them are accepted or rejected before releasing the blog, so I can definitely put the code in one place or another.
Supported features are:
- Markdown syntax for writing entries
- Source code highlighting
- Saving entries as drafts
- Tags
- Multilanguage (marking entries as translation to others)
- RSS feeds: global, comments for an entry and any tag/language combination
- Pingback and trackbacks, for receiving (with source verification) as well as sending (with auto-discovery)
Planned features are:
- Multilevel tags
- Comment autocitation (e.g. @author will link to last comment by "autor" in the current entry)
- Spam filtering
- Captcha protection (optional)
-
Blog + Django = Blango
March 26, 2008 at 00:02:39 CETEse es el nombre que es escogido para el blog que estoy desarrollando y bajo el que funciona este sitio.
Por ahora, es necesario parchear Django para que funcione, aunque todas las modificaciones que le he hecho podrían moverse al código del propio blog. No obstante, creo que algunas de ellas pueden ser útiles para más gente y he enviado los correspondientes parches al ticket tracker. Así que voy a esperar unos días, para saber si finalmente se aceptan o no, y ubicar definitivamente el código dentro de Django o del propio blog.
Por ahora, las características que hay implementadas son:
- Sintaxis de Markdown para escribir los posts
- Coloreado de código fuente
- Posibilidad de guardar las entradas como borradores
- Etiquetas
- Multilenguaje (con enlaces entre entradas que traducen otras)
- Feeds RSS: global, comentarios de una entrada y cualquier combinación de etiqueta/lenguaje
- Pingbacks y trackbacks, tanto recepción (con comprobaciones de que la fuente enlaza realmente a la entrada), como envío (con autodiscovery)
Y otras que tengo en mente:
- Etiquetas multinivel
- Autocitado de los comentarios (p.e @autor enlaza automáticamente con el último comentario de "autor" para la misma entrada)
- Detección de spam
- Captchas