Posted
14 days
ago
Hace un par de días se ha liberado la versión 1.0 final de Haystack. Haystack es probablemente la forma más sencilla de añadir un sistema de búsqueda a Django. Ofrece una API que permite utilizar distintos backends de búsqueda como Solr, Whoosh
... [More]
ó Xapian. Además ofrece una interfaz para realizar las búsquedas llamada SearchQuerySet que es muy similar a las QuerySets de Django. [Less]
Posted
15 days
ago
Haystack 1.0.0-final has been released (via the packages at
PyPi or
GitHub).
You can also install it via ``sudo pip install django-haystack`` or via git
from GitHub.
The goal of Haystack is to
... [More]
provide modular search for Django. This means
pluggable backends (Solr, Whoosh & Xapian currently), a reusable app
architecture, the ability to add search to third-party modules without
modifying their sources and a flexible codebase
with many points of extension. The crown jewel is the ``SearchQuerySet``,
which provides a ``QuerySet``-like interface to your search index. Included
with the main install is everything needed to get basic search up and
running in short order and yet powerful enough to provide search to some
decent-sized
sites. And there's a fair amount of
documentation available.
As with Django, Haystack will attempt to remain backward-compatible for the
duration of the 1.X series, though there are no guarantees on this. Should
a backward-incompatible change come up, I will post full disclosure on
the changes on the mailing list as well as the commit itself.
Some fun facts about Haystack's development:
315 days in development (from first commit to 1.0-final).
420 public commits with another 100 or so that were squashed.
27 people in AUTHORS.
3 complete backends.
121 closed issues.
It's been a long ride, especially given I thought I was going to be ready
to mark it as 1.0 many months sooner. And there are some good features lined
up for 1.1, which I'll be starting on shortly. It's been exciting and I'm
looking forward to what's next. A big thanks to everyone who contributed
bug reports and patches.
Finally, the entire project would've been completely impossible without the
support of my wife Moriah, who graciously accepted the many (late) hours I
put into Haystack and did lots of editing for me in both the documentation
and mailing list posts. [Less]
Posted
15 days
ago
Recently I had a bit of an interesting problem, I needed to define a way to represent a C++ API in Python. So, I figured the best way to represent that was one class in Python for each class in C++, with a functions dictionary to track each of the
... [More]
methods on each class. Seems simple enough right, do something like this:
class String(object):
functions = {
"size": Function(Integer, []),
}
We've got a String class with a functions dictionary that maps method names to Function objects. The Function constructor takes a return type and a list of arguments. Unfortunately we run into a problem when we want to do something like this:
class String(object):
functions = {
"size": Function(Integer, []),
"append": Function(None, [String])
}
If we try to run this code we're going to get a NameError, String isn't defined yet. Django models have a similar issue, with recursive foreign keys. Django's solution is to use the placeholder string "self", and have a metaclass translate it into the right class. Also having a slightly more declarative API might be nice, so something like this:
class String(DeclarativeObject):
size = Function(Integer, [])
append = Function(None, ["self"])
So now that we have a nice pretty API we need our metaclass to make it happen:
RECURSIVE_TYPE_CONSTANT = "self"
class DeclarativeObjectMetaclass(type):
def __new__(cls, name, bases, attrs):
functions = dict([(n, attr) for n, attr in attrs.iteritems()
if isinstance(attr, Function)])
for attr in functions:
attrs.pop(attr)
new_cls = super(DeclarativeObjectMetaclass, cls).__new__(cls, name, bases, attrs)
new_cls.functions = {}
for name, function in functions.iteritems():
if function.return_type == RECURSIVE_TYPE_CONSTANT:
function.return_type = new_cls
for i, argument in enumerate(function.arguments):
if argument == RECURSIVE_TYPE_CONSTANT:
function.arguments[i] = new_cls
new_cls.functions[name] = function
return new_cls
class DeclarativeObject(object):
__metaclass__ = DeclarativeObjectMetaclass
And that's all their is to it. We take each of the functions on the class out of the attributes, create a normal class instance without the functions, and then we do the replacements on the function objects and stick them in a functions dictionary.
Simple patterns like this can be used to build beautiful APIs, as is seen in Django with the models and forms API. [Less]
Posted
15 days
ago
Recently I responded to the question on Stack Overflow about wether Google App Engine is worth it, over conventional hosting providers for typical databased-backed setup.
I will not recite all the pros and cons of App Engine as I already did that
... [More]
in my answer, but I would like to focus on one interesting aspect of Google App Engine where it wins big time over conventional hosting approaches.
In particular - the deployment process. Let's get started...
Deploying on regular hosting environment
How do you deploy a web application (like Django for example) to an Apache-backed hosting server? Well there are a few steps you have to take:
FTP or SCP your applicaton to the server
Replace the folder with the new folder
Stop the server, services etc..
Start the server services etc...
BONUS: Modify your databse schema
Of course if you are proper developer you might simplify you deployment process and also make use of revision control system. You can also write a script to automate the deployment process, in particular for steps 3-5:
Commit your code to revision control, possibly marking it with a tag for Release or Deployment.
Log onto your producton server
Check out the code to be deployed. Note that doing just an update from revision control is possible, but it's better to do a "full" checkout.
Replace the production folder or files with the newly checkout out sources.
Stop and start and server, processes, services etc... (this is where automated script really helps)
BONUS: Modify your databse schema
Even though the second approach seems more involved it is more proper and error-proof. You can always go back to previous version of the code from revision control, and also having an automatic script to stop and start your server and services eliminates any guesswork.
However you can see that this is still a lengthy process, oftentimes very complicated to setup just right, and most imporantly it varies from project to project.
Deploying on Google App Engine
Now let's take a look at deploying your web application on App Engine:
Type "appcfg.py update you_app_name" in terminal on Linux-based system or click Depoy in Google App Engine launcher on Windows.
The script automatically bundles your application, uploads it to the server, puts the files in all the right places and automatically restarts it.
One of the conviniences of this approach is that it separates the revision control of your application from the deployment. After you commit your whole app engine web project to revision control, your deployment proess becomes something like this:
Commit your changes to revision control.
Put your code into the deployable state. I.e.: use your revision control to revind or forward the state to that which you want to be on the server, optionally marking it with a tag.
Execute deploy command.
There is something natural about deploying the code from your version of the code, just as you have it right now. It's as if Google App Engine and Revision control were made for each other.
BONUS: Versioning
Another helpful feature is the Google App Engine is version string. That is you can deploy your app in a few different versions.
So for example above I've deployed a simple demo application to three different versions: 1, 2, and experimental. This gives one great flexibility to put out a test or beta release of your application.
The default version runs on the regular domain name, in my case duriyko.appspot.com, and is the one visiable to all your visitors.
While the other versions are accessible through special urls, like http://version.subdomain.domain.com or something similar. Note that the latest version also has a special "latest" subdomain, for easy identification.
Conclusion
In the end I think deploying with Google App Engine is a pleasant experience. It is a great boon when you need to get your website from Development to Production in record time. It also makes creating simple sites, like for your school or experiment projects, extremetly fast.
Overall I think everyone should try App Engine for toolset it offers. [Less]
Posted
15 days
ago
Haystack 1.0 Final Released. I’ve used Haystack on a number of projects recently, and it has proved itself as a completely painless way of adding full-text search (using Solr or Whoosh—I haven’t tried the Xapian backend yet) to a Django ORM powered project in just a few minutes. Congratulations, Daniel + contributors.
Posted
15 days
ago
Send this to your significant other/parent/relative/friend so, instead of that sweater, you get one of these nuggets of awesome this Christmas.
The Pragmatic Programmer: From Journeyman to Master
Write better, cleaner, more maintainable code.
... [More]
Learn how to manage your projects and focus on shipping your product. With insight that covers the gamut of software development [...]
Related posts:Be Language Agnostic – Solve the Problem!Django 1.0 Template Development: Sample Chapter “Serving Multiple Templates”Django and Python First Impressions – Part II [Less]
Posted
15 days
ago
uWSGI project [1] reaches the 0.9.3 milestone. You can review the complete announcement [2] on the mailing list and download the code here [3]
This new release brings some new exiting features :
- Nginx 0.7.x module
-
... [More]
configuration via python module
- support (non-standard) for Python 3.x
- Twisted client resource adapter
- graceful restart of worker processes and hot-plug substitution/upgrade
of the uWSGI server
- shared memory area to share data between workers/processes
- Tomcat handler
- support for virtualenv
In this post [4] I have covered the usage of both the "configuration via a python module" and the "virtualenv support".
uWSGI allows you to run your favorite wsgi application on top of prefered web server (apache, cherokee or nginx).
[1] http://projects.unbit.it/uwsgi/
[2] http://lists.unbit.it/pipermail/uwsgi/2009-November/000020.html
[3] http://projects.unbit.it/downloads/uwsgi-0.9.3.tar.gz
[4] http://yml-blog.blogspot.com/2009/11/setting-up-django-project-with-cherokee.html [Less]
Posted
15 days
ago
The other day I was helping a friend get their Django site back online, and I found myself doing a couple of very similar commands when backing up the databases:
$ pg_dump -U some_database -f some_database_backup.sql
I use Bash as
... [More]
my shell in Linux, and apparently it's capable of doing some neat string substitution. I wanted to try something I had seen a few days prior to save myself a few keystrokes. ... [Less]
Posted
16 days
ago
Una de les característiques que més m'agraden de Django per desenvolupar és que ja ve amb el seu propi servidor integrat. És un servidor no apte per entorns de producció, de fet a les planes de Django es recomana repetides vegades que NO es faci
... [More]
servir a producció, però que va molt bé al desenvolupament.
El que fa tenir aquest servidor és per una banda acursar el temps necessari per començar a desenvolupar. Una vegada creat el projecte i la primera aplicació, posam el servidor en marxa amb un python manage.py runserver i ja tenim accés a un complet servidor web.
A més ens permet depurar des del principi les nostres aplicacions. La consola del servidor que acabam d'executar mostrarà els missatges del servidor i els logs que li enviem com un servidor web qualsevol, però a més ens servirà de consola de depuració de Python.
Encara que hi ha entorns com Eclipse+Pydev que ens permeten posar punts de ruptura directament al codi, un dels mètodes més simples consisteix en escriure import pdb;pdb.set_trace() allà on vulguem que s'aturi el programa. Llavors, en arribar-hi a la consola on hem executat el servidor ens apareixerà l'entorn de depuració de Python (el pdb). Si volem fer un poc més de feina podem instal·lar l'ipdb i tendrem una consola de depuració amb autocompletat i resaltat de sintaxi.
A Python diuen allò de "batteries included" per indicar que amb Python hi ha tot el necessari per arrancar, Django segueix la mateixa filosofia, de manera que no necessitam configurar cap servidor web per començar a fer-hi feina i ens proporciona a més eines de depuració prou potents: la possibilitat de depurar amb pdb/ipdb o semblants, la depuració mitjançant els missatges d'error de les plantilles o la possiblitat de depurar evitantn la recàrrega amb l'opció de --no-reload del servidor de desenvolupament.
Una vegada ja tenim l'aplicació creada i depurada passam al desplegament. Pels experts de sistemes no ha de ser cap problema seguir les instruccions de les instruccions de desplegament de Django. Es pot desplegar en Apache (mod_python o mod_wsgi), damunt ngnix, lighthttp, Cherokee, ... En general no es tant cosa del servidor com de triar una tecnologia considerant el nostre entorn d'execució.
Perquè pensau que Django està pensat per ser escalable per amunt i per avall. Segons les restriccions del nostre entorn de producció ens convindrà elegir una tecnologia o una altra. Decidir si ens convé tenir un sols servidor http o separam l'execució de l'aplicació del servidor de continguts, quin tipus de caché farem servir, etc. etc.
Tot és molt flexible, però aquesta flexibilitat fa que ens tenguem que fer preguntes, Django no decideix per nosaltres com s'ha d'instal·lar. Fa recomanacions però en general s'adapta al que hi ha.
Si un disposa d'uns tècnics de sistemes com els que jo tenc la sort de fer feina, aquesta flexibilitat és fantàstica, segons l'aplicació decideixen la tecnologia que es fa servir, la caché, les instàncies que s'aixecaran o com es serveix el contingut estàtic. Si un s'ho ha de fer tot i no disposa d'un servidor propi (o al manco d'un servidor virtual) el desplegament vindrà marcat pel que ens deixi el nostre ISP.
Posar una configuració? Doncs no, dependrà de cada aplicació i de cada entorn. Sols un parell de recomanacions:
wsgi funciona molt bé
Si podeu separau el servidor d'aplicacions Django del servidor de contingut estàtic.
Amb un poc més de pressupost es pot tenir un servidor dedicat o virtual configurat i podrem treure tot el suc a la nostra aplicació.
0 comentaris,
0 trackbacks (URL)
Automatic translations of this post by Apertium [Less]
Posted
16 days
ago
Following yesterday's post another hotly requested topic was testing in Django. Today I wanted to give a simple overview on how to get started writing tests for your Django applications. Since Django 1.1, Django has automatically provided a
... [More]
tests.py file when you create a new application, that's where we'll start.
For me the first thing I want to test with my applications is, "Do the views work?". This makes sense, the views are what the user sees, they need to at least be in a working state (200 OK response) before anything else can happen (business logic). So the most basic thing you can do to start testing is something like this:
from django.tests import TestCase
class MyTests(TestCase):
def test_views(self):
response = self.client.get("/my/url/")
self.assertEqual(response.status_code, 200)
By just making sure you run this code before you commit something you've already eliminated a bunch of errors, syntax errors in your URLs or views, typos, forgotten imports, etc. The next thing I like to test is making sure that all the branches of my code are covered, the most common place my views have branches is in views that handle forms, one branch for GET and one for POST. So I'll write a test like this:
from django.tests import TestCase
class MyTests(TestCase):
def test_forms(self):
response = self.client.get("/my/form/")
self.assertEqual(response.status_code, 200)
response = self.client.post("/my/form/", {"data": "value"})
self.assertEqual(response.status_code, 302) # Redirect on form success
response = self.client.post("/my/form/", {})
self.assertEqual(response.status_code, 200) # we get our page back with an error
Now I've tested both the GET and POST conditions on this view, as well the form is valid and form is invalid cases. With this strategy you can have a good base set of tests for any application with not a lot of work. The next step is setting up tests for your business logic. These are a little more complicated, you need to make sure models are created and edited in the right cases, emails are sent in the right places, etc. Django's testing documentation is a great place to read more on writing tests for your applications. [Less]