Unkillable zombie blog

This blog just won't die

May 15, 2010

Tools for generating PDFs from django.

For a Django project i’m working on i needed to generate PDF reports. For example a “job ticket” that displays the client data, the material list and a list of “processing” actions to be performed, or an invoice (classic use case).

What i wanted was a way to generate these PDF files from a template using Django’s templating language. I had previously done something similar using PISA but i was not satisfied. There documentation was rather bad, generating HTML/CSS is not my strong point and automatic tools produce unreadable code. It does work though.

After some heavy and masterful googling i came up with several options.

  1. Reportlab. Very well known, very powerful, but the good parts are not free. I did not want to write the layout using Python code. I’d rather use some high level abstraction on top of Reportlab. Their RML framework (which does exactly that) seems great but as far as i can see it is not free. There are open source alternatives though, which i’ll talk about later.
  2. Pod Uses OpenOffice in server mode to generate documents in PDF. I’ll be running my software in a memory limited VPS and running OpenOffice (even in server mode) seems very scary. I did not investigate the exact memory requirements though because it seemed like a waste of time.
  3. rst2pdf. RST is very awesome, Sphinx uses it but from my reading of rst it seems that generating accurate and custom layouts seems somewhat difficult (for a report that needs specific elements in specific locations).
  4. trml2pdf. This is a tiny and free implementation of RML. This seemed to be a better solution, but what i wanted was a way to generate RML documents using a GUI tool (i’m a lazy bastard). The solution is tiny_sxw2rml which produces an RML document from an OpenOffice .odt file.
  5. JasperReports. This is a very impressive Java package and GUI designer that can generate beautiful reports from various data sources. This was a serious contender (** especially** with their very nice GUI designer) but i chose to avoid it because i could not use the Django ORM to do templating (i can use raw SQL but that is severely suboptimal in templating , especially on complex templates). I could use the Django ORM to produce an XML file with all the information but the prospect of using an XML file (using XPath ) seemed dreadful (but it would work nicely). It is a Java package with Python bindings available for it and a web interface that can be used to access it using a standard interface (HTTP)

The fourth solution (trml2pdf) is the one i chose. These tools are developed by the openerp framework for their reporting needs.

However, it is far from a perfect solution. There is no official repository for this package with various versions floating around the web with different features. More specifically, i was only able to use barcode generation using the version from openerp server source code, which i had to patch to make it work (because it relied on other modules of OpenERP).

Additionally, i had to patch it to make it work with unicode fonts as per the instructions from the OpenErp Docs. Not something you would want to depend on.

Nevertheless i was able to make it all work. I could use the tool tiny_sxw2rml to produce an rml template that would first be processed by the Django templating system and then fed into trml2pdf to produce a PDF. It works.

All in all i would have to say that JasperReports is the best solution from a technical standpoint since it has a great GUI designer that produces beautiful documents with perfect layout, has a lot of features, a large community, can be used as an independent server that produces PDF documents and much much more. The main problem is that you lose that advantage of integrating your workflow into the philosophy of Django (ORM/templates etc) and have to walk the extra mile.

I’ve already integrated trml2pdf but i’m keeping my eye open for a way to switch to JasperReports.

I’d like to hear what solutions others may have used/considered for this.

Click to read and post comments

May 11, 2010

Deployment with Fabric

Τί είναι:

To fabric είναι ένα εργαλείο για αυτοματοποίηση εργασιών μέσω SSH που διευκολύνει το deployment ή την διαχείρηση συστημάτων.

Συγκεκριμένα, πρόκειται για ένα command line εργαλείο και μια βιβλιοθήκη (API) γραμμένη σε Python που επιτρέπει την εκτέλεση προγραμμάτων command line ή και Python κώδικα, σε τοπικό η και απομακρυσμένο server(s).

Παράδειγμα:

Έστω οτι έχω ένα Django site που το αναπτύσσουμε στον υπολογιστή μας, και τρέχουμε ένα production server σε ένα VPS.

