Django Newbie Mistakes
code.djangoproject.com
code.djangoproject.com
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.
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).
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.
The Serverless documentation, an SPA, blew my mind in terms of how fast and clean it is: https://serverless.com/framework/docs/
(Single Page Applications arguably have their place. I'm just really confused why you think this is a particularly good example.)
HN is my baseline for how fast a site should be.
You can test the difference yourself by toggling JavaScript in your browser.
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.
Have you tried browsing the site...?
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...
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.
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.
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.
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.
Hacker news:
- first load: 6 seconds
- next loads: 3.5 seconds
Serverless:
- first load: 26 seconds
- next loads: 7.5 seconds
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.
The only thing I can conceivably think of is an offline app, but they're so rediculously niche.
I think it's just web developers who like SPA's
Why would you want to move away from something that works?
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.
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.
Edit: This was removed in Play Framework 2
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.
(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)
Any areas that Pyramid doesn't do well at?
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.
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.
Curated ecommerce, a CRM like system for stylist, order management, fulfilment and distribution.
https://thread.engineering/scaling-django-codebases-pycon-uk...
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.
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.
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
Each solution for Python/Django add complexity: - async -> celery/rabbitmq - websocket -> Channels, Daphne, asgiref, channels_redis, redid.
It's quite huge to manage.
Sure....
For old good stuff is still a good framework. It really depends on your usage.
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?
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...
Love the admin interface and logic though, and python>ruby IMHO
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.
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.
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.
> 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.
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.
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.
Try it. You'll understand what we mean when we say they're good.
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.
Docs, error messages etc are WAY superior in Perl. Idiot.
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.
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.Edit: I think it's a typo and meant to be a CharField. There's no such thing as IntegerField max_length.
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.
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.
> 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.
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
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 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".
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.
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.
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.
This has been fixed since Django 1.0, released in 2008. The page links to the commit that fixed the issue.
>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.
> 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.
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!
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.
I've added a big note at the top of the page explaining that, and providing a link to the actual Django documentation.
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.
The official documentation (at docs.djangoproject.com) is scrupulously maintained, and excellently written.
* 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.
If the number of models and views grows too much and gets brittle, maybe it will be worth trying again.
Probably goes for all opinionated frameworks. That's part of the tradeoff you make when choosing one.
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.
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.
[0] http://hug.rest
When you have to do an small API in Python is what I use.
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.
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.
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.
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.
In general, I think Django makes it way too easy to shoot yourself in the foot.
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.
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.
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.
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.
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.
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...
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.
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.
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.
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.
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.
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.
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)
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?
But I'll think it over.
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 :)
See the many other comments I've made in this thread for how to handle elements of postal addresses in Django.
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 ...
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 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...
https://groups.google.com/d/topic/django-developers/Kw7-xV6T...
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.
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!
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.
If you are fighting a robust framework, you are probably doing something wrong and should take a step back.
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.
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.
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.
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 :)
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 :).
Not really. What about sessions? Auth? CSRF protection?
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.
Interesting, when one of the complaints about Java is exactly this.
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...
I am. So, yes.
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.
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.
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. :)
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.