I'm currently playing around with Dave Winer's OPML Editor, which he now uses for his blog. It looks quite fun and has a lot of features. My OPML Blog has collected some of the insights I've gained from it. I certainly won't switch over just like that - that would be Quark, which is not necessarily my target software. But it's fun to play with something completely different again.
Unfortunately, the OPML Editor has inherited some of the ailments of Radio Userland and Frontier, especially the handling of umlauts is not really smooth (I would like to have consistent UTF-8 support finally) and the runtime behavior is better than in Radio, but it still occasionally consumes too much CPU.
The concept of rendered outlines does have a certain charm. However, many parts of the rendering are not really accessible to normal users - you can edit the ancient table layout and make something else out of it, but the OPMLs are implemented with the internal OPML renderer and the HTML fragments are not so easy to change - and thus, for example, changing the language is quite cumbersome, as is the complete removal of layout tables.
More will certainly appear on the OPML blog from time to time, here I will write at most a few conclusions.
The NY Times asks why Bill Gates wants 3,000 new patents and finds a massive siege of the patent office with mountains of software patents, which are often just trivial patents (like the cited patent for adding/removing spaces in documents). The commentator makes a demand in the comment (after considering whether Microsoft should not simply have all the patents it already has revoked):
Perhaps that is going too far. Certainly, we should go through the lot and reinstate the occasional invention embodied in hardware. But patent protection for software? No. Not for Microsoft, nor for anyone else.
And this from the country that has had software patents for a long time and that is repeatedly cited by software patent proponents in the EU as a reason for a necessary worldwide harmonization.
No, software patents are also not popular there and not really useful. Dan Bricklin, known to some as the father of VisiCalc, also thinks so:
Mr. Bricklin, who has started several software companies and defensively acquired a few software patents along the way, says he, too, would cheer the abolition of software patents, which he sees as the bane of small software companies. "The number of patents you can run into with a small product is immense," he said. As for Microsoft's aggressive accumulation in recent years, he asked, "Isn't Microsoft the poster child of success without software patents?"
And why is Microsoft doing this now? The manager responsible gives a reason, as only a business administrator could come up with, it's that stupid:
"We realized we were underpatenting," Mr. Smith explained. The company had seen studies showing that other information technology companies filed about two patents for every $1 million spent on research and development. If Microsoft was spending $6 billion to $7.5 billion annually on its R&D, it would need to file at least 3,000 applications to keep up with the Joneses.
Ok, the idea of patent applications alone being oriented towards numbers from the industry is absurd, but how stupid do you have to be to draw a connection between the number of patents and revenue in the field of research and development?
The NY Times also draws a parallel to the pharmaceutical industry, which - at least according to its own statements - is happy to get a patent for a drug when it invests 20 million in research (which is already critical enough, as can be seen in the fight against AIDS in Africa).
And the fallout is also well summarized in the NY Times:
Last year at a public briefing, Kevin R. Johnson, Microsoft's group vice president for worldwide sales, spoke pointedly of "intellectual property risk" that corporate customers should take into account when comparing software vendors. On the one side, Microsoft has an overflowing war chest and bulging patent portfolio, ready to fight - or cross-license with - any plaintiff who accuses it of patent infringement. On the other are the open-source developers, without war chest, without patents of their own to use as bargaining chips and without the financial means to indemnify their customers.
The question of what Jefferson (the founder of the US patent system) would say about what is now being patented is quite justified. In his sense - which was actually more about protecting real inventive genius from exploitation by corporations - this is definitely not the case.
Münte on the Roll: Linkspartei "politically and legally absurd". I have the impression, however, that he would help the SPD more by giving them a program that appeals to ordinary citizens again, instead of simply stirring up fear of the left and spreading defamation (sorry, but the combination of PDS and WASG in the open list may be strange, but legally flawless - claiming otherwise is simply defamation).
If the SPD cannot achieve more in the election campaign than just to blow the horn of the Union parties against the alleged danger from the left, the SPD will simply put itself out of the political game - with such nonsense, you don't win an election. If the SPD is nothing more than a union with a red tie, it can stay away from me ...
Dieser Artikel ist mal wieder in Englisch, da er auch für die Leute auf #django interessant sein könnte. This posting will show how to build a very simple filesystem browser with Django. This filesystem browser behaves mostly like a static webserver that allows directory traversal. The only speciality is that you can use the Django admin to define filesystems that are mounted into the namespace of the Django server. This is just to demonstrate how a Django application can make use of different data sources besides the database, it's not really meant to serve static content (although with added authentication it could come in quite handy for restricted static content!).
Even though the application makes very simple security checks on passed in filenames, you shouldn't run this on a public server - I didn't do any security tests and there might be buttloads of bad things in there that might expose your private data to the world. You have been warned. We start as usual by creating the filesystems application with the django-admin.py startapp filesystems command. Just do it like you did with your polls application in the first tutorial. Just as an orientation, this is how the myproject directory does look like on my development machine:
.
|-- apps
| |-- filesystems
| | |-- models
| | |-- urls
| | `-- views
| `-- polls
| |-- models
| |-- urls
| `-- views
|-- public_html
| `-- admin_media
| |-- css
| |-- img
| | `-- admin
| `-- js
| `-- admin
|-- settings
| `-- urls
`-- templates
`-- filesystems
After creating the infrastructure, we start by building the model. The model for the filesystems is very simple - just a name for the filesystem and a path where the files are actually stored. So here it is, the model:
from django.core import meta
class Filesystem(meta.Model):
fields = (
meta.CharField('name', 'Name', maxlength=64),
meta.CharField('path', 'Path', maxlength=200),
)
def repr(self):
return self.name
def get_absolute_url(self):
return '/files/%s/' % self.name
def isdir(self, path):
import os
p = os.path.realpath(os.path.join(self.path, path))
if not p.startswith(self.path): raise ValueError(path)
return os.path.isdir(p)
def files(self, path=''):
import os
import mimetypes
p = os.path.realpath(os.path.join(self.path, path))
if not p.startswith(self.path): raise ValueError(path)
l = os.listdir(p)
if path: l.insert(0, '..')
return [(f, os.path.isdir(os.path.join(p, f)),
mimetypes.guess_type(f)[0] or 'application/octetstream')
for f in l]
def file(self, path):
import os
import mimetypes
p = os.path.realpath(os.path.join(self.path, path))
if p.startswith(self.path):
(t, e) = mimetypes.guess_type(p)
return (p, t or 'application/octetstream')
else: raise ValueError(path)
admin = meta.Admin(
fields = (
(None, {'fields': ('name', 'path')}),
),
list_display = ('name', 'path'),
search_fields = ('name', 'path'),
ordering = ['name'],
)
As you can see, the model and the admin is rather boring. What is interesting, though, are the additional methods isdir , files and file . isdir just checks wether a given path below the filesystem is a directory or not. files returns the files of the given path below the filesystems base path and file returns the real pathname and the mimetype of a given file below the filesystems base path. All three methods check for validity of the passed in path - if the resulting path isn't below the filesystems base path, a ValueError is thrown. This is to make sure that nobody uses .. in the path name to break out of the defined filesystem area. So the model includes special methods you can use to access the filesystems content itself, without caring for how to do that in your views. It's job of the model to know about such stuff.
The next part of your little filesystem browser will be the URL configuration. It's rather simple, it consists of the line in settings/urls/main.py and the myproject.apps.filesystems.urls.filesystems module. Fist the line in the main urls module:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^files/', include('myproject.apps.filesystems.urls.filesystems')),
)
Next the filesystems own urls module:
from django.conf.urls.defaults import *
urlpatterns = patterns('myproject.apps.filesystems.views.filesystems',
(r'^$', 'index'),
(r'^(?P<filesystem_name>.*?)/(?P<path>.*)$', 'directory'),
)
You can now add the application to the main settings file so you don't forget to do that later on. Just look for the INSTALLED_APPS setting and add the filebrowser:
INSTALLED_APPS = (
'myproject.apps.polls',
'myproject.apps.filesystems'
)
One part is still missing: the views. This module defines the externally reachable methods we defined in the urlmapper. So we need two methods, index and directory . The second one actually doesn't work only with directories - if it get's passed a file, it just presents the contents of that file with the right mimetype. The view makes use of the methods defined in the model to access actual filesystem contents. Here is the source for the views module:
from django.core import template_loader
from django.core.extensions import DjangoContext as Context
from django.core.exceptions import Http404
from django.models.filesystems import filesystems
from django.utils.httpwrappers import HttpResponse
def index(request):
fslist = filesystems.getlist(orderby=['name'])
t = templateloader.gettemplate('filesystems/index')
c = Context(request, {
'fslist': fslist,
})
return HttpResponse(t.render(c))
def directory(request, filesystem_name, path):
import os
try:
fs = filesystems.getobject(name exact=filesystemname)
if fs.isdir(path):
files = fs.files(path)
tpl = templateloader.gettemplate('filesystems/directory')
c = Context(request, {
'dlist': [f for (f, d, t) in files if d],
'flist': [{'name':f, 'type':t} for (f, d, t) in files if not d],
'path': path,
'fs': fs,
})
return HttpResponse(tpl.render(c))
else:
(f, mimetype) = fs.file(path)
return HttpResponse(open(f).read(), mimetype=mimetype)
except ValueError: raise Http404
except filesystems.FilesystemDoesNotExist: raise Http404
except IOError: raise Http404
See how the elements of the directory pattern are passed in as parameters to the directory method - the filesystem name is used to find the right filesystem and the path is used to access content below that filesystems base path. Mimetypes are discovered using the mimetypes module from the python distribution, btw.
The last part of our little tutorial are the templates. We need two templates - one for the index of the defined filesystems and one for the content of some path below some filesystem. We don't need a template for the files content - file content is delivered raw. So first the main index template:
{% if fslist %}
<h1>defined filesystems</h1> <ul> {% for fs in fslist %}
<li><a href="{{ fs.get_absolute_url }}">{{ fs.name }}</a></li> {% endfor %}
</ul> {% else %}
<p>Sorry, no filesystems have been defined.</p> {% endif %}
The other template is the directory template that shows contents of a path below the filesystems base path:
{% if dlist or flist %}
<h1>Files in //{{ fs.name }}/{{ path }}</h1> <ul> {% for d in dlist %}
<li> <a href="{{ fs.getabsoluteurl }}{{ path }}{{ d }}/" >{{ d }}</a> </li> {% endfor %}
{% for f in flist %}
<li> <a href="{{ fs.getabsoluteurl }}{{ path }}{{ f.name }}" >{{ f.name }}</a> ({{ f.type }})</li> {% endfor %}
</ul> {% endif %}
Both templates need to be stored somewhere in your TEMPLATE PATH. I have set up a path in the TEMPLATE PATH with the name of the application: filesystems . In there I stored the files as index.html and directory.html . Of course you normally would build a base template for the site and extend that in your normal templates. And you would add a 404.html to handle 404 errors. But that's left as an exercise to the reader.After you start up your development server for your admin (don't forget to set DJANGO SETTINGS MODULE accordingly!) you can add a filesystem to your database (you did do django-admin.py install filesystems sometime in between? No? Do it now, before you start your server). Now stop the admin server, change your DJANGO SETTINGS MODULE and start the main settings server. Now you can surf to http://localhost:8000/files/(at least if you did set up your URLs and server like I do) and browse the files in your filesystem. That's it. Wasn't very complicated, right? Django is really simple to use