Hacker News new | past | comments | ask | show | jobs | submit login
Django Newbie Mistakes (djangoproject.com)
431 points by tosh on June 28, 2018 | hide | past | favorite | 221 comments



One of the things that makes me sad is there is no project even remotely close comparable to Django for say Golang or Scala.

I love the fact that you get an admin interface out of the box. And tons of documentation. The views/template stuff is a bit dated since everyone started moving to frontend/backend services and SPAs but we still have DRF which is incredible in the amount you get for "free".

I've had the "pleasure" of working with other large projects built on flask and ever time it gets to a certain size I wonder why we didn't just use Django. There is stuff you don't realize you need until some enterprise customer requires it for your product to even be considered. Auditing, session retries/timeouts, etc. With flask you can just add another library but it isn't as connected as Django is. And that matters a lot when you get bigger because it affects discussions about what the right way to do things is. You generally have discussions about what is the right Django way vs what is the right way in general.


> I've had the "pleasure" of working with other large projects built on flask and ever time it gets to a certain size I wonder why we didn't just use Django.

Actually, I've had the exact opposite experience. I like using Django for small and mid-sized projects, because with Flask I have to spend time adding all these extra libraries for universally required functionality on a quick app whereas, with Django it's plug and go.

However, the larger the project gets, the more I like Flask since I have near total control and understanding of the app. There's no digging into Django internals to make some obscure customization.

Then again, it's been several years since I last used Django, so it may have changed for the better here.


For what it’s worth, on a Django codebase of 180k lines, 100k lines of templates, 1000 URLs, 380 “apps”, 350 models, we have a nice coherent structure across the whole codebase that makes us really productive.

I haven’t seen a Flask code bass do this anywhere near as well. They all seem to end up becoming very different and tricky to onboard new devs onto because they are so custom.

Django hides some complexity, but we haven’t found many pets we can’t effectively customise, and the architecture at scale is great, something I haven’t seen in many other places.


> I haven’t seen a Flask code bass do this anywhere near as well. They all seem to end up becoming very different and tricky to onboard new devs onto because they are so custom.

While some Flask web applications may use different file organization schemes, any large app will use blueprints. Blueprints are fairly standardized and easy to understand. I personally find Flask blueprints easier to follow than Django apps, but they're pretty similar.


Do you mind explaining what that structure is? I always find the standard Django structure of everything is an "app" difficult to navigate once the codebase gets larger.


As much as I'd rather not plug my own talk, it's probably going to give you more information than I could ever get in a reply here.

https://thread.engineering/scaling-django-codebases-pycon-uk...


What does that Django project do?


https://www.thread.com/

Curated ecommerce, a CRM like system for stylist, order management, fulfilment and distribution.


Similar experience for me. Django is pretty thick with quite a bit of (confusing, to me) magic. Flask comes without very basic components that are required for pretty much any website (user accounts, db access, etc).


Between Django and Flask, Pyramid is often forgotten. It seems like the only one of the three that has been genuinely designed to be extended (vs. Flask's approach of "here you have a magic-global variable (that's magically working like a stack of dicts), go put some stuff into it"); a good example would be renderers. In Django it's still kinda awkward to use other/multiple templating engines; Flask doesn't really help. Pyramid on the other hand has a simple and extensible interface to support multiple templates and other renderers ( https://docs.pylonsproject.org/projects/pyramid/en/latest/na... ). This is a common theme with Pyramid. Another is avoiding global state; they're quite successful at that (vs. "I declare my entire app/blueprint within a function"-Flask and "I don't know how this works, it's just like magic. I go to my model class and, BAM, suddenly I'm connected to some database"-Django).

(Other examples where the other two's solution feel rather lackluster to me include middleware vs. view derivers, view predicates, the routing system and the security area)


I've been meaning to look into Pyramid, it does sound like it avoids some of the worst of both Flask and Django.

Any areas that Pyramid doesn't do well at?


It has nothing like the django admin and no forms handling is built into it. Creating a project from scratch is a bit cumbersome (like flask), but good cookiecutters exist (e.g. the pyramid-sqlalchemy one).


Wow, Pyramid even seems to pitch itself as the "Goldilocks Solution"! OK, will give it a try.


Maybe it's because I'm used to Rails, but there is really little magic in Django. One is even free to structure the code as one likes. Almost no mandatory directory structure. It's a beefier Flask but still straightforward. If I may come up with a criticism, there are too many complications that slow down development compared to Rails.


Agreed. Also, unless django has changed peaking under the hood is a nightmare. Forms and the ORM (and really the whole framework) is giant ball of mud.


Forms are a nightmare to work with. It's a component in Django I systematically avoid, even when using actual forms.

Nowadays I use DRF for everything though. Serializers > Forms. And React > Templates.

As for the ORM, I long for a world where the ORM is replaceable by SQLAlchemy. Django's ORM is nice and simple, but as soon as you want typed complex queries, SQLAlchemy is really good.


Agreed. Django Forms' hay-day was back in the Request/Response rendering of page state era of the web. They introduced the ability to bind data for validation, rendering in the Template, programmatic generation based on Model and sanitization of form input data. They still can be utilized loosey-goosey on the backend in the world of APIs. Why bother when better tooling now exists? The use-case of Forms now is the Admin side of the house where they can facilitate the CRUD of the Models.


Just wondering, what do you use instead of Forms for non-Javascript websites?


For what it's worth you can still use DRF serializers instead of forms on non-JS sites. DRF can take multipart/form-data


Personally I find Django's forms easier to work with, but maybe that's because i have spent more time with them.


Yep, forms smell of Java Struts. I was so happy to say goodbye to them when I started using Rails in 2006. Another Javism, templatetags, because they don't want we write Python in the templates. So every small customization takes x100 the time in the best tradition of early 2000 Java frameworks.


It's not changed much. Some things are a bit better (model's Meta is now documented and not considered "private") but largely I have grown to enjoy the benefits of picking the right tools (SQLAlchemy, Jinja2) and luckily Django is doing a lot better at making things pluggable and you can use Jinja2 as a first class citizen now.


> everyone started moving to frontend/backend services and SPAs

Yes, there are valid reasons for SPAs, but many web applications and most classic web sites are still better served with plain old server-generated HTML, IMO.

First, because replicating even basic functionality in JavaScript comes at a cost, namely in bytes sent, bytes to be parsed, bugs introduced, etc. Second, because most projects don’t have unlimited development resources, so developers might just slap a few libraries together without necessary optimization, customization, or testing.

Third, because the well-known experience of browsing static web pages is already pretty darn good, and what developers will find exciting, users might just find irritating. Needlessly breaking conventions is simply bad UX.

Contrary to that, I keep reading that SPAs are the “new way”, as if classic server-rendered HTML enriched with some Ajax suddenly became a deprecated, inferior technology. It really isn’t. Unless you know what you’re doing, and why you need to, the classic way is still a sane default. If in doubt, I would always prefer a solid Django site over a half-baked SPA.


This is exactly my view as well. Every time I've used Flask, I ended up regretting it, because I've invariably needed to fit something to it that would have worked out of the box with Django (or at least integrated much more easily).

I haven't found any reason to use Flask in a project, except maybe for small, ad-hoc scripts that you want to run in a single file.


And its perfectly possible to write a one file/ten loc Django app. Everything is optional. Its just there by default, because 99% of projects will need it anyway.


> its perfectly possible to write a one file/ten loc Django app

Examples: http://olifante.blogs.com/covil/2010/04/minimal-django.html https://stackoverflow.com/questions/1297873/how-do-i-write-a..., and also this interesting one: https://github.com/simonw/djng where the guy builds a microframework which uses Django.


In your last example, "the guy" is one of the people who was on the team that originally created Django, back when it was an internal tool for building a news CMS.


> One of the things that makes me sad is there is no project even remotely close comparable to Django for say Golang or Scala.

Could not agree more. This is my number one reason for not moving away from Python for web stuff.

> The views/template stuff is a bit dated since everyone started moving to frontend/backend services and SPAs

