Live data from Hacker News

Some more things about Django I've been enjoying

jvns.ca

61–70 of 128 posts

Re: Some more things about Django I've been enjoying

#61

Earlier quoted context omitted.

Not the author, but I no not understand the desire to use multiple apps. I am never going to want to carve one out as a separate module I re-use in another product. It is all interconnected, why add arbitrary boundaries separating them? Put everything into a "core" app and move on with life. Maybe if you are an enormous organization working on Instagram where you have rigid responsibilities per team.

So you’d prefer one file with all models? Do you break out into apps for business logic? Keep models in one app/file. Then domain driven design elsewhere?

As things get more complicated, I will separate out by some kind of concept. Which can be something as simple as:

  /coreapp
    /forms_foo.py
    /forms_bar.py
    /models_bar.py
    /models_foo.py
    /views_bar.py
    /views_foo.py
You can do a more sophisticated module layout, but essentially something as straightforward as the above, all under a single "core" application. Prevents Django from fighting you when you want to work across the arbitrary "app" boundary.

Re: Some more things about Django I've been enjoying

#62

Earlier quoted context omitted.

- Django apps are an anitipattern for large internal / single purpose products due to migration overhead as FKs cross application boundaries Totally agree with this. Now we have thousands of unsquashable migrations that require a ton of work to fix.

Can you share more on this? Is it better to keep all models in one app?

Well whether it's better or worse depends on your specific situation.

What I'm facing right now is a 10 year monolith modularized with applications. Like a sibling comment already discussed these applications are not reusable application so almost all advantages of having that are moot.

Now, the consequence of having this structure is that we now have complex dependencies between the migrations of these apps i.e. cyclic dependencies, dependecy constrains that are underspecified. Thousands of migrations that now take a significant amount of CI time. We would like to squash them but it requires a lot of review and manual work and if we keep using multiple apps we are going to ave the same problem in the future.

The only meaningfull gain we had with multiple apps is that we have less migration conflicts when people create migrations concurrently.

Is that advantage worth the pain? I don't think so.

Re: Some more things about Django I've been enjoying

#63
post #57

Not to be a downer since a lot of JEvans’ content is great. People should really give .NET a try. I don’t know if we are just old greybeard curmudgeons who look at this and go “is this a new thing? haven’t we been doing this for decades?”, but .NET out of the box with a few packages for databases, logging, etc is so pleasant you don’t even think about it. Maybe it’s just not a vocal community idk.

At this point Django also qualifies as "for decades" - most (maybe all?) of what's in this post applied back when it was new. The basic design has been stable for a very long time.

Re: Some more things about Django I've been enjoying

#64
post #57

Not to be a downer since a lot of JEvans’ content is great. People should really give .NET a try. I don’t know if we are just old greybeard curmudgeons who look at this and go “is this a new thing? haven’t we been doing this for decades?”, but .NET out of the box with a few packages for databases, logging, etc is so pleasant you don’t even think about it. Maybe it’s just not a vocal community idk.

To be fair, for grey beards, python predates .net and I was using Django in 2008, which predates .net mvc.

Re: Some more things about Django I've been enjoying

#65
post #5

> Some light load testing (with (ab -n 1000 -c 1) shows that right now we can serve about 2-3 requests per second (on a ~$10/month VM). > After turning on template caching, it seems like the site can now pretty easily handle 12 requests per second or so without using all of the CPU. I have not carefully benchmarked the before and after but it seems like it’s made a pretty big difference. That seems crazy low, I think…

Those numbers sound... Single-threaded. Like they're using the development runserver instead of uwsgi or gunicorn.

Development runserver has been multithreaded by default for over a decade. I think you need to go back to major version 1 to see it single-threaded by default. Maybe affected by the GIL though.

Re: Some more things about Django I've been enjoying

#66

Earlier quoted context omitted.

Can you share more on this? Is it better to keep all models in one app?

Well whether it's better or worse depends on your specific situation. What I'm facing right now is a 10 year monolith modularized with applications. Like a sibling comment already discussed these applications are not reusable application so almost all advantages of having that are moot. Now, the consequence of having this structure is that we now have complex dependencies between the migrations of these apps i.e. cyc…

We have a distributed monolith that's 20-30 years old, that has various systems written in various different languages interacting with multiple interconnected databases. We're working on migrating all of it to python, using django models.

The key thing in a system like this, that was kind of stumbled upon by previous devs who started the python migrations, is the database should be treated as its own independent unit and managed separately from the individual applications that connect to it. For example, we've defined the django models in an independent library that the individual applications import. It also contains the configuration for routing queries to the different databases - only takes a couple of lines of boilerplate in the application's settings file.

We haven't yet switched to using django migrations and are still doing updates manually, but after some work the past couple of years it would now be an option. They would go in the common library, avoiding the pain points you've listed, and could be run from any application that needed it - django tracks the migrations that were run inside the database so they'd all see the same thing and act the same way.

For us, it has absolutely been a major benefit.

Re: Some more things about Django I've been enjoying

#67

> Some light load testing (with (ab -n 1000 -c 1) shows that right now we can serve about 2-3 requests per second (on a ~$10/month VM). > After turning on template caching, it seems like the site can now pretty easily handle 12 requests per second or so without using all of the CPU. I have not carefully benchmarked the before and after but it seems like it’s made a pretty big difference. That seems crazy low, I think…

It's because -c 1 only makes 1 request at a time, which is not representative of a real website load. This was also brought up on lobsters a few days ago https://lobste.rs/c/lctz1y

1000ms / 12 = 83ms per request which sounds normal

Re: Some more things about Django I've been enjoying

#68
post #32

Earlier quoted context omitted.

Not if you do the magic with getattr and comparison overrides. You actually need to do it on the metaclass because the Field as I wrote it isn't an instance but this works: from datetime import datetime class Filter(): def __init__(self, name): self.name = name def __gt__(self, value): return { "field": self.name, "operator": ">", "value": value } class FieldMeta(type): def __getattr__(cls, name): return Filter(name)…

If you change an operation that is meant to return a Boolean to return anything else, you are insta fired.

That's a well established pattern in Python, for instance with Numpy. That's the point. Operations in Python aren't "mean to return" anything in particular. Each class can define the operations as it wants. That's a powerful feature that allows creation of specialized expression languages, as used by other ORMs besides Django.

Re: Some more things about Django I've been enjoying

#69
post #29
post #24

Earlier quoted context omitted.

if self._midnight(today) returns a datetime object, than: self.filter(end__gt=self._midnight(today)) will evaluate to: self.filter(end__gt= ) While self.filter(Field.end > self._midnight(today)) will evaluate to: self.filter( )

How would you model string comparisons with LIKE?

For those you would have a method on the field object (e.g., `Table.field.like("whatever")`).

Re: Some more things about Django I've been enjoying

#70
post #24

Earlier quoted context omitted.

> I can't quite picture how operator overloading would look like, could you give an example? Instead of this: self.filter(end__gt=self._midnight(today)) You could write a "Field" class that implements __getattr__ and __gt__ so you could do self.filter(Field.end > self._midnight(today)) The "Field.end > self._midnight(today)" would evaluate to an object that would just store "my field name is end and my value needs to…

if self._midnight(today) returns a datetime object, than: self.filter(end__gt=self._midnight(today)) will evaluate to: self.filter(end__gt= ) While self.filter(Field.end > self._midnight(today)) will evaluate to: self.filter( )

No it won't, because there's no requirement that the result of `>` be True or False. It can return an object that then can participate in further expressions that "keep track" of what operations are done to the fields.
Post reply on HN