Live data from Hacker News

Django plugins you shouldn't start without

blog.hndigest.com

81–89 of 89 posts

Re: Django plugins you shouldn't start without

#81
I respectfully disagree with OP.

I would say that django_extensions is handy enough to have it included (mainly for the sake of shell_plus and runserver_plus), South is invaluable (although migrations are going into the core in near future[0]), but others—it very much depends on the project.

sekizai is one I've never heard about before. Judging from the first sight, I think it can make templating more flexible, but at the cost of increased complexity.

Earlier I thought that reversion is great to have by default, and I was adding it to every project. Then, as I recall, mysterious errors started popping up one day in one project after Django update. They turned out to have something to do with reversion compatibility. I looked into it and found that we had no use cases for reversion—I could simply throw it away without any consequences, which I promptly did.

I've used grappelli for a while, but in the end I found its UI less usable than native Django admin UI. (Recently I stumbled across http://djangosuit.com/ — this one does seem more functional, although I've never used it in my projects yet.)

[0] https://docs.djangoproject.com/en/dev/topics/migrations/

Re: Django plugins you shouldn't start without

#82

As someone who is just starting to dive into Django and Python in general I have to admit being confused by benchmark after benchmark that puts Python near to the bottom of the performance curve when compared to other technologies (Go being one that jumps out at me). I have to admit that part of me is wondering if I am making the right decision in investing time, effort and money getting up to speed on Python/Django…

I'm certainly no expert, but thought I'd chime in as I have been wrestling with the same issue. I enjoy web development and have done projects with Java with JSP's, a few smaller projects with Rails, a large Django project, and now am playing with Rails again. Your performance concerns (and I believe the other comments have touched on this) likely don't matter for most real world sites, and then, even if you get big,…

I would also suggest checking out the TwoScoops book, very well written best practices. Barring that, just using the template defined in the book to start new projects will get you on the right path to great project organization.

     django-admin.py startproject --template=https://github.com/twoscoops/django-twoscoops-project/zipball/master --extension=py,rst,html PROJECT_NAME

Re: Django plugins you shouldn't start without

#83
post #75

Earlier quoted context omitted.

> The request object is context local. The request object is a threadlocal (or, if greenlet is installed, a greenlet-local). Which is exactly the same as a global variable in a single-threaded program.

> The request object is a threadlocal (or, if greenlet is installed, a greenlet-local). request objects aren't stored in python's thread local storage. If they were, a thread re-use will leak context local. Werkzeug uses the thread/greenlet id as key in its storage and cleans up when the request completes. > Which is exactly the same as a global variable in a single-threaded program. In a single threaded server, the…

> request objects aren't stored in python's thread local storage. If they were, a thread re-use will leak context local.

No more so than werkzeug since it works the same way.

> Werkzeug uses the thread/greenlet id as key in its storage

Which is exactly how Python's threadlocals work.

> and cleans up when the request completes.

You do realize that nothing stops you from "cleaning up" your threadlocal "when the request completes" right? Yes werkzeug's locals and localmanagers conveniently provide hooks for that cleanup, but that's what it is: convenient. The primary purpose and the one explicitly mentioned in werkzeug's own documentation is having a single system for both greenlets and threads (the stdlib's threading.local obviously doesn't work with greenlets, just as werkzeug's locals don't work with non-greenlet coroutines)

> In a single threaded server, the context locals won't leak from one request to another. If they were global, they would.

Not if you cleaned them up after the request has executed. And apparently that's all you need to make a global variable not-global-after-all.

> I don't see how request object has anything to do with global variables.

It's an object available from all scopes. That's pretty much the definition of a global variable.

Re: Django plugins you shouldn't start without

#84
isn't the South functionality there out of the box in rails? I've only ever written one rails app in my life, and I now use (non-Django) python all the time, but needing a 3rd party library to handle db migrations sounds like madness, and makes me want to re-learn ruby rather than use Django.

Re: Django plugins you shouldn't start without

#85
post #44

Earlier quoted context omitted.

{{ block.super }} does the trick for me.

That only works with templates that extend a base template, not ones included inline.

This is true. But I've never felt that the need for something like sekizai in practice based on how I structure templates.

Re: Django plugins you shouldn't start without

#86
post #62

Earlier quoted context omitted.

> How about in Round 7 that Python surpasses Nodejs I can't find what you're referring to. Node was still infront of Django in the JSON benchmark. Django (until 1.6) hasn't had connection pooling for the database either. Updating those benchmarks with pooling should make significant differences. But my point was that the framework itself can have a huge impact. Database and other I/O does have overhead, and it may ev…

You are comparing a Web framework (Django) with a language+network runtime (Nodejs). The Nodejs web framework is Express, behind Bottle and Falcon.

Oh, I see. But "python" wasn't represented, which confused me. There is still a large discrepancy between the different frameworks in the javascript and python set.

But the original point was that database and I/O make the largest difference. After restricting the set of languages and frameworks to python and javascript, I can only (now) agree.