This is certainly true for customer facing products, but for internal tools I've yet to see anything that beats the speed of development for server-side rendered basic HTML pages. 80% of the pages we have in our Django application are internal facing (we don't use the admin due to it being a poor fit for particular reasons).


Personally, as a customer, the "new" way of doing it is irritating, usually somewhat broken, slow and usually unreliable.

I wouldn't be surprised if non-techies couldn't give a toss if you're using a traditional MPA with a sprinkling of ajax for the bits that really need to be responsive or a total SPA.

I'm beginning to suspect the only people who want a SPA are the programmers. Has anyone even got any proof that a SPA is better than a MPA in terms of customer satisfaction? It seems to have all originated from a technical need rather than a customer need. I still prefer doing most thing server-side and then sending snippets of html to update the bits on the page that need updating, occasionally using client-side view templates/JSON, depending on the case.


As a programmer, I absolutely hate SPA's. I've never used a good SPA, they're always slow, and behave strangely. I much prefer the traditional way. It's the same with Electron apps.

I think it's just web developers who like SPA's


Agreed, logic usually ends up scattered between the front end and the back end. You need to start using JavaScript (I much prefer Python). The Angular app I ma maintaining just now would be so much simpler if it was server side rendered, instead we have an ajax call to load contents of every dropdown....


I think with server side pages, you’re limited in how much you can mess it up, but very limited in how far you can take the experience.

With single page apps you have to do a lot more to get back to what server side pages give you, basic browser functionality, and as a result you can end up with worse experiences. However if you’ve got the development resources it can be a far better experience and enable applications that just wouldn’t be usable or even possible on server side rendered pages.


Name me a single thing you can't do in a SPA that you can't do in a MPA with a bit of Ajax?

The only thing I can conceivably think of is an offline app, but they're so rediculously niche.


I think it depends on use case, of course. Gmail, Google Slides, or Figma would be poor MPAs I’d say.


Good SPAs are fantastic. It's just a lot of people suck when implementing them.

The Serverless documentation, an SPA, blew my mind in terms of how fast and clean it is: https://serverless.com/framework/docs/