Οταν έχω μια νέα έκδοση του site μου, τρέχω μερικές εντολές στο τοπικό PC (πχ το test framework, κάνω push τις αλλαγές κλπ), μετά κάνω login στο VPS μου μέσω SSH και κάνω τις αναβαθμίσεις. Αυτά τα βήματα μπορούν, αφού καταγραφούν, και μετά να αυτοματοποιηθούν κάνοντας χρήση του fabric.

Εγκατάσταση.

Η εγκατάσταση είναι πολύ έυκολη. easy_install fabric ή απο το package manager της διανομής μας

Το fabfile

Το πρώτο βήμα για την χρήση του fabric είναι η δημιουργία του αρχείου στο οποίο βάζουμε τις “εντολές” μας. Το αρχείο αυτό το ονομάζουμε fabfile.py γιατί με αυτό το όνομα το βρίσκει αυτόματα το εργαλείο fab (το command line εργαλείο του fabric)

Στο fabfile αρχείο καταγράφουμε τις διάφορες “λειτουργίες” που θα εκτελεί το Fabric.

Παράδειγμα:

def hello():
    print "Hello world"

Τώρα μπορούμε να τρέξουμε την “hello” τρέχοντας:

arcanum@localhost ~ $ fab hello

Το fabric αυτόματα θα ψάξει για ένα αρχείο με όνομα fabfile.py και μέσα του για ένα callable με όνομα hello και θα το εκτελέσει.

Φυσικά αυτό είναι υπερβολικά απλό και όχι ιδιαίτερα χρήσιμο απο μόνο του. Η χρησιμότητα του Fabric έρχεται απο το API του.

Παράδειγμα με το API του Fabric

Όπως είπαμε θέλουμε να τρέξουμε μερικές εντολές στο τοπικό PC και μερικές στο απομακρυσμένο. Το fabric μας παρέχει ένα API για αυτή την δουλειά Αυτό είναι ένα (τροποποιημένο για πολλούς λόγους) script που χρησιμοποιώ σε ένα project μου.

def import datetime
from fabric.api import local, run, cd, env

# The app directory of metaxas.gr
PROJECT_DIR='/home/arcanum/django_projects/myproject'

env.hosts = ['arcanum@metaxas.gr:2000']

def deploy():
    backup_database()
    sync_remote_repo()
    run_migrations()
    restart_wsgi()

def push_updates():
    """
    Push updates from local repo to remote repo
    Does *NOT* commit uncommited modifications
    """
    # TODO check for uncommitted modifications and give warning
    local("hg push")

def sync_remote_repo():
    """
    Sync the remote stable repository on the production server
    """
    with cd(PROJECT_DIR):
        run('hg pull')
        run('hg up')

def run_migrations():
    """
    Run any migration on the remote server
    """
    with cd(PROJECT_DIR):
        run('./manage.py migrate')


def restart_wsgi():
    """
    Restart the WSGI app by 'touch'ing the wsgi file.
    Thi means updating the last modification date of that file, which is
    monitored by the WSGI app server
    """
    with cd(PROJECT_DIR):
        run('touch wsgi/django.wsgi')


def backup_database():
    """
    Make a backup of the database.
    """
    with cd(PROJECT_DIR):
        now = datetime.datetime.now()
        now_str = now.strftime("%d-%m-%Y")
        BACK_CMD = 'pg_dump --format=t mydatabase |bzip2 > mydatabase-%s.sql.bz2'%(now_str, )

        run(BACK_CMD)

Θεωρώ οτι είναι αρκετά απλό παράδειγμα και κάποιος με εμπειρία στην Python θα καταλάβει αμέσως τι γίνεται όμως θα ανεφέρω μερικά πράγματα:

  1. Τρέχοντας fab deploy το fabric θα βρεί την function με όνομα deploy και θα την εκτελέσει. Αυτή με την σειρά της καλεί διάφορες άλλες functions μέσα στο fabfile.

  2. Απο το API του fabric χρησιμοποιούμε μερικές τυπικές λειτουργίες όπως local , run, cd κλπ.