109,000-5700 rps for JSON requests, and 4800-117 rps for multiple database queries. Quite significant.

Re: Django plugins you shouldn't start without

#87
post #62

Earlier quoted context omitted.

You are comparing a Web framework (Django) with a language+network runtime (Nodejs). The Nodejs web framework is Express, behind Bottle and Falcon.

Oh, I see. But "python" wasn't represented, which confused me. There is still a large discrepancy between the different frameworks in the javascript and python set. But the original point was that database and I/O make the largest difference. After restricting the set of languages and frameworks to python and javascript, I can only (now) agree. 109,000-5700 rps for JSON requests, and 4800-117 rps for multiple databas…

I agree with ya. There's big room for db connection improvement in Django.

Re: Django plugins you shouldn't start without

#88
post #75

Earlier quoted context omitted.

> The request object is a threadlocal (or, if greenlet is installed, a greenlet-local). request objects aren't stored in python's thread local storage. If they were, a thread re-use will leak context local. Werkzeug uses the thread/greenlet id as key in its storage and cleans up when the request completes. > Which is exactly the same as a global variable in a single-threaded program. In a single threaded server, the…

> request objects aren't stored in python's thread local storage. If they were, a thread re-use will leak context local. No more so than werkzeug since it works the same way. > Werkzeug uses the thread/greenlet id as key in its storage Which is exactly how Python's threadlocals work. > and cleans up when the request completes. You do realize that nothing stops you from "cleaning up" your threadlocal "when the request…

> No more so than werkzeug since it works the same way.

I don't know if you are being intentionally dense. Werkzeug doesn't work the same way. Thread locals restrict themselves to thread lifecycle; werkzeug locals restrict themselves to request lifecycle. They are 2 very different things.

> Which is exactly how Python's threadlocals work.

Except for different lifecycle.

> You do realize that nothing stops you from "cleaning up" your threadlocal "when the request completes" right?

That "cleaning up" makes it request local, not thread local. They are global for the duration of the request and one request scope is separate from another request which makes them request local(how it is done is immaterial). Spare me the definition of global. There is no point in continuing this discussion any further since I don't seem to have any epiphany from your insights; and doesn't seem like you are going to have one either.

Re: Django plugins you shouldn't start without

#89
post #61

Earlier quoted context omitted.

> "In almost every case where we allowed non-local effects, it has bitten us. Badly." But the request object in flask is not global. If the guarantees break(request locals leak to other requests), it will be a problem. I never have had a request local leak in flask. On the other hand, I have ran into cases where I need the request object in django signals. A simple task of getting the full uri requires either a reque…

Leakage between requests is only one of the problems with globals. There's also poor testability, inability to re-use functions that reference the request internally, inability to statically analyze dependencies (less of an issue in Python, since the lack of types makes it hard to analyze them anyway), additional context that the developer must keep in his head, and inability to cross-reference parameters & call-site…

> There's also poor testability, inability to re-use functions that reference the request internally, inability to statically analyze dependencies (less of an issue in Python, since the lack of types makes it hard to analyze them anyway), additional context that the developer must keep in his head, and inability to cross-reference parameters & call-sites and identify where a given variable is coming from in code browsers or debuggers.

I don't know. Most of them seem like a non issue to me. Shouldn't the api cover that testability(of request)? At least, it does in Flask. Re-using a function which uses request won't be any different from re-using a function which uses datetime. I do get your point about difficulty of analyzing Python owing to dynamic typing and monkey patching, but I couldn't connect it to context local. As for cross referencing, you just treat request as you treat datetime.

> Singletons are no better - if you dress it up as RequestManager.get_current_request(), it's just as bad. If you don't understand why something is a bad idea, complying with the letter of the law without complying with the spirit doesn't really get you much.

I won't do that. That is just a tongue in cheek comment to appease "death to globals" police.

> Now I want my programs to do as little as possible and have access to as little as possible.

I don't disagree with that but assuming that the request object is available for the request lifecycle is pretty reasonable.

> Usually I end up pulling out the values I want inside the view function and calling any helpers using only those values, so I don't pass the request around anyway.

You don't pass around request in a general workflow(why would you?). But consider this https://github.com/tschellenbach/Django-facebook. This does a post save signal when a new user registers. I need to send a welcome mail to the user asking him to activate his account. I need request.build_absolute_uri to construct the uri, and guess what, I don't have request in the callback and I don't have a way to obtain it. Now there can be other ways I can solve it - configure sites and generate url using sites; simply have the base url in settings and construct the url by doing a urljoin; may be in some alternate universe, django's reverse generates external url. But the thing is, I have needed access to request object on more than a few occasions. Granted if the callback passed me the request object, it won't have been an issue but it doesn't and I had to resort to thread local middleware to save the request object.

> A fourth was that I worked a bunch with both systems and found that adding a parameter to each function along a call path is easy

The issue is apis which you haven't wrote. I can always change the packages myself, but I don't want to sync up with upstream for something I see as a small change.

Post reply on HN