Really? Randomly clicking e.g. Providers > Azure, I see a significant loading animation (the grey lines) - likely slower than just loading a simple new page each time. (Compare e.g. https://docs.python.org/3/library/weakref.html.)

(Single Page Applications arguably have their place. I'm just really confused why you think this is a particularly good example.)


On my awful connection, serverless is as fast as HN on new pageloads, and faster than HN when navigating to cached pages.

HN is my baseline for how fast a site should be.


HN is typically how I determine no connection vs. crap connection. I could `ping` I suppose, but in these circumstances I'm in the browser having just signed in to the crap/not connecting AP.


HN is typically how I determine no connection vs. crap connection.


> "I see a significant loading animation (the grey lines) - likely slower than just loading a simple new page each time."

You can test the difference yourself by toggling JavaScript in your browser.


It takes ~2.5 seconds to load and the first ~1.5 of that won't display anything because it has to process ~600KB of JavaScript and CSS before it can render a few hundred words of text:

http://www.webpagetest.org/result/180628_AQ_c87264f303f9e72f...

The only reason that's faster as an SPA than static HTML is because they've disabled caching for static resources:

http://www.webpagetest.org/result/180628_AQ_c87264f303f9e72f...

If the site was optimized it'd perform very similarly either way since there's none of the complex logic or interactions where an SPA really starts to shine and the content is very cache-friendly.


Testing an SPA against a single pageload is absurd. You're not optimizing for a single page load (and if you are, a couple hundred milliseconds makes zero difference). You're optimizing against browsing the site.

Have you tried browsing the site...?


> Testing an SPA against a single pageload is absurd. You're not optimizing for a single page load (and if you are, a couple hundred milliseconds makes zero difference).

As a user I don't care about the developer's aesthetic preferences for tooling, only how long it takes to see the information I need. This feeds back to the question of why an SPA matters: for a rich application, there's more benefit to cancel out the runtime overhead.

For static docs, your timing is off by at least one order of magnitude: I have to wait a second or more — a LOT more on a high-latency connection where that initial page load is 15+ seconds worse[1] – and there doesn't seem to be much benefit to compensate for that. I mean, the animation is cool the first time I see it but I see it a lot because there's less information on each page so the novelty wears off pretty quickly.

Again, please note the last part of my comment: there is a place for SPAs but I'm not sure why a site this simple needs 500KB of JavaScript to deliver static documentation slower than Apache did two decades ago. I was expecting to see a selling point such as loading the content so that it was usable offline and search results were instantaneous but e.g. that nice search box (which is the one thing you couldn't have done in 1994) still takes 3+ seconds to load and render the new page on a well-peered gigabit connection.

1. http://www.webpagetest.org/result/180628_CF_db268e65de67002e...


I'm on a terrible high latency connection in Athens, Greece. The serverless SPA is one of the fastest sites I've ever visited. It's a ton faster than HN for me.

Yes the initial pageload takes time. But afterwards I can click around the site and get immediate feedback. Immediate as in native app speeds. Images and such obviously still take time to load and render but they do not block loading. There's no whitescreen while I wait for new pages to load.

So as someone with shitty internet who often browses documentation, give me hundreds of sites like this. This is significantly faster to browse around than, say, the Python or Django documentation, both of which make very little use of Javascript. I'm sorry you're not getting the same experience, I can't speak to that.

To reiterate: An SPA will bloody obviously not faster on the first pageload. The whole idea behind it is that you load more machinery upfront but you don't load it again afterwards. Depending on how good the app is, you make up for it very, very quickly. And if you have any significant JS usage on your site at all, you make up for that too.

My point, which everyone seems to have completely missed, is that well-built SPAs do exist. They don't have to feel slower to use than other apps.


When I look for an information I usually google it, then click on the first link, get what I need, and close the site.

It's especially true for a documentation website.

Even if I browse a little, it will be swift clicks on 3 to 4 pages to get to what I'm looking for. The enormous initial loading time is far from amortized.

Bottom line, if your site is just displaying text like a doc, a wiki, etc., making it an SPA is ridiculous.

Just use old school techs, and offer a zip for download.


YMMV, but when I've dabbled with what I believe are good SPAs, I've noticed what I was essentially was essentially implementing a crude primitive web-browser inside my React app. I mean, I was neck-deep trying to code page transitions, load progress indicators, history states, all this sort of stuff.

Thankfully, I'm not a frontend developer. Was just toying around here and there. Maybe it was just that I sucked at simple things.

Still, for now I believe many (not all, of course) fancy SPAs are a probably a waste of otherwise productive time. There is already a browser, and it does things well. Having something that would allow for smaller documents is a good idea, of course, and some eye candy for transitions between different documents would be neat to have, but every site doing this for themselves feels just plain wrong to me.

Exceptions - e.g. for heavily API-centered systems - apply, of course. If a webpage is one of half a dozen client applications that consume the same API, then SPA could be a sane way to do it.


All a symptom of the browser being a document-first platform that's been reused to be app-centric. I agree with you it's a bummer that these things are getting reimplemented on top of a platform that already offers them, but the way the platform offers them hasn't changed much since the 90s and hasn't kept up with what apps need.

The core issue being that you have no way of statefully going from one page to the next. State only exists within the page you're on. Hence the rise of SPAs.


Just tested it on an edge connection in the German country side:

Hacker news:

- first load: 6 seconds

- next loads: 3.5 seconds

Serverless:

- first load: 26 seconds

- next loads: 7.5 seconds


> Could not agree more. This is my number one reason for not moving away from Python for web stuff.

Why would you want to move away from something that works?


Indeed we are also looking for a framework to change our Django/python. We were looking at golang as half of our backend is in go but the lack of ORM make the choice impossibile. Gorm, xorm.. are not supporting Foreign Key...

Yes you can write your raw SQL query but that means that your backend can't support MySQL and Postgresql (one of our prerequisites for on-premise deployment).

So we are ending with phoenix. Very sad that golang doesn't provide a very good ORM.


What’s the motivation for moving away from python?


We are in python 2.7 and we need to migrate the application to python 3.0 For me it's another language to learn if we want to make good python 3 code. Python/Django/DRF is a stack with very poor performance if you are dealing a lot with JSON. We already have API points in golang with very good performance. No need to deal with nginx/CGI etc. nightmare. Conclusion was that our code in golang has a lower downtime. (Typed etc.)

The issue is on the ability to provide code compatible with MySQL and Postgresql. Without ORM you have to duplicate your queries.

So looking at a framework with ORM we are doing a benchmark of Elixir/Phoenix/Ecto. This solution could simplify our architecture a lot: websocket with room shared between server etc.

Bad point is the lack of documentation on Phoenix 1.4


The changes from Python 2.7 to 3.x are hardly so dramatic that it's like learning a new language. I'm pretty sure your performance issues can largely be addressed after proper investigation where the bottlenecks are. I do understand how nice it is to have a simpler architecture, but make sure it's worth all the work.


Well we can migrate to python 3 but this will be more investment in a stack that is more and more obsolete (Django) for SPA. Developers need also to learn the new best practices for python 3. At the end this will result in short term with python 3 code base written in python 2 style without the benefits of typing etc. Investment without benefits except keep our stack up-to-date.

Each solution for Python/Django add complexity: - async -> celery/rabbitmq - websocket -> Channels, Daphne, asgiref, channels_redis, redid.

It's quite huge to manage.


Django obselete?

Sure....


For our usage that's my point of view. When you need to manage ws & asynchronous task, you are just ending stacking technologies to make Django enter in 2018 (remember tornado?). I would say that the framework didn't followed technology evolution and so our new requirements

For old good stuff is still a good framework. It really depends on your usage.


I love Elixir (more so than golang), so I would sincerely recommend using it. Erlang concurrency story is lightyears ahead of Python3 asyncio (despite being older by maybe 20 years). And OTP has no equivalent anywhere.

But if you are migrating just to avoid spending a couple of days learning and migrating to Python 3 based on reading too much FUD I'm very saddened. Migrating from Python 2 to Python 3 is not much harder to handle than a Django migration. Though of course it depends on your codebase, but compared to moving to Elixir/Phoenix/Ecto it's a peace of cake.

Move to Elixir/Phoenix/Ecto because it fits your needs better than Python, be proud of it even. But please, learning Python 3 to write good Python 3 code coming from Python 2.7 is very easy, nothing like switching to a completely different paradigm...


The goal will be to take benefits of the elixir/OTP platform and the concurrency assets. Today we have a lot of asynchronous/background task distributed with rabbitMQ. If our investment provide better stack and simplify the architecture , this could be a better ROI than keep the current stack up-to-date.


Normally people use something like uWSGI to host python apps behind Nginx - in any case, it’s something you figure out once and pretty much never deal with again. So it shouldn’t be an ongoing nightmare.

While I didn’t downvote you, I suspect the people that did have done so because it sounds like you’re making quite a naive mistake in blaming the tool for your issues. Changing language is almost certainly the wrong thing to do, period. You should profile your existing code and figure out where the real issues are. If you don’t know how to do that effectively, no amount of rewriting from scratch in a new language will save you.

Sounds like you really care about the ORM (though if you’re using the Django one, it’s pretty basic). Python has hands down the best ORM (SQLAchemy), so if that’s such a priority, then why not start there?


Well I don't blame python. It's just that the stack python/Django/DRF is not more efficient for us now as our requirements changed spa/ws/asynchronous tasks. Investing in this stack is more and more difficult as our requirements don't fit. But yes we can also check flask/sqlalchemy . I'm just afraid of the stuff needed for ws/asynchronous task. This will not simplify our architecture.


Dude moving to Python3 is easy. It is an order of magnitude easier than moving over to a new language.


No new stuff on your resume though....


You might want to try using Pypy as your interpreter as a potential drop-in fix.


Python 2.7 and 3 are hardly as different as you think. Migrating is a total breeze


I'm surprised you are worried about JSON performance and not ORM performance. It seems like if you really needed better serialization/deserialization you could just call a c module from python.


Good point. Lost of performance in the query is acceptable a as we gain support of MySQL & Postgresql. Lost of performance in JSON serialisation is more difficult to accept.


Why wouldn't you be able to support both MySQL and PostgreSQL without an ORM?


This implies to create 2 queries each time you want to hit the database. One query for PostgreSQL and one query for MySQL. This is something we can't afford. Do you have some good tips to manage this ? To be honest the ORM is required only to support multiple database.


Scala / Play Framework does in fact have an out of the box solution for this: https://www.playframework.com/documentation/1.2.2/crud

Edit: This was removed in Play Framework 2


They dropped that in Play 2.x, as far as I can tell.


Looks like you're right. Comment withdrawn.


Yep. I just joined a company and what I could do in two months blew their minds. A lot of which was thanks to all the freebies by Django.


> no project even remotely close comparable to Django for say Golang

I've used Django, flask and Golang quite a bit. One thing the Golang community seems to do a good job with is building things around the http.HandlerFunc interface which in turn leads to many of the subcomponents from other OS projects fit well together through chaining handlers. For example check out the Gorilla toolkit.

Django hides much of it away from you and the magic can be annoying at times. Flask seems to have failed on being both modular and nice to use for bigger projects (this is likely because WSGI isn't conducive to that sort of chaining).

Basically, with go I feel like I get Flask level lightness and visibility with actual modularity -- "easy to add batteries" if you will.

But I generally agree, Django is awesome. And the Django Admin is a whole beast of its own that is very unique and has been very useful for small staff alliances and management operations.


what made me sad when trying Django was that it felt not remotely close to RubyOnRails. Did I miss some ORM magic, scaffolds, generators, migrations? Did they add those in the meantime?

Love the admin interface and logic though, and python>ruby IMHO


What was the last version of Django that you used? There's build-in schema migrations since 1.7 version. Not sure what you mean by ORM magic.


I've used neither, but Qor looks like it's of the same family: https://github.com/qor/qor


Play! framework for Scala was pretty close to Django back in 2012, has something changed? Did they stop developing Play! ?


I've worked with django for a considerable amount of time now (~9 years), and I have found the documentation a joy to work with. The documentation generally covers each piece of functionality, and the source code is rich with documentation.

When it comes to django itself, there are nuances, and yep, some of them probably can be smoothed over for developer experience, but developers must have knowledge over their tools.

If you feel like django is getting in your way, take a step back. Maybe you can remove some of the abstractions it provides and do it yourself? Maybe look at the source code? If the magic is no longer working, it's time to realize that it isn't magic to begin with, but possibly a lack of understanding.


Usually when people complain about the magic in Django it means that they're trying to work with things that are complete antipatterns. Django usually has one, really good, solid way to do each task and going against the grain is always going to hurt.


To add to this, when you want to go against the grain, you can quite easily, at the core, it's mapping HTTP requests to python functions. Outside of middleware, it's trivial to strip all unnecessary additions.


> and I have found the documentation a joy to work with.

> Maybe look at the source code?

My co-workers sometimes think I'm a magic supergenius with how easily I've been able to answer some of their Django questions. It always comes down to one of those two things: A vague memory of something I'd seen in the docs just scrolling through it in the past, or having seen the same problem they have now and used pdb to step through Django code to learn how parts of it work.


When I started with django, the development server was a nuisance due to behaving totally different from real servers. That was where documentation at that time didn't help too much.


Django’s documentation is still the best I have worked with so far of any software project I came across to date. It not only explains, it educates.


I find it some of the hardest documentation (close to AWS) to understand the best way to do something. I think it's great if you know what you're doing or you have a rough idea of what to do but need more information, but for someone new to the framework it makes me want to paper cut the webs of my fingers and bath my hands in vinegar because it would be less painful.


This is the first time I have ever heard anyone talk ill of the django docs. I've been using django for at least 8 years now, and I had only been using python for a year or two at that point. The tutorial really brings you up to speed on all the basic concepts, and everything has a reference with examples. What projects do you think have better documentation?

Now that I really think about it, one annoyance I have with the django docs, is that they don't show you the import path for the modules used in examples. Though it's usually just 30 seconds of searching to find it.


I agree. The tutorial is incredibly simplistic with a "go play" ending. Then the actual documentation assumes you have a pretty good knowledge of how everything works. There is no middle step without utilizing 3rd party docs.


There are also lengthy guides on each part ORM, Templates, etc.


The problem is they quite frankly suck.

The official ones are incredibly dry and not approachable by someone wanting to get started and do anything meaningful. I've helped people learn Django and the official docs/guides are the last on the list of recommendations. there are so many better resources to look at first. I've told people to skip the polls app and go through Django girls tutorial. The polls app is a waste of time.


May be the django book might be the approach you are looking for...

https://djangobook.com/the-django-book/


I can relate. Beyond the very basics, there's a lot of 'what' but not so much 'how', especially when it comes to combining pieces. Often when I have a hard time to achieve something, I don't know if it needs to be that hard or I'm just trying the wrong way. The code doesn't help much with that, because without a lot of experience, it's a maze. Everything is connected to everything, due to the nature of the framework. Either you need to understand it all, or you end up fighting it. I really want to like Django, but every time it's the same story. Nowadays I prefer frameworks and specialized libraries that are much lighter. Even if the documentation is more limited, I also need significantly less of it. Perhaps I'm doing more work than strictly necessary, but at least I feel in control. I'd much rather go slower and see where I'm going than quickly down a road that ultimately turns out to be a dead end. Django is reasonable good for beginners and great for experts. Being neither, it frustrates me.


Do you have any specific examples? I'm sure the Django Project would be keen on improving the docs if they know why they're bad


I used to be a Perl dev for years, and tried a couple of Perl frameworks. I switched to Python because the docs were so much easier to get started with.

There are a lot of concepts to understand with a framework so my guess is that's actually your problem, but as far as documentation goes, Django's is pretty good.


How the fuck was any of Pythons docs better than Perl’s? ??????????

Docs, error messages etc are WAY superior in Perl. Idiot.


Django's docs were better than Catalysts (I would agree with you that python's docs aren't great).

Catalyst being Perl had more than one way to do everything, to the point that i couldn't actually work out what the framework was other than the URL router. Django had a far more sane approach which would seem to be needed if its your first time venturing into a web framework.


Could we please keep the discussion factual instead of resorting to name calling?


Not trying to sound overly-pedantic, but have you tried reading them? Not skimming them. Reading them start to finish. One line at a time, in order.

Try it. You'll understand what we mean when we say they're good.


Have you seen GCP's docs? They're far worse than AWS'.


I vastly prefer Flask's documentation (http://flask.pocoo.org/docs/). It explains everything from a perspective of what your use case would be, and they've gone above and beyond in covering use cases that might otherwise have been deemed outside their scope.


I really like flask's documentation, too. But somehow the explanation of blueprints didn't work for me, even after reading it several times.


Great post, though this bit stuck out for me:

   current_zip = meta.IntegerField(max_length=5, blank=True)
You should not store zip data as an integer as they can start with 0. Zip codes use numbers, but aren't actually numbers themselves (leading zeros, no arithmetic, etc). Plus, someday you'll want to ship something to Canada.


The 'meta' there indicates that you're looking at something properly ancient. The ORM stuff in 'meta' is from the Django 0.9x era, meaning 2006.

If you want to store a US zip code today, use the 'localflavor' add-on:

https://django-localflavor.readthedocs.io/en/latest/

Which provides model and form fields and validation for various country-specific data types. It includes a US zip code field.


Even full canonical US zip-codes are 10 characters, right? XXXXX-YYYY or something

Edit: I think it's a typo and meant to be a CharField. There's no such thing as IntegerField max_length.


It's even worse: zip codes can contain letters and spaces in United Kingdom: https://en.wikipedia.org/wiki/Postcodes_in_the_United_Kingdo...


Falsehoods programmers believe about this HN thread: it links to Django's documentation.

It linked to a 13-year-old unmaintained community wiki page, and people apparently didn't look too closely at it. I stuck a big honkin' warning at the top of the page to clarify that.

If you want to handle US zip codes, UK postcodes, or other country-specific data types in Django, may I suggest this, which formerly was bundled with Django and now is maintained as a separate add-on:

https://django-localflavor.readthedocs.io/en/latest/

It includes such things as a correct dedicated US zip code field, and a correct dedicated UK postcode field.


And they are not called zip codes.


A lot of these things are only common mistakes because of Django's unusual behavior.

> POST to views loses POST data

The middlewares shouldn't be redirecting POSTs then! They could have returned a client error instead.

> Blank object names

They could have provided a fallback of __class__.__name__.

> Integer & NULLS

If the admin interface knows the field is required, why does it even attempt to insert a null value? It could return a validation error.

> Appending to a list in session doesn't work

Django's behavior with ORM relationships has always disappointed me. There's no way to work with them in memory like in SQLAlchemy because they always attempt to sync out changes to the database immediately. As a result you often have to write some very strange code. They could change this.

> Errors about undefined attributes with one-char names

They could have done a type check to see if you passed a string instead of an iterable of strings.

...etc.

To me, the Django project exudes the stubbornness of the developers who maintain it because rather than fixing these problems they've decided to write this page about how it's you, the user, who is wrong.


> To me, the Django project exudes the stubbornness of the developers who maintain it because rather than fixing these problems they've decided to write this page about how it's you, the user, who is wrong.

Sounds like you're doing the same thing. You have a set of expectations about how the world works that is not the exact same as Django's - which is true of any other tool anyone uses.

Also I want to point out that software is not made by a monolithic entity; it's made by people, and you suggest a few simple things like adding type checks and validations, which would be a wonderful opportunity to contribute! In fact, opinions such as yours are enormously helpful to the creators of software frameworks. Software doesn't build itself; if you have ideas, contribute!


Back when I was interested in Django I'd go to Python meetups and hear people complain about how the Django project would not accept their patches. They told me that third party changes never make it into Django. That "contrib" is a lie, and that it's made almost entirely by core developers.

Ultimately I found Django to be more trouble than it's worth. I only use it if my work forces me to. I find its design to be obtuse and unpleasant in many places.


> They could have provided a fallback of __class__.__name__.

It does do that

> Integer & NULLs

If you say `blank=True` you're telling the admin it isn't required

> Appending to a list in session doesn't work

99% of the time I never do anything with sessions and I can't think why you would without side effects in any case

> One-char names

That could be type-checked and type hints will probably be added at some point now Django 2.0 drops Python 2 support


> > Integer & NULLS

> If the admin interface knows the field is required, why does it even attempt to insert a null value? It could return a validation error.

There's a lot going on here. In this case, you're telling the admin interface that nothing is required of the user. There could be a default value, for example. On the more technical side, blank and null are different concepts that are codified differently in different database systems. Here, in most systems, a integer attribute is nullable. If it were a string attribute, however, there are cases (Oracle) where null and the empty string are not distinguished, which is rather sensible for text.

This separation supports all of these modes.

I'll give you that `blank=True` lives in the wrong place in today's Django, but it was an early design and it stuck.


>> POST to views loses POST data

>The middlewares shouldn't be redirecting POSTs then! They could have returned a client error instead.

It does raise RuntimeError during development

>> Integer & NULLS

>If the admin interface knows the field is required, why does it even attempt to insert a null value? It could return a validation error.

Maintaining integrity is databases' job primarily, also I could have triggers and functions inside my database to fallback to some default value when there isn't one incoming. This isn't an uncommon setup.

>> Appending to a list in session doesn't work

>Django's behavior with ORM relationships has always disappointed me. There's no way to work with them in memory like in SQLAlchemy because they always attempt to sync out changes to the database immediately. As a result you often have to write some very strange code. They could change this.

Where did ORM come from? Session backends are not exclusively written to be stored in databases.

>> Errors about undefined attributes with one-char names

>They could have done a type check to see if you passed a string instead of an iterable of strings.

...etc.

This way they'd have to type check at thousands of other places where types are assumed. If one isn't comfortable with python's syntactical sugar coatings - inevitably leading to some syntax gotchas, then they should move to more statically typed language.


Someone apparently decided to link a 13-year-old unmaintained community wiki page on HN.

I've added a big note at the top of the page explaining that, and providing a link to the actual Django documentation.


Definitely agreed regarding django orm. And moment you decide not to use it or cannot use it because of legacy issues you're in a world of pain. We've developed https://github.com/shosca/django-rest-witchcraft and https://github.com/shosca/django-sorcery as the project was already using django+sqlalchemy and doing everything manually and also had to touch legacy db's (think composite pk's and all kinds of db quirks..)


> The middlewares shouldn't be redirecting POSTs then! They could have returned a client error instead.

This has been fixed since Django 1.0, released in 2008. The page links to the commit that fixed the issue.


Up until 90 minutes ago the previous change to this was 8 months ago. Before that it was 4 years ago.

I think you might be complaining about out of date documentation :)

Given django's docs are impressive, I doubt this is used actively by people.


I use django at my day job, every day for the past two years. I didn't know this page existed, and better yet, I've never run into these problems


> To me, the Django project exudes the stubbornness of the developers who maintain it because rather than fixing these problems they've decided to write this page about how it's you, the user, who is wrong.

I sometimes feel that, similar to how perl's motto is "There's more than one way to do it", some python developers have converged on an unofficial mottot of "You're doing it wrong".


Because... they are?

I mean look, for the most part developers have optimized a happy path that is by far, one of the most productive ways to get anything done in the web dev world.

If you're purposely going to go against that path for whatever reason, you're going to have to do the heavy lifting that the framework is doing for you.

In the 9 years I've been using Django, I've rarely if ever come to a situation where there was any benefit to working against the framework's idioms. And the more I've grown to using the framework, the more you realize that people would rather create their own thing from scratch rather than learn existing methodologies.


> Because... they are?

The lack of self-instropection & hubris in some framework's devotees is astonishing. If someone is attempting to solve a problem, and their approach is not well-suited to the framework, perhaps it is the framework's fault? Perhaps suggest an alternative tool rather than telling the person they haven't come up with the 'best' approach (which is the version that the framework is well-suited to solve)?

I feel that a lot of the time this defensive "you don't understand the problem" conversations are from devs who have invested a lot of time in the framework & have internalised their expertise into their sense of self-worth, such that 1.) they don't have much experience with other frameworks/approaches which may be better suited to the questioner's problem; 2.) admitting to a failure or gap in the framework becomes equivalent to admitting to a personal failure.

