[HN Gopher] Django and Postgres for the Busy Rails Developer
___________________________________________________________________
Django and Postgres for the Busy Rails Developer
Author : plaur782
Score : 103 points
Date : 2024-12-11 14:56 UTC (8 hours ago)
(HTM) web link (andyatkinson.com)
(TXT) w3m dump (andyatkinson.com)
| Supernaut wrote:
| As a longtime Rails developer who has experimented with Python
| but knew little about Django, I read this article with interest.
| Something that jumped out at me was the author's description of
| the "models.py file, which contains all the application models
| (multiple models in a single file)". I did some quick research
| and I gather that this approach isn't maintained as you move
| beyond the scale of a toy application. I kind of think he's doing
| Django a disservice with his current wording there, as my
| immediate reaction was that it sounded nightmarish!
| pmontra wrote:
| We have a models file that imports models from other files, to
| keep them in the same directory tree. Anyway one could import
| models from any location of the project. Every app the Django
| project is made from can have its own urls, models, migrations.
| 9dev wrote:
| I'm not originally a Python guy, but when I'm forced to work
| with Django, what I do for models and settings and such is just
| creating a barrel module, that is--instead of models.py, have
| models/__init__.py that imports (and thus re-exports)
| everything from every file in the models folder. Then I can
| have a single model per file, as it should be.
|
| I'll never understand the conventions of Python land, but at
| least the language is flexible enough to do it properly.
| bena wrote:
| Yes, that's the way to do it.
|
| Python is fairly accepting with modules being either
| directories or files.
|
| Going the dir/__init__.py route also allows you to do a bit
| of encapsulation as you can not export things.
|
| Of course, someone could import from your file directly
| still. But, yeah, there is no reason to keep _all_ of your
| models in a single file.
| adithyareddy wrote:
| Zulip does this: https://github.com/zulip/zulip/blob/main/zer
| ver/models/__ini...
|
| Zulip in general is a great example of a large open source
| Django app that's been maintained and actively developed for
| a long time. I use it as a reference quite a lot.
| dsego wrote:
| You have dozens of apps (modules) each having its own models.py
| with a handful of models.
| pmontra wrote:
| I'm working on a Rails and on a Django project for two different
| customers and I've been doing that for years now. I'd pick Rails
| over Django any time for every single feature.
|
| The absolute worst Django feature is the templating language. It
| seems to be designed to slow down developers to the like of old
| time Java web apps, almost mandatory templatetags et all.
|
| The query language is moderately bad, quite verbose
| (Model.objects every time) for no good reason.
|
| The lack of common project structure means that every project is
| different.
|
| There is no Capistrano to deploy. I wrote something like that
| myself and we have been using it for maybe 7 years.
|
| I'm sure I could go on for a while if I keep thinking about it,
| but you got the gist of it.
|
| On the Rails side, sometimes I'd like to have a talk with some of
| the previous developers of the Rails app, which hid some
| important functionality in a before save callback in a different
| module for no particular reason, but one can be too clever with
| Python too. However the language (Python) is quite dull, which
| can be a good or a bad thing. It's very subjective. It's a Ruby
| gone bad at design time to me.
| kamikazeturtles wrote:
| Python is used for much more than just web dev and Django,
| whereas Ruby seams to only be synonymous with Ruby on Rails.
|
| Do you think Rails is still worth using when investing in
| learning Python and Django has a much higher roi?
| karolist wrote:
| Majority of learning surface will come from framework and not
| the language, if you need Python elsewhere just learn that as
| well, but this shouldn't move framework choice much.
| Tronno wrote:
| Ruby, and Rails in particular, has a lackluster dev
| experience with any editor that isn't RubyMine. That's been
| a huge obstacle for me personally.
| Joe_Cool wrote:
| Although a bit annoying to install I am still using the
| rails plugin for NetBeans.
|
| I just never switched to Aptana or Rubymine and now I
| don't wanna.
| Lio wrote:
| Each to their own I guess.
|
| Personally I like the ruby-lsp and TPope's Rails plugin
| in NeoVim.
|
| I dislike heavy weight IDEs, I never find the juice is
| worth the squeeze.
| weaksauce wrote:
| ruby-lsp and rails-lsp from shopify is pretty good right
| now and getting better by the day. the vscode extension
| handles it well too.
| infamia wrote:
| > Majority of learning surface will come from framework and
| not the language
|
| Once you get past the beginner level in Django, you're
| going to pick up a ton of Python knowledge (standard dunder
| methods, MRO, standard lib, data type's im/mutability,
| package ecosystem, etc.) and muscle memory along the way.
| Django (for the most part) is just plain old Python data
| structures, classes, and functions that a decent Django dev
| will apart, reuse, override, repurpose, and add on to as
| they do more interesting things. Python is boring (in a
| good way), however it has _a lot_ of surface area (std lib
| is massive) and intricacies that a Django dev will pick up
| along the way to becoming an intermediate /advanced dev. It
| would take someone coming in fresh to Python quite a while
| to catch up. Naturally, if the same person knew several
| languages, the ramp up would be quite a bit quicker.
| criddell wrote:
| It sounds like you've already made your choice and it's a
| good one. Go with Python and make great stuff.
|
| Rails has been around two decades, Ruby three. Both will
| still be there down the road when you decide to try it out. A
| lot of what you learn in your Python work will translate in
| some way to Ruby & Rails.
| RangerScience wrote:
| Yes. You learn unique, transferable things from every
| language and framework; usually, techniques and perspectives,
| but also confidence and theory.
|
| I'd also contest your statement that learning Python and
| Django have a "much higher ROI" - but, I don't actually want
| to get into it.
| giancarlostoro wrote:
| Funny you mention templating, its one key thing I'd change
| about Django, that... and maybe scaffolding, I'd crank it up
| drastically more.
|
| My ideal enhancement to Django would be something like how
| Microsoft made Razor into Blazor... A template engine that can
| run purely on the back-end or purely on the front-end,
| replacing any need to ever use JavaScript, you stick to your
| native programming tongue if you will.
| davepeck wrote:
| I think of Django's templating system as a great tool for a
| previous era. I'm hopeful that PEP 750 [1] gets accepted and
| a modern ecosystem of template engines emerges in Python-
| land. For the moment, I tend to use in-python builders like
| htpy [2] when I want back-end Python code to generate some
| HTML.
|
| [1] https://pep-previews--
| 4124.org.readthedocs.build/pep-0750/
|
| [2] https://htpy.dev
| ic_fly2 wrote:
| The whole appeal of Django is that you can just swap in a
| different templating engine / syntax if you prefer.
|
| And you can add a DB and let there be managed by some other
| system.
|
| Same goes for extending manage.py
|
| I've worked on Django projects big and small and generally the
| speed are which we could deliver even on strange edge cases
| impressed.
| mostlysimilar wrote:
| You can do that with Rails too. The difference is that Rails
| defaults are very good.
| aerhardt wrote:
| The Rails dev says that Rails defaults are very good and so
| says the Django dev about the Django defaults.
|
| The Django ORM is loved by tens, maybe hundreds of
| thousands of Python devs globally, and while I could raise
| concerns about it (for example, the async experimental
| capabilities fucking suck, and the core dev team is
| extremely slow to innovate on them on the basis that that's
| not "the Django way"), I've never heard anyone but a Rails
| dev complain that it's "too verbose".
|
| People love it so much that they'll do atrocities like
| import it into Jupyter notebooks or simple scripts that
| should otherwise have no business in bringing in those type
| of dependencies. I should know because when I've felt
| creative and a bit naughty about doing those types of
| things I've found out - to my unmeasurable disappointment -
| that there were many other trailblazers before me to write
| gists, Medium articles, and almost everything every type of
| format short of an entire O'Reilly book on how to do it.
| deaddodo wrote:
| > I've never heard anyone but a Rails dev complain that
| it's "too verbose".
|
| Maybe not too verbose, but there's a large population of
| python devs that find SQLAlchemy (+ Alembic) the much
| better option.
| kshahkshah wrote:
| That's curious to me honestly. I really prefer the
| ergonomics of Django's ORM compared to when I've had to
| use SQLAlchemy+Alembic in the past. I find alembic
| incredibly confusing and poorly documented. Not that
| documentation matters as much nowadays with AI
| adammarples wrote:
| Actually the dango dev is saying that the whole appeal of
| dango is that you can swap the defaults out easily, kind
| of the opposite
| techscruggs wrote:
| A bit off topic, but whenever Rails and templating get brought
| up, I have to plug my absolute favorite project out there:
| Phlex https://beta.phlex.fun/. It's like ViewComponents, but
| swap out the ERB for pure Ruby. It has been a joy to develop
| with.
|
| With the addition of Phlex::Kit, it has made building out a
| component library pretty easy too. RubyUI
| https://github.com/ruby-ui/ruby_ui does a great job of showing
| off how to do this.
| petepete wrote:
| Funnily enough I write most of my view components without a
| template these days, unless there's a load of markup.
|
| I keep meaning to take a look at Phlex.
| pmontra wrote:
| Those kind of things used to be a lose lose proposition back
| at the time of haml (?) and all the yaml like templating
| languages. That was more than 10 years ago. The reason was
| that any designer that could actually do html was able to
| write an erb page, maybe except loops and logic, but they
| could understand them if a developer added them into the page
| later. On the other side with one of those languages, and
| more with phlex, only a developer could write the views so we
| were back to the 90s with photoshop layouts.
|
| Furthermore your can't copy and paste examples. Think about
| Bootstrap components. You have to really write everything
| from scratch.
| whalesalad wrote:
| Rails is 10x better than Django in every way and it isn't even
| close.
| pmontra wrote:
| I add one item to my own list: Django admin, being backed by
| default into the framework is a good thing. Rails has
| ActiveAdmin but it's a separate gem and it requires more work
| to integrate. Furthermore, being extra work is something that
| some customers don't want to pay for. With Django, it's always
| there.
| dethos wrote:
| I've worked for many years with both frameworks. I have the
| opposite view, since I prefer the Django ecosystem and Python.
|
| Rails has nice things, but overall, I prefer Django's approach
| and the language it uses.
| mlboss wrote:
| For an alternative django templating, I would recommend htpy.
| https://htpy.dev/
| mrsilencedogood wrote:
| I've used rails for years, and have used old versions of django
| at one company, and used python extensively for non-web
| purposes.
|
| I think my take is that there's no middle-ground between Rails
| and some of the newer Java-based frameworks.
|
| Either I'm doing a side project or startup, and I need to go as
| FAST as possible, type systems and similar be damned, or I'm OK
| with not going as fast as possible and we're going to go slower
| but deliver something very solid.
|
| Python/django still had me spending a bunch of time on stuff
| that rails will either generate, scaffold, or hide from you
| completely. While still not being nearly as safe or performant
| as anything in the Java world. Note I'm mostly thinking about
| more modern frameworks like Javalin, not necessarily Spring's
| entire ecosystem/way-of-life.
| theflyinghorse wrote:
| I was not aware of Javeline being used in the same way that
| RoR/django/Laravel would be used. Javeline provides
| primitives to build a backend/API layer only no?
| paulddraper wrote:
| Rails is so good it succeeded despite Ruby.
|
| Django's main benefits are
|
| 1. Admin interface 2. Python
| kshahkshah wrote:
| Unfortunately for Rubyists (myself included) those are huge
| benefits though nowadays. It's much easier to find Python
| developers.
|
| Having an out-of-the-box admin interface means business
| people can operationalize and workaround short comings of the
| software today, not tomorrow. I think functional admin
| interfaces can often be the difference between a successful
| company and one which is constantly operating off of
| spreadsheets in the background and never fully commits to
| their software.
| wfleming wrote:
| > Migrations in Django > > The Django approach has noteworthy
| differences and a slightly different workflow
|
| My explanation of Django's approach to migrations would involve a
| lot more expletives. It is by far my least favorite thing about
| the framework.
|
| - Fields are not-null by default, the opposite of SQL itself
|
| - Field declarations use argument names that _sound_ like the SQL
| equivalents (default, on delete cascade /restrict), but they're
| fully enforced in python and don't make it into the SQL schema at
| all by default. I get that not every DB supports these features,
| and there are sometimes good reasons for doing something like a
| delete cascade in process (if you need to implement custom on-
| delete logic or something), but the DSL shouldn't read like SQL
| if it's not going to change the SQL schema. The default value
| thing combined with not-null by default is particularly easy to
| get bitten by adding a new field with default if you deploy
| migrations separately from deploying code (which you must do to
| avoid downtime): if you add a new field with a default value
| believing it's safe, you will probably get crashes in the
| interval between applying the migration & the new code deploying
| because you've got not-null column without a default value in the
| schema. They did finally add db_default recently, thankfully, but
| it took years!
|
| - Django migrations cannot be understood in isolation, the sql a
| generated migration containing something like an AlterField
| operation will run depends on what _earlier_ migrations say. You
| have to check with the sqlmigrate command and /or actually read
| earlier migrations to be sure you understand what the migration
| will do. Compared to Rails, where each migration can be read and
| understood in isolation (though you may still need to understand
| how a Rails migration DSL will translate to actual SQL of
| course). This also has a performance impact making Django
| migrations slower because Django has an in-memory model of what
| the schema should be at each migration point, so running a
| migration is not just "load the file and run the commands", it's
| "determine the schema that should exist after running this
| migration, diff that with the schema we think exists before this
| point, magically generate SQL for that diff, then run that".
|
| - The makemigrations command to auto-generate pending migrations
| is very aggressive and will detect things as "changed" that don't
| impact the schema. If you changed some help text on a field, or a
| localization string, or the aforementioned only-in-python default
| value, makemigrations will see that as requiring a migration that
| does nothing. Leads to lots of cruft.
|
| - Related to both of the above points, AlterField's auto-
| generated SQL can be dangerous and bad. Particularly, I've seen
| cases where very minor changes to a ForeignKey (like changing
| from nullable to not-nullable, or even not-schema-impacting
| changes like above) would, by default, have dropped the foreign
| key constraint & index, and then re-created them. Completely
| unnecessary and potentially dangerous since it could be locking a
| large table. I'm not positive, but in some cases I think these
| have been generated purely because of a django upgrade leading to
| it deciding the names of the indexes/constraints need to be
| changed for some reason.
|
| - AlterField will _also_ tend to stomp all over any tweaks you
| manually made to the schema to work around all these issues. If
| you manually wrote a SQL statement in an earlier migration to add
| a default value to a column, and then that column 's definition
| gets tweaked months or years later the generated AlterField is
| gonna remove your default value. At a technical level this isn't
| surprising when you understand how Django is modeling the schema
| internally & generating the SQL changes, but it's definitely a
| bad user experience downstream of a lot of these design
| decisions.
|
| Generally the field declaration/migrations system in Django feels
| to me designed to lead people down a garden path towards bad and
| dangerous behavior. If I had my druthers I'd enforce a policy in
| our Django app of "never run makemigrations, all migrations must
| be manually written SQL".
| infamia wrote:
| > The default value thing combined with not-null by default
|
| It is interesting... I strongly feel the opposite after
| debugging far too many SQL queries where someone checked for an
| empty string but forgot to check for NULL. NULL by default is a
| SQL footgun IMO.
| wfleming wrote:
| I prefer null as a clear "no value" marker to handle rather
| than special-casing handling of an empty string vs other
| strings, and if "empty string" isn't considered valid that
| should be validation logic and that should never get stored
| in the database. But it's certainly a matter of opinion and
| either can work as long as you're consistent.
|
| The point about Django's choices about default and not-null
| though is that it can easily lead to crashes while you're
| adding fields. If you add a string field with default="" and
| don't specify null=False, the generated schema will be a non-
| null field without a default value in SQL, but Django will
| backfill "" into all existing rows. To avoid downtime, you
| need to deploy migrations & apply them, then deploy the
| models.py/other code changes. But if anyone tries to write a
| new row before the new code finishes deploying after applying
| the migration, it will crash.
| alephxyz wrote:
| > Generally the field declaration/migrations system in Django
| feels to me designed to lead people down a garden path towards
| bad and dangerous behavior. If I had my druthers I'd enforce a
| policy in our Django app of "never run makemigrations, all
| migrations must be manually written SQL".
|
| `makemigrations --dry-run` is helpful to see if your manual
| migrations are complete but besides that I agree
| czhu12 wrote:
| I worked significantly in both Django and Rails, and I found the
| most magical part of rails is its ORM (ActiveRecord). I find both
| SQLAlchemy and DjangoORM both more awkward and less natural to
| use, both for the query side and the relationship definition
| side.
|
| Once the data is loaded into memory, everything else is just
| syntax.
|
| At this point, I only reach for python as a web application if I
| need to build something that has AI / ML features. Rails apps
| I've built in the past that needed to call a local model resulted
| in having to create a python inference microservice, which kinda
| sucks.
| RangerScience wrote:
| FYI, there's a few projects out there for interoperability
| between Ruby and Python - stuff like putting one language in
| another.
|
| Also, Jupyter and Zeppelin notebooks allow for
| interoperability, although I don't know how.
|
| (Oh, lastly, if there's a JVM implementation of Python you
| could probably use alongside JRuby)
| kitsune_ wrote:
| I have yet to see a software project where ActiveRecordish ORMs
| did not end up making the modelling of business processes and
| translation of use cases into code overly messy and complicated,
| Rails or Django.
| RangerScience wrote:
| The Rails apps I've worked with where there was an ORM mess
| (which yeah... is all of them) it's extremely clear that the
| mess is the normal "too fast" software development mess. Sure,
| it's worse because it's the ORM (and/or sharp knives), but it's
| also always been the case that I can clean it up with _better_
| use of Actuve Record.
|
| Also, I've worked with some pretty gnarly pure-SQL systems that
| had essentially the same kinds of problems.
|
| It's all just variations on "saving hours of planning with
| months of work" kind of things.
| Tainnor wrote:
| Rails and especially DHH particularly encourage not having
| any sort of separation between your domain objects and your
| persistence (and even your views), which is why N+1 queries
| are so goddamn common and why people are going to put
| confirmation mail logic in model callbacks etc.
| devjab wrote:
| I can't speak for rails's ActiveRecord but I don't think
| DjangoORM is worse than any other ORM in that regard. It's
| probably one of my favorite ORMs. I don't think I'll ever
| really use it again but that includes every other ORM.
| kitsune_ wrote:
| I mean there is a clear difference in how ORMs that use the
| data mapper pattern like Hibernate or Entity Framework etc.
| ultimately allow for a cleaner overall application
| architecture vis-a-vis ActiveRecord (the pattern) which
| usually ends up leaking throughout the entire application.
| devjab wrote:
| I think we agree. I don't think there is that much
| difference between ORM patterns (and I'm sorry I
| misunderstood you) because they all eventually become more
| trouble than they are worth in larger and more serious
| projects. I agree that you can probably go further with
| data mapper pattern ORMs, like EF, but I'm not sure I think
| the same is true for something like DjangoORM vs
| SQLAlchemy. On the flip-side a lot of projects will do fine
| with any ORM and never run into issues over their
| lifecycles.
|
| Though in a world of SQLC (and similar) I'm not sure what
| ORMs are really solving for anyone anymore.
| brap wrote:
| With all of this praise Rails is getting, even still in 2024,
| it's mind boggling how there was never a successful Rails
| alternative in one of today's popular web programming languages.
| Nothing ever caught on.
| joshlemer wrote:
| Laravel and Django don't count?
___________________________________________________________________
(page generated 2024-12-11 23:00 UTC)