Η local μας δίνει την δυνατότητα να τρέξουμε μια εντολή (σαν να είμασταν στο shell) στο τοπικό μηχάνημα.

Η run τρέχει μια εντολή (πάλι shell) στο remote μηχάνημα. Αυτό γίνεται transparently μέσω SSH. Το remote host τον βρίσκει απο το την env.hosts λίστα. Θα μπορούσαμε να συνδεόμαστε σε πολλούς hosts (αν για παράδειγμα είχαμε πολλούς web server σε ένα scalable site).

Το cd κάνει αυτό που φαντάζεσται. Η ανάγκη του προέρχεται απο την έλλειψη state της των shell-less SSH συνδέσεων. Το cd έχει ένα context manager (with statement ) οπότε οτι τρέχει μέσα στο context του with γίνεται prepend το path.

Γενικά το fabric λύνει πολλά προβλήματα έυκολα και γρήγορα. Απο οτι διαβάζω υπάρχουν πιο ευέλικτες αλλά πιό πολύπλοκες λύσεις αλλά δεν έχω ασχοληθεί γιατί το fabric είναι ικανότατο.

Το API του fabric είναι, προφανώς, πολύ μεγαλύτερο με δυνατότητες για prompts, file transfers, κλπ.

Για περισσότερα ανατρέξτε στο fabric documentation

Click to read and post comments

Dec 11, 2009

Hi5 security issues.

One of my servers had a lot of traffic due to image hotlinkers (they are now being served Goatse) and while examining the logs i noticed an unusual referer from hi5. It had get variables like loginToken , loginid and reviewCommentLink. I thought that was a little strange and thought, could it be?

One click later i was logged in as some Mexican guy.

I never liked Hi5, but i can’t deny its one of the big social networking sites. Using information in links that can log someone in without any validation (or, at least, expiring them upon first use), is a serious mistake. Its not a mistake i would expect from the likes of Hi5.

I thought about reporting it, but after a google search i came upon this blog post which describes the same issue and that guy has already reported it. So, there’s no point of reporting it again. They know and don’t care. That post is from 2006.

This is really sad. This seems like a very exploitable hole. Host an image in your server that enough people will click ( keira knightley is a great choice :p ) and just wait until you get this kind of link in your referer log. It doesn’t get any simpler. (the image on my server was probably used as a profile image for someone else)

Click to read and post comments

Oct 16, 2009

Django generic relations in test fixtures

Το Django framework περιλαμβάνει μια λειτουργικότητα που την ονομάζει content types. Το content types framework επιτρέπει, μεταξύ άλλων, στο Django να έχει λειτουργίες όπως τα generic relations

Ο τρόπος λειτουργίας είναι σχετικά απλός. Το content types framework βασικά λέει:

Για κάθε μοντέλο του ORM φτιάχνω μια εγγραφή στον πίνακα django_content_type που περιέχει ,μεταξύ άλλων, το όνομα του application και το όνομα του μοντέλου και φυσικά ένα ID.

Το generic relationship επιτρέπει σε ένα μοντέλο να έχει ένα foreign key σε ένα οποιοδήποτε άλλο μοντέλο στο django. Αυτό το επιτυγχάνει προσθέτοντας 2 πεδία στο μοντέλο που περιέχει το foreign key. Το content type και το id.

Έστω οτι έχουμε ένα μοντέλο Comment. Μιας και θέλουμε το Comment μπορεί να μπορεί να αναρτηθεί σε διάφορα μοντέλα (πχ Story, άλλα Comments, News, Product κλπ) χρησιμοποιούμε generic relations. Αν ονομάζαμε το πεδίο αυτό “commenting_on” τότε όταν ζητήσουμε απο το django να μας δώσει το object στο οποίο δείχνει το commenting_on, το Django θα δεί το content_type πεδίο, θα αναζητήσει την αντίστοιχη εγγραφή στον πίνακα django_content_types και θα βρεί το application και model στο οποίο αναφερόμαστε. Γνωρίζοντας αυτά, και αφού έχει και το id μπορεί έυκολα να μας επιστρέψει ένα instance του μοντέλου.