I wish we had less ego in programming, and more decisive, clear declarations of intent and limitations in frameworks.


Not really. What I'm claiming is that in the same way that 99% of claims of people who say they've found a compiler bug have not found one and instead just hit some undefined behavior or language corner case, 99% of people who find something unusual in well-worn web programming frameworks are usually not trying to solve problems the right way.

Synchronous web development in dynamic programming languages is, for all intents and purposes, a solved problem. The conceptual differences between Django, Rails, Laravel and so on are minuscule; there's a bounded number of ways to get a web request and spit out HTML.

It is an extremely well understood problem domain where escape hatches to go against idiomatic framework conventions have been built at all levels and are actually used judiciously by people who have an understanding of the tool's shortcomings.

And in the same spirit, I can say quite confidently that people that are trying to reinvent the wheel here have a non-zero, but minimal, chance of actually hitting a significant roadblock.


Django’s documentation is excellent, but parts of the wiki are out of date.

This page has barely been updated in the last four years. It mentions MIDDLEWARE_CLASSES (deprecated in Django 1.10) and using strings in url() (deprecated in Django 1.8). There may well be other bits which are out of date.

The entries in the faq [1] are more likely to be kept up to date.

[1]: https://docs.djangoproject.com/en/2.0/faq/


The wiki (at code.djangoproject.com/wiki) is community-maintained, and not part of the official documentation, and yes, very often out of date.

The official documentation (at docs.djangoproject.com) is scrupulously maintained, and excellently written.


Thanks for the clarification. My point was that this wiki page is out of date so probably not that useful. I could have been clearer that the wiki is not part of the official documentation.


If you're writing a REST api, invest the time to learn Django Rest Framework. It is well worth it.


DRF is nice enough 90% of the way, but when you need to do something that its authors haven't really thought of, you need to dig in very deep to fix things, I've found. :/


If that's the case, you should take a step back and think about it from another angle to make absolutely sure that you're not attacking the problem from the wrong vector.


I have heard great things about DRF, and often it is good to resist coloring outside the lines.

That being said, your comment assumes that DRF has indeed thought of everything. All abstractions leak, some more than others. Clean escape hatches are very valuable.


I never said that you MUST be thinking about it wrong. I just said to make sure you're not thinking about it wrong. No framework has thought of everything.


Ah, my bad, I should have noticed that.


Agreed, for this reason I stopped using it, the investment in those digs were not worth the time to not copy/paste some CRUD api views. Which is what I do now, and modify as needed.

If the number of models and views grows too much and gets brittle, maybe it will be worth trying again.


I had that issue for a while, but lately I've really just found that 95 times out of 100, I can accomplish everything I want to do with just a .to_native() and using whatever method I see fit. I know it's not always the most optimal way, but leveraging that allows me to really use DRF for so many projects and get it up easily and without too much hassle.


I think this is true of django in general.


> I think this is true of django in general

Probably goes for all opinionated frameworks. That's part of the tradeoff you make when choosing one.


DRF's code is realtively easy to read and it's designed in a way where you can just roll your own parts quite easily.


Seconded. It provides an API similar to that of Django's various Form classes. It should feel somewhat familiar, even to newcomers. Their documentation is also great with rich examples and explanations.


It's my understanding that you can use Django's Form classes to replicate any POST/UPDATE/DELETE operations you'd like to use DRF for. I'm not sure what else DRF gets you besides more API-like auth - for example I don't know how well Django would support token-based auth out-of-the-box as compared to DRF.


You get:

* pluggable authentication methods (literally adding JWT, session and cookie tokens takes one line of code * pluggable output serializers (want YAML? Plug in a renderer. XML? Same thing) * pluggable documentation generators * Utility methods for handling RESTful response types

DRF has a staggering amount of features that, if implemented by hand, require a stupid amount of time and a 100% guarantee of subtle bugs.


Isn't Flask simpler for REST stuff?


Smarter developers than me have spent much time and effort hammering into my thick skull the following idea: one of the most important aspects of a senior developer is the ability to choose the correct tool for the job.

Flask is indeed much simpler, and serves the needs of smaller apps very well. The reason I've stopped using it is because I'm now familiar enough with Django's substantial, problematic learning curve that building a Django project is now just as easy for me as spinning up a Flask app (django-cookie-cutter and wagtail's project init help with this, but they're no replacement for several years of smashing your head against bad Django code). While I love Django, and have derived much utility from the tools it gives me, it's not the solution to all problems, and there are times when Flask makes total sense.

But once Flask's simplicity advantage is removed by experience, I find that it's immensely useful to have (largely correct) opinions on ORM<->DB interactions, templating, settings/config management, form validation, and user authentication baked into the project. For my projects, having these has never cost me anything even if they go unused, and more than once I've gotten myself into the situation of "You either use Django or build Django"

All of the above applies even more so to the specific task of producing a rest API. DRF is, by a large margin, my favorite tool for producing robust, understandable APIs, and I've been lucky enough to never encounter the scaling issues that I've been told (and believe to) exist.


Only if you need to implement simple CRUD API. But if you need filtering/ordering/authorization/complex serialization/unconvential request parsing -- you would need to implement a lot of stuff or install a lot of packages and find a way to make them work together. DRF makes all this things for you.


Sort of, but you'll have to assemble several different libraries to make it good. It doesn't handle request validation, JSON serialization/deserialization, or databases well out of the box.

If you use Flask with Flask-SQLAlchemy be sure to use apply_driver_hacks to enable the pool_pre_ping option or you'll end up in production wondering why 1/3 of your requests are getting a bad DB connection from the pool.

Honestly, it seems like many somewhat essential libraries for Flask APIs are being maintained by one person on GitHub. I wouldn't want to put my faith in that for a core part of my business. Django has a lot more resources going into it even if it's not as powerful as SQLAlchemy or as simple as Flask.


Flask-Restful seems pretty well maintained and it's very easy to use. If you use marshmallow it's very easy to get request validation with meaningful errors. There is also a package called apispec that can make a Swagger specification from your flask paths and marshmallow models. I like Django but unless I'm using it already I've not seen a reason to use it instead of these simpler libraries for APIs.


Hug [0] has my goto for REST. Validation, versioning, serialization, automatic documentation.

[0] http://hug.rest


This looks great! I've been keeping my eye on APIStar but that still seems like it's undergoing a lot of breaking changes. This delivers a lot of the same benefits but it looks like it's actually production ready!


Define, "simpler."

For a simple CRUD API, if you already have a cookie-cutter template of your REST API sketched out with Django Rest Framework, you can write your models and you're done.


For simple stuff yes.

When you have to do an small API in Python is what I use.


Agreed, but with the caveat that there are a lot of bad parts of DRF. It's probably the best tool to build a REST API, but only if you're using some minimal subset of the tools available.


What are the bad bits? Why are they bad?


Too many issue to enumerate them here, but there are just a lot of things that are likely to lead to security vulnerabilities or hidden performance problems. I'm planning to write a blog post on this in the next few weeks.


How do I subscribe to get it?


I'll post it here, you can subscribe via email:

http://alexkrupp.typepad.com/


My favorite opinionated boilerplate for new Django projects: https://github.com/pydanny/cookiecutter-django/

From the author of the great Two Scoops of Django series. https://www.twoscoopspress.com/products/two-scoops-of-django...

Two great ways to avoid some newbie mistakes. Although some could argue diving into boilerplate without understanding it is in fact a newbie mistake itself.


As a word of caution - the authentication framework used in this boilerplate, Allauth, is opinionated and badly documented. Expect to do code dives if you use this.


That’s actually the one thing I throw out immediately when I use this for precisely that reason.


Maybe not just Newbies, but I often notice even seasoned Django developers cribbing about Django's Class Based Views (CBV). I don't really understand why to be honest. There are many blog posts that express regretting the time invested in CBV by their respective authors by pointing out all sorts of pitfalls they fell into during usage. My ex-boss hates it as well, he even banned it from usage among developers. IMHO, it's was a great new introduction in version 1.3.

I hear them discuss about the difficulties and time it takes to implement some views which involves complex logic and more than one entity per view. How to embed a Form inside a Paginated page for example: to use a FormView or to use a ListView or both, followed by a long day of trying to exit a maze full of dead-ends

My advice to Newbies and other people who are struggling with CBV is:

1: You are probably not struggling with the concept of class based views.. just with Django's generic views module

2: Stop stressing about not being able to understand what each Django generic view class does, or it's Mixin classes. Instead refer to ccbv.co.uk and source code extensively - not just the docs.

3: If you are not able to fit every logic you want to fit inside your view using a generic Django view class.. Then just spin up your own class from Mixins or django-braces like nice apps or from object.

4: Remember, one basic upgrade you get from using Classes vs Functions is the ability to extend. If your views can not take advantage of this then you probably don't need a class based view, function based is fine. I almost always keep a base view class with me, often call it a ContextMixin(object) and use it in every view so that i can have some common context variables available in my every template.


Or just don’t use class based views. Simple function views do the job just as well while not obscuring code “behind a magic wall”.


I personally don't use them, except for date-based pages. I find plain old functions the most clear, even if there's a little bit of duplication.


I don't remember running into any of these issues learning Django or maintaining a Django codebase, but I've written the problems I ran into: https://alexcbecker.net/blog/django-is-dangerous.html

In general, I think Django makes it way too easy to shoot yourself in the foot.


“Validation defined on the model is only enforced on the form” hasn't been true since 2010 when Django 1.2 was released. Most of the database-related discussion shares that pattern of either being factually incorrect (“queries can't use computed columns”), blaming Django for MySQL's many problems or failing to fix problems caused by other code failing to do things like input validation.

There's a real discussion about how to handle such issues on large, complex codebase but hiding it behind a clickbait title is not a good way to have that end up anywhere productive.


You must not have read the section "Validation defined on the model is only enforced on the form". The validations I referenced, e.g. `choices`, are only run in when [`full_clean()`](https://docs.djangoproject.com/en/dev/ref/models/instances/?...) is called, and it's not called on `save()`--it is usually called through form validation.

Regarding computed columns, it looks like the specific issue I ran into repeatedly was [fixed in 1.8](https://docs.djangoproject.com/en/2.0/releases/1.8/#query-ex...). I should have been explicit that I was referring to not being able to define such computed columns on the model the way one would a normal column, not to being unable to use `F`-expressions.


> You must not have read the section "Validation defined on the model is only enforced on the form". The validations I referenced, e.g. `choices`, are only run in when [`full_clean()`](https://docs.djangoproject.com/en/dev/ref/models/instances/?...) is called, and it's not called on `save()`--it is usually called through form validation.

In addition to being wrong about whether I read your post, this is a great illustration of what I found tedious while reading it: since that feature was released in Django 1.2, the documentation has been clear about the relationship between save() and full_clean():

https://docs.djangoproject.com/en/2.0/releases/1.2/#model-va...

http://django.readthedocs.io/en/1.2.X/ref/models/instances.h...

The direct statement of fact you used as a heading simply hadn't been true for years before you wrote your post and it's not helped by little mocking asides such as “Because nobody ever modifies a model instance expect through its form, right?” which are basically restating the reasons why that feature exists in the first place.

> I should have been explicit that I was referring to not being able to define such computed columns on the model the way one would a normal column, not to being unable to use `F`-expressions.

Strong agreement here. Your post could have been so much more useful if each of the mocking asides had instead been taken as a cue to ask whether it's more likely that so many people have worked on Django for years without noticing such a major flaw or that your understanding of how it was intended to be used is incorrect.

Imagine if your post had been something like “Things I learned about Django the hard way” and had covered things like picking safer defaults or updating the docs to more explicitly suggest how validation is intended to work (especially in this age where people use fewer forms and more APIs than a decade ago), or that Django treats the database as the ultimate source of truth so you should approach various things about validation and transactions with that in mind (e.g. strengthening the the wording to make it clear that e.g. get_or_create relies on database integrity checks so you should either set those or religiously use some other strategy). That post could be a DjangoCon talk and it'd get a lot more positive reaction than another angry rant on an internet full of them, especially since people in the community would be likely to share it rather than seeing a big claim which is not correct and closing the tab.


Back when I was working on Django codebases, I saw almost no use of `full_clean()`, largely because some validation was performed on `save()` (by virtue of being database constraints, e.g. non-nullability) while other validation was not, and there was no indication in the APIs which was which.

In a world in which Django applications were always written by people who read and understood the docs in full, I would totally agree with you about these criticisms. But I've never had such an opportunity outside of my own projects. I've only dealt with codebases that were written with falty assumptions, enabled by Django's choice to hide some but not all tricky work from its users. By then the database constraints would be incredibly painful to add since there was lots of data already violating it, and switching global defaults like ATOMIC_SAVE were nearly as bad since code had widely relied on other behavior.


I absolutely love Django's documentation. As a desktop developer looking to get more into web stuff, Django has been super attractive as a backend to get my hands dirty with.


Django is great at being "batteries included," with tons of functionality for free. One thing that bugs me about these frameworks however is that you have to wire everything together by hand, sometimes from both sides.

Would be great if there were a product built on top that let you drop a model or a view file in a folder and everything would be wired automatically for the default case, customizable later of course.


Django Rest Framework is getting close to that.


Huh?! Any moderately complex usage of DRF requires tons of boilerplate, or ton of app-specific abstractions... Also, just having to write a view, then a serializer... to actually write it!!

Imho the ideal framework would work with a models definition, json or yaml, not code, with extra anatotions for everything needed to have the logic of stuff like serializers and views instantiated from them. And keep the "custom behaviors" code fully separate from this models config, preferably in some modules with stateless and mostly pure function, sort of the serverless mindset, and not too much oop bullshit on top.

Rails and all the frameworks that copied it (Django, Laravel etc.) set a really bad example imho...


Well, of course complex and specific stuff will require more boilerplate, but if you just need a basic CRUD on a model – just define a view set and you're done, URLs and methods will be created automatically.


> json or yaml, not code only to sooner or later realise that those definitions have turned into a DSL – or code, for that matter, anyway.


I doubt it's still the case but for a long time the default "Authorization" was effectively fail-open so a newbie mistake was to use that and then not customize it leaving your API vulnerable to any logged in user reading anything.

There was a bright red box effectively saying "Don't use this module without customizing it" in the documentation but that didn't stop newbies going live with it in place.


My standard tool for quickly spinning up a web app is Rails, but recently I've been writing a lot of python for data projects and I'm thinking about spending some time learning Django. Rails development seems to be going strong though and has me a little worried. Can anyone speak to Django development and its ecosystem in 2018?


Django in 2018 is still a very vibrant and active community. The project is actively developed, there is a lot of sponsorship from big companies (instagram etc) funding a dedicated fellow who's job is to work on Django full-time.

The plugin ecosystem is very rich and active too - almost always a pre-made package for some feature or implementation you want to add to Django.


Is mylist = []; mylist == [] really a thing for testing for an empty list? Seems very unpythonic.

My newbieish mistake was assuming (forgetting!) that NULLs aren't distinct/unique, so you can not enforce a nullable column unique and expect only a single NULL value. There is a way around it with conditional constraints ... but unique=True or unique_together is not it.

It's really an RDBMS thing, not a Django thing, but when Django abstracts away the RDBMS, one forgets.


> current_zip = meta.IntegerField(max_length=5, null=True, blank=True)

This is given as the 'correct' way?

Storing a ZIP code as an integer? What does an 'integer' length of 5 mean? Integers have max values, not lengths.

"The django docs are so great! They educate you!"

I'm presuming most people aren't being sarcastic when they post that sort of sentiment, but it's hard to take those endoresements seriously.


Someone dug up a 13-year-old page from the community wiki and presented it as "this is totally the official Django documentation".

I've added a gigantic warning at the top of it to address this. See also my other comments in this HN thread, for the right way to do what that particular example was trying to do.


Thanks... ?

Having dates on the pages would probably help avoid some of this in the first place.

People point to a lot of the PHP comments in their docs as "bad" (and many are) but they're also dated, and you can use a comment date of 2009 when trying to give weight to how relevant/useful something may be.

"blank=..." anything is, imo, more confusing than "required=", regardless of what version/age of the docs though.


The issue is: what would you list as the date?

Apparently some other people noticed this was on HN, too, so there are minor edits from a few hours ago, but the bulk of the information is still a decade old. Would you stick a date on every paragraph?

(personally I'd forgotten that this page even existed)


"Created on" and "last modified".

I see last modified way at the bottom of a long page in light grey.

I did not even notice it was a wiki until others point it out.

Biggest text on the page says 'code'. I plead nav-blindness to not seeing 'wiki' in the floating navbar.

Perhaps a date on every block section?

Or... something that throws a big block at the top if the last edit was more than 2 years ago?


Honestly I'm not convinced it's worth the amount of work involved in doing all this, and the number of places available for people to share tips/tricks/etc. has drastically increased since 2005. So if it were up to me the wiki would either go away, or become read-only with prominent "only for historical purposes, don't use information here" warnings.

But I'll think it over.


i was meaning probably more in a general sense, not so much for this particular page. the notice at the top of that specific entry does the trick. a notice at the top of all wikis which aren't intended as the 'official word' indicating such would mitigate a bit of this sort of confusion.


This is very useful for beginners.

I hope more frameworks/languages have a page of common "gotcha's" in their documentation in the future. Then again, it's sort of a right of passage to spend a couple of hours debugging common mistakes when you're learning something new: you'll definitely not repeat your mistake in the future that way :)


Shout out to the IRC #django freenode community. What a helpful group of people if you get stuck, thanks FunkyBob wherever you are.


Please don't ever use integers for ZIP codes. In Germany there are ZIP codes (Postleitzahlen) that start with a 0.


Please don't use examples on a 13-year-old community wiki as recommendations, period!

See the many other comments I've made in this thread for how to handle elements of postal addresses in Django.


"Newbie Mistakes" - this will be read by new people and taken as good practice. They should change these examples.


From my perspective there's little reason to be building html serving webservers these days.

1) Frontend React+Redux paired with an API (eg golang http server serving json)

2) Your boss is going to want "APIs!" soon anyways. le sigh.

3) IMO its as easy to do a JSON API HTTP server in golang as python, but you get typesafety, compiled code and multicore ...


> React+Redux paired with an API

For building a REST API, there are no frameworks or languages I know of that are easier, quicker, or more user-friendly than Django REST Framework. I say this of someone who is not a big fan of Django in general (although it's not a bad framework).

However, I wish that Django REST Framework were build on top of an async HTTP server. Although it's never been an issue, I've occasionally in the past felt uneasy building APIs on top of Django since I know beyond a certain point scaling will be an issue. But either fortunately or unfortunately, I've never had that problem.


I'm trying DRF now (last project in Golang) and one point I have no idea which way to go is how to deliver updates to the mobile client (avoiding polling every N seconds).

I'm not sure I want to try Django channels, which comes with its own spec (ASGI?) and possibly changes the entire way the Django application is run[1].

Should I go with Django channels or - my alternative idea - deploy a separate Golang server only for "real time updates" ? Then I can send updates by simply POSTing from Django to Golang, which forwards the update to the mobile client.

[1] For example: https://channels.readthedocs.io/en/latest/topics/databases.h...


There's recent talk of giving Django an async option:

https://groups.google.com/d/topic/django-developers/Kw7-xV6T...


But then in Goland most people are even against ORMs, so the difference in productivity becomes gigantic. Maybe the pragmatic way is to write a prototype in Django and rewrite in Go once the design stabilizes (I mean, for the smallish stuff I work on..)


These are great tips, but maybe they should be on separate pages so Google has a better chance of matching them up to search queries?


Django is a hell for APIs and big projects. It's good for beginners and small projects, but once you need the least amount of actual control, you will find it's too late


I read this a lot, but I do not agree. Worked on quite large (and busy) websites, did not experienced problems with exactly that. And if the project really is that large, perhaps it is time to split things up? (I intentionally avoid the term microservices, because there are more ways to split things up.)

Actual control... where? And why is it too late? Too late for what?

You can get actual control everywhere if you want to. Doing raw sql queries is perfectly possible. Rendering with jinja instead of django's template system is possible. Speaking to redis directly: possible. Returning a string instead of something rendered: possible.

Heck, even speaking to the django db from another project with sqlalchemy worked out quite alright.

A big problem in large projects is too many queries per view, or unoptimized queries. Django's orm often gets the blame. But I did see that happen with ORMs in other frameworks as well (flask, bottle although an orm is optional). Even raw sql. Another nice feature of django 2.1 will be the .explain() method on querysets. Im using 2.1 to debug queries now and switch back to 2.0 when things are speedy again.

Another problem is having way too many unused variables and unclear calls to database from templates. But that is also a big problem in flask etc.

I think it is a myth Django is a hell for big projects, there are plenty big companies and websites which prove im right. Of course there are struggles. But those struggles are there with other python frameworks as well.

A lot of work happens quickly beyond the framework you use anyways. When a website grows many background jobs have to run or many business rules have to be programmed at some place. This does not have to do with the framework and often times just happens to become messy. I think of the work i do in django projects 30% is django related 70% is django unrelated.

You can consider to use another _static_ language and framework for speedups, like play or something. But i think the parent poster meant Django is a hell compared to other python frameworks.

I do wish django could do some async stuff, like the play framework does. It would be just nice to fire off a few db queries and resize an image and just wait for the result at the moment you build the response. But other than that it is superb!



Can you provide some examples?

I've worked on plenty of large projects and haven't run into places were I've "lost control". Just the opposite, I have found it to be very extensible.

I'm curious if there are cases I haven't hit that you have, though.


Django is perfectly fine for large projects. It's not the size of your project that will end up being a problem it's what you're trying to build that can be an issue.

Most application built today, as in in-house development projects, are basic CRUD applications. Perhaps with some integrations to other systems and maybe a little calculation thrown in. I doubt that many, regardless of size will run into any really challenges.

In terms of API, yeah, Django Rest Framework may not fit you're use case, and if that's the case there's little point to building on Django at all. For the most part, what I've seen, if DRF doesn't work for you, check that you're not actively fighting the framework. Doing the API as DRF want's you to may not result in the API you want, but it will give you a pretty nice REST API in the end.


I think that generally applies to most frameworks, but I've noticed it heavily with django. Developers get upset that Django isn't working for them when they are actively avoiding best practices and going out of their way to fight it.

If you are fighting a robust framework, you are probably doing something wrong and should take a step back.


I feel like I just got into a time machine - this is the top post on hacker news? People are learning Django in 2018?

I guess its fine if you have a small project and aren't going to see much traffic, but Python is so slow and difficult to maintian compared to (e.g.) Go. I say this as someone who worked in Python for a long time, and on several large Django projects.


How large are we talking? Do you consider Instagram large? If so, you should let them know they should stop using Python and Django.


I'm sure they could save a massive amount of money and improve their latencies if they did.


I agree in principle that python for web can be slow, but plenty of sites have been able to scale with it (e.g. Reddit, Pinterest, Quora). So I think saying that python is only for projects that aren't going to see much traffic is a very broad and unfair generalisation.


scalability and speed are two very different beasts. You can build scalable things in Go, or Python, or most any language.

At a certain scale though, the amount you'd save in infrastructure bills by using Go instead of Python is absolutely stupid. A 10x difference would not be surprising in the slightest.


It’s 2018 and people still work on COBOL, but unlike that, Django is actually really great.

Where I’m from the most popular techs are .net (not core), Java, PHP and Django. Django is perfectly viable in that regard.

Go may be better, but if you can run Instagram on Django, I don’t think most people will really have to worry about scalability. Go might become popular eventually, but right now, there isn’t a single golang job in my country, so you know. :)


Oh man! I feel where you are coming from but who clicked on this link except Django fans?

That's like walking into a Django club and telling everyone their framework sucks. Even as a member that only gets you so far.

I can't believe you also called it difficult to maintain! Because when you say slow, the response its easy to maintain, and you went ahead and called it difficult to maintain?

At least give us a reason.


Ha, ok - Django is not difficult to maintain, Django is a very powerful, carefully built framework with tons of features that can get you up and running with a production ready website very quickly.

Python is difficult to maintain. Full stop. Why? Anything in Python can do anything to anything else - there are no boundaries which makes it basically impossible to reason about code at scale. You need very strictly enforced code quality standards across your entire codebase and libraries in order to be able to trust anything - otherwise you don't know if some method on a class has been swapped out right underneath your feet, or if some field access is actually calling a function which is accessing a database.

Go is super easy to reason about compared to Python - as long as no one is importing unsafe or reflect (easy to check), you have very solid guarantees as to what can happen at any point.


Needs change over the lifetime of a project. The flexibility that is a virtue at first becomes less so as designs solidify. Theoretical issues become problems as a codebase/team scales.


Does go have a web framework that does as much for you as django?


I know this was rhetorical, but no, it doesn't


I'd like to see one that does 1/4 to 1/2 as much but otherwise stays out of my way.


It is current year and Django is still very relevant in web development.


The stuff we used Go for was the right choice for Go for sure, but I don't think the API would have been any easier in Go (though I haven't used those frameworks before...).