Εδώ πρέπει να αναφέρω μιά ακόμα τεχνολογία του django. Το serialization framework που μας επιτρέπει να κάνουμε serialize και να εξάγουμε τα δεδομένα μας σε αρχείο κειμένου (YAML,XML, JSON και άλλα) όπως και να τα εισάγουμε στην βάση μας απο ένα serialized αρχείο.

Τα serialization είναι εξαιρετικά χρήσιμο σε πάρα πολλές περιπτώσεις, με πιθανότατα πιο συχνή το Testing framework, όπου μας δίνει την δυνατότητα πριν απο κάθε test να φορτώνουμε κάποια γνωστά δεδομένα στην database.

Όταν κάνουμε serialize ένα μοντέλο που περιέχει generic foreign keys, οι serializers του Django απλά καταγράφουν το content_type_id και το object_id.

Εδώ δημιουργείται το πρόβλημα.

Τα content_types φτιάχνονται κατα το syncdb (κάτι που γίνεται στην αρχή του test runner ) και τα id που θα πάρουν εξαρτώνται απο την σειρά με την οποία θα διαβάσει τις εφαρμογές και τα μοντέλα το django. Τα test fixtures που φτιάξαμε νωρίτερα μεσω του serializer θα βγούν άχρηστα όταν για κάποιο λόγω αλλάξουν τα id των content types, και τα test μας θα αρχίσουν να σπάνε και χωρίς εμείς να ξέρουμε γιατί (αφού τα φόρτωσε χωρίς πρόβλημα).

Δυστυχώς δεν υπάρχει καλή λύση για αυτό το πρόβλημα.

Μια προσωρινή αλλα πολύ άσχημη λύση είναι στο test να κάνουμε lookup για το σωστό content type και να το αλλάζουμε on-the-fly. Yuck.

Είμαι γκαντέμης ή απλά άτυχος? :p

posted at 14:12  ·   ·  django  ellak  bug
Click to read and post comments

Dec 14, 2008

Τhe Alexandros Grigoropoulos’s Diary Release

Αν και σπανίως βλέπω τηλεόραση, έχω δεί οτι η υπόθεση με την δολοφονία του 15χρονου Αλέξανδρου Γρηγορόπουλου έχει γίνει διεθνώς είδηση.
Δεν είχα συνειδητοποιήσει, όμως, πόσο έχει επηρεάσει την διεθνή κοινότητα μέχρι που στο community (planet βασικά) του Django είδα να ονομάζουν την νέα release του diario blogging software με τίτλο “The Alexandros Grigoropoulos’s Diary Release”

Οπως αναφέρουν στο project :

This version is a tribute to Alexandros Grigoropoulos, 15-year-old boy, libertarian, murdered by greek police in last week (2008-12-06).

Συνήθως η προγραμματιστική κοινότητα είναι πολύ απομακρυσμένη απο την πολιτική/κοινωνική επικαιρότητα, και σίγουρα αυτή η πρακτική δεν είναι κάτι συχνό.

Ενδιαφέρον…

(Βέβαια εδώ έχουν σπάσει και κάψει το σύμπαν και εγώ περιμένω ένα release άγνωστου software για να καταλάβω τι έχει γίνει? Έκαστος στο είδος του :p )

Click to read and post comments

Dec 03, 2008

Django CSRF tag for AJAX POST calls.

Το Django μας παρέχει (προαιρετικά) το CSRF middleware του οποίου η δουλειά είναι να αποτρέπει τις επιθέσεις CSRF. Για να το πετύχει αυτό, στα response object βρίσκει τις φόρμες με POST method και “εισάγει” ένα ακόμα κρυφό field που περιέχει ένα token μοναδικό για το session. Στα POST request επιβεβαιώνει οτι το token υπάρχει και είναι σωστό.

Όλα ωραία και καλά, αλλα αυτός ο τρόπος έχει το πρόβλημα ότι όταν θέλουμε να κάνουμε AJAX κλήσεις με POST requests δεν θα δουλέψουν γιατί το CSRF middelware δεν θα βρεί tokens.

Για να λύσω αυτό το πρόβλημα με τον πιό απλό τρόπο έφτιαξα ένα template tag που παρέχει ένα token στα template μου.

Έτσι, για παράδειγμα στο YUI όταν κάνω το request είναι κάπως έτσι:

1
2
3
4
{%csrf_token as token    %}
params = "ham="+ham+"&eggs="+eggs + "&csrfmiddlewaretoken={{token}}" ;
var transaction = YAHOO.util.Connect.asyncRequest("POST", {%url spam%},
    callback, params);

Μιας και βασίζεται στην ύπαρξη του sessionid στο cookie, αυτό το tag δεν θα μας δώσει token όταν ο χρήστης έχει απενεργοποιήσει τα cookies (κάτι που σπάει ένα σκασμό site οπότε δεν με πολυνοιάζει) και όταν είναι το πρώτο request στο site μας. (Μπορούμε όμως να ελέγξουμε αν υπάρχει το token και να πράξουμε κατάλληλα)

Ορίστε και το tag:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from django.conf import settings
from django.utils.hashcompat import md5_constructor
import re

class CsrfNode(template.Node):
"""
Tag that provides a CSRF token in the context.
Usage: {% csrf_token as token %}
If the user has no cookies (cookies disabled, or this is
the first ever page view on the site, this tag will provide
an empty token. You can test that (eg to refresh the page)
"""

def __init__(self,var_name):
    self.var_name = var_name

def render(self,context):
    SESSION_COOKIE_NAME = getattr(settings,
            "SESSION_COOKIE_NAME","sessionid")
    sess_key = context['request'].COOKIES.get(SESSION_COOKIE_NAME,None)
    if not sess_key:
        # User has no cookie. Empty token.
        token = ""
    else:
        val = settings.SECRET_KEY + sess_key
        token = md5_constructor( val  ).hexdigest()
    context[self.var_name] = token
    return ''

@register.tag(name='csrf_token')
def do_csrf_token(parser,token):
    try:
        tag_name , params = token.contents.split(None,1)
    except ValueError:
        msg = "%r tag requires arguments" % token.contents.split()[0]
        raise template.TemplateSyntaxError(msg)
    m = re.search(r'^as (\w+)$', params)
    if not m:
        msg = "%r tag had invalid arguments" % tag_name
        raise template.TemplateSyntaxError(msg)
    var_name = m.groups()[0]
    return CsrfNode(var_name)

Ελπίζω να είναι bug free :p

Click to read and post comments

Nov 09, 2008

Django tips (part 1)

Στην ενασχόλησή μου με το Django έχω κάνει πολλά λάθη και έχω μάθει με τον δύσκολο τρόπο (βλέπε “χτυπάω το κεφάλι μου στον τοίχο” ). Κάνω μια προσπάθεια λοιπόν να καταγράψω μερικά χρήσιμα tips που ελπίζω να κάνουν την ζωή σας λίγο πιό εύκολη η/και να αποφύγετε τα δικά μου λάθη

Pluggables

Πλέον, υπάρχουν πάρα πολλά pluggables για Django. Πριν ξεκινήσετε να γράφετε κάποια λειτουργικότητα , κάντε μια αναζήτηση να βεβαιωθείτε οτι δεν υπάρχει ήδη κάποιο pluggable που κάνει την δουλειά που θέλετε να κάνετε. Ένα site με αρκετά καλή συλλογή απο pluggables είναι το http://djangoplugables.com/.

Ένα pluggable που θα σας βοηθήσει πάρα πολύ , ειδικά στο debugging είναι το django-command-extensions που σας δίνει κάποια υπέροχα εργαλεία για να κάνετε την ζωή σας ποιό έυκολη. Κυρίως προσφέρει νέες εντολές για το manage.py.
Για παράδειγμα σας δίνει το shell_plus που κάνει αυτόματα import όλα τα μοντέλα σας (μεγάλη ευκολία) και διάφορα άλλα. Το σημαντικότερο όμως είναι οτι εαν έχετε εγκαταστήσει το Werkzeug τότε κάνει χρήση του debugger του, και στα traceback στον browser σας δίνει ένα καταπληκτικό AJAX console debugger. Για να δείτε το werkzeug τρέχετε:

./manage.py runserver_plus

(πάντα κάνω chmod +x manage.py για ευκολία )

named urls

Τα named urls είναι μια αντιστοιχία ονόματος (python string) με ένα URL. Αυτό σημαίνει οτι στα urls.py θα προσθέτεις την name=”myname” παράμετρο. Παράδειγμα:

1
2
url(r'^tag/(?P<tagname>\w+)/$','view_profiles_for_tag',
    name='profiles-for-tag'),

Προσέξετε οτι πλέον κάθε url pattern είναι το αποτέλεσμα της url() function και όχι απλά ένα tuple. Αυτό μας δίνει την δυνατότητα να χρησιμοποιήσουμε 2 πολύ σημαντικά εργαλεία. Την reverse() μέθοδο απο το django.core.urlresolvers και το {% url %} template tag. και τα 2 κάνουν την ίδια δουλειά, απλά η reverse() είναι χρήσιμη στα views (ή models) και το {%url%} στα templates. Η δουλειά τους είναι να βρούν το URL που θέλετε με βάση το όνομα (και τις παραμέτρους, αν το URL πάιρνει παραμέτρους).

Local settings

Μια ακόμα καλή πρακτική είναι που θα σας βοηθήσει πάρα πολύ στο deployment είναι να έχετε την εξής γραμμή στο τέλος του settings.py σας:

1
from local_settings import *

και να φτιάξετε ένα local_settings.py το οποίο θα το έχετε εκτός version control και στο οποιό θα μπορείτε να κάνετε override τιις ρυθμίσεις στο settings.py. Για παράδειγμα μπορείτε να έχετε άλλα paths (πχ για MEDIA_ROOT ) , άλλες ρυθμίσεις για DATABASE, για mail servers κλπ. Επιπλέον, στο settings.py μπορείτε να προσθέσετε το εξής στην αρχή :

1
2
import os.path
PROJECT_ROOT = os.path.normpath(os.path.dirname(__file__))

Με αυτό τον τρόπο έχετε μια μεταβλητή, το PROJECT_ROOT με το PATH του project σας. Μπορείτε τα υπόλοιπα paths να τα φτιάχνετε σχετικά με αυτή την τιμή αντί να τα κάνετε hardcode στο settings.py. Για παράδειγμα το TEMPLATE_DIRS μπορεί να είναι κάπως έτσι:

1
2
3
TEMPLATE_DIRS = (
    os.path.join(PROJECT_ROOT, 'templates'),
)

MEDIA_URL

Μια πρακτική που θα σας γλιτώσει απο μπελάδες είναι να χρησιμοποιείτε την MEDIA_URL μεταβλητή στα template σας.
Μπορεί σήμερα στον developement περιβάλλον σας να έχετε το MEDIA_URL="" αλλα άυριο στο deployment το πιθανότερο είναι να θέλετε να τρέχετε ένα media.myproject.com όπου θα σερβίρει τα media.
Σε αυτή την περίπτωση τα URL που θα έχετε γράψει στα template σας θα χρειάζονται αλλαγή.
Αυτό ισχύει για αντικείμενα όπως CSS ή εικόνες που δεν τις διαχειρίζεται το Django (οχι ImageFields δηλαδή). Στην περίπτωση τον FileField/ImageField υπάρχει το ειδικό attribute url που δίνει το σωστό url λαμβάνοντας υπόψιν του την ρύθμιση MEDIA_URL.
 Παράδειγμα:

1
<link rel="stylesheet" type="text/css" href="{{MEDIA_URL}}css/main.css" media="screen" />

RequestContext

Για να υπάρχει το MEDIA_URL διαθέσιμο στα template σας δεν αρκεί το κλασικό Context που περνάει το Django απο τα views στα templates. Χρειάζεστε το ειδικό RequestContext (που είναι subclass του Context). Το κλασικό Context στα view είναι κάπως έτσι:

1
return render_to_response('my_template.html',data_dict)

Για να περάσετε το RequestContext θα δώσετε ένα τρίτο argument στο render_to_reponse, ώς εξής:

1
2
return render_to_response('my_template.html', data_dict,
            context_instance=RequestContext(request))

To RequestContext ουσιαστικά λαμβάνει υπόψιν του την ρύθμιση TEMPLATE_CONTEXT_PROCESSORS στο settings.py και εκτελεί κάθε context_processor. ( ένα context processor, τροποποιεί το context που πάει στo template και εκτελείται σε κάθε request. Είναι κάτι σαν middelware.)
Υπάρχουν αρκετά default context processors αλλα είναι πάρα πολύ έυκολο να γράψετε το δικό σας, αν θέλετε κάθε template να έχει έξτρα μεταβλητές στο RequestContext που λαμβάνει.

posted at 18:46  ·   ·  ellak  django  tips  greek
Click to read and post comments

Sep 12, 2008

Ξεκίνημα του www.gentoo-users.org

Πριν λίγο ανέβασα το www.gentoo-user.org.
Είναι ένα google maps mashup όπου οι χρήστες της διανομής Gentoo μπορούν να γραφτούν και προσθέσουν την γεωγραφική θέση τους.

Μπορείτε να δείτε τους πλησιέστερους χρήστες σε εσάς (με χιλιομετρική απόσταση) να δείτε το προφίλ τους και γενικά είναι μια προσπάθεια να δούμε που υπάρχουν κοινότητες (η να δημιουργηθούν!).

Το site δουλέυει με Django με χρήση του contrib.gis (GeoDjango). Τρέχει στο slicehost, σε διανομή … Gentoo :p

Ελπίζω να κάνω και διαθέσιμο μέσω open source άδειας τον κώδικα σύντομα.

Click to read and post comments

Sep 04, 2008

The eagle has landed

Με 4.000 commits, 2.000 bug fixes , προσθαφαιρέσεις 350.000 γραμμών κώδικα,και 40.000 νέες γραμμές documentation το Django 1.0 είναι εδώ.
Στις πολύ σοβαρές αλλαγές σε σχέση με την προηγούμενη έκδοση (0.96.x) έχουμε:
  • Refactored ORM. Με προσθήκη inheritance, και πολλά νέα κόλπα.
  • Newforms. Το νεο σύστημα των forms που αντικαθιστά το παλαιό.
  • Νέο Admin βασισμένο στο newforms
  • GeoDjango. Το Γεωγραφικό framework για Django υπάρχει πλέον σαν contrib στο django.contrib.gis
  • Βελτιωμένη υποστήριξη unicode
  • Αυτόματο escaping στις μεταβλητές στα templates. Προσθέτει ασφάλεια σε XSS attacks.
  • Νέα διαχείριση των αρχείων (και uploads). Πλέον είναι pluggable. Θες τα uploads να πηγαίνουν απευθείας στο S3 Amazon storage? Κανένα πρόβλημα
  • Νέο django.contrib.comments. Το παλαιό έτσι και αλλιώς ήταν undocumented γιατι θα άλλαζε. Η αλλαγή έγινε και έχουμε και documentation.

Υπάρχουν πάρα πολλές αλλαγές μικρότερης εμβέλειας,πολλά bugs που φτιάχτηκαν (και ένα δικό μου :p ).
Απο τα αγαπημένα μου είναι τα named url patterns, όπου δίνεις ένα όνομα στο URL που θες και στα templates δεν κάνεις hardoced τα links αλλα τα ‘ζητάς’ με ένα ειδικό template tag {%url urlname%}. όπου urlname το όνομα του url που έχεις δώσει στο urls.py. Ετσι μπορείς να αλλάξεις όλη την δομή των URL σου χωρίς καμμία αλλαγή στην HTML σου.
Click to read and post comments