We also could have done Django a lot better. And all of the Celery stuff probably should have been Go, especially with the Cassandra driver we were using. Still, I'm using Django today and as long as you don't abuse the ORM and nested DRF serializers too much, it's very scalable. I think as long as you make separate services in other languages at the right time for the right use cases, it's a very valid choice for rapidly building an API.


> People are learning Django in 2018?

I am. So, yes.


I surmise I'll still be learning it in 2028!


I am too.


What makes Go projects easier to maintain?


I would argue that it's simplicity. I believe I've read somewhere that Golang was designed with junior engineers in mind. They wanted to create a language that young engineers could learn easily yet cannot make a lot of mess due to its simplicity.

They baked all features necessary right into the language. You get a http server, ssl support, templating engine etc. right in the language. You also have a database agnostic database driver right in the language. Python is also similar in many ways, it comes with "batteries included". But in my experience go standard library is written in a crystal clear straight-forward way. My workflow (and I believe the workflows of many programs) always involves jumping to the source of go standard library and just reading the code.

Django on the other hand has layers and layers of magic, you've got an ORM, modules etc. etc. Some people might like to let a framework handle everything, learn it inside and out and use it. But for other people like me, with a short attention span, django seems subjectively boring. Maybe if I didn't program as a hobby and it was my job to learn django I might have taken the time and learn it.

I started the django tutorial twice in the last 2-3 years. Both the times, I got bored and left. My subjective opinion was that it didn't teach me anything besides how to "generate" a site with Django. OTOH I had much more luck with Flask. Immediately after following the tutorial I was able to write websites and deploy them.

I think it's a matter of taste. I don't like big frameworks, I like to keep things very simple and minimal. My favorite OS of choice is OpenBSD, my favorite languages are C, Golang and Python. I don't like to use IDEs, I use Emacs, even Emacs feels a bit bloated sometimes.

From time to time I get the urge to try one of the big frameworks like Rails and Django, but I never quite got them.


I ran into this problem hard while learning Rails, and a full 99.9% of tutorials out there have you using generators rather than learning how it works. As a result, I didn't learn Rails for ages, writing it off as magic beyond my ken since none of them were teaching me what I thought I needed to know.

The tipping point for me was actually progressing through these tutorials a few times.

In Ralis land, creating a new page results in no less than 3 files being touched. A new view and controller, and a modification to routes.rb so the page can be hit. If those pages need to interact with the database, you also need to create a model and likely a database migration to write your new tables. Once you get comfortable with the ecosystem, you stop seeing the generators as newbie crutches and start seeing them as serious time savers. It's like you're learning a Rake-based metalanguage that spits out Ruby and ERB code.

It's much less time consuming to just delete any extra boilerplate than to make all those changes by hand.

That said, if you dig simplicity, then things like Django and Rails (especially Rails) will be huge turnoffs. The magic is their selling point :)


That is exactly what I felt. Even while using Flask I was put off by having to rely on magical decorators @app.route() etc. While I was experimenting with ruby I had really enjoyed toying around with the cgi module.

Nowadays I want to dig a little deeper into uwsgi with Python.

Maybe at the end of my journey, I will reach enlightenment and get to the point where I start seeing the generators as serious time savers. For now I feel like, if I want a generator, I'll build one :).


> They baked all features necessary right into the language.

Not really. What about sessions? Auth? CSRF protection?


That's true Golang does not come with automatic session management, authentication, csrf etc.

But if you look at it, csrf is just a hidden form value involving a token injected into the page. It is not hard to implement. In that sense Flask doesn't have csrf proection either.

Session management on the other hand could be troubling, but in the end they all rely on cookies: if I take a look at https://golang.org/src/net/http/cookie.go , I can easily make sense of it. But I can imagine the need for a higher level library for session management.

There is something called gorilla toolkit which has session management, but you're right it isn't included in the standard library. Golang's own template engine is also very primitive.


> I believe I've read somewhere that Golang was designed with junior engineers in mind.

Interesting, when one of the complaints about Java is exactly this.


I found the link again, apparently Rob Pike had said:

  The key point here is our programmers are Googlers, they’re not researchers. They’re typically, fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They’re not capable of understanding a brilliant language but we want to use them to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt.  [1]
But I think we should also keep Rob Pike's experience and wits in mind. It was probably intended as a humble witty remark. If you consider how complex concurrency is, and how Golang has made it simple with a single keyword to spawn coroutines (go) and a straightforward data structure (channels), I think he is right to say that Golang is easy to understand and easy to adopt.

[1] http://nomad.uk.net/articles/why-gos-design-is-a-disservice-... citing the quote from http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/Fro...




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: