I mean first of all you could "just" use an array field for your list of items. Single model.
But then you have actual properties on your todo list. So even in your object model you already have two classes, and your todo list has a name and a list of items.
So there's not one class, there's two classes already.
As to "having a list", Django gives you reverse relations so you can do `my_list.items.all()`. Beyond the fact that your persistence layer being a database meaning that you need to do _something_, you're really not far off.
One could complain that `my_list.save()` doesn't magically know to save all of your items in your one-to-many. But I think your complaint is less about the relational model and much more about the "data persistence" question. And Django gives you plenty of tools to choose how to resolve the data persistence question very easily (including overriding `save` to save some list of objects you have on your main object! It's just a for loop!)
Using an array is just giving up on a relational database. In fact what you'd do is use a JSON field, but at that point you don't need an ORM, just use an object database.
You can only do `my_list.items.all()` if you've already saved the related records in the db. And if you do something like `my_list.items.filter(...)` well that's another db query. A proper ORM should be able to map relationships to objects, not these thinly veiled db records. See how SQLAlchemy does it to see what I mean. In SQLAlchemy you can fully construct objects with multiple layers of composition and it will only map this to the db when you need it to. That means you can test your models without any kind of db interaction. It's the whole point of using an ORM really.
I mean if you think SQLAlchemy does the job for you that's great! My general contention is more "there are good ORMs". I believe Django is the good one, but if you think SQLAlchemy works well for you, go for it!
They are all useful tools, but I think it's important to keep them in context. I feel like what most people want is the automatic SQL generation from their general purpose language of choice. That and a migration framework. But none of them should be considered a no brainer because they all come with considerable downsides. One of the most difficult things I've found in complex, long running projects is people clinging on to the ORM long after it's ceased to be useful. SQLAlchemy at least lends itself better to proper architecture with it's data mapper, but Django really doesn't like being relegated to a lower level.
But then you have actual properties on your todo list. So even in your object model you already have two classes, and your todo list has a name and a list of items.
So there's not one class, there's two classes already.
As to "having a list", Django gives you reverse relations so you can do `my_list.items.all()`. Beyond the fact that your persistence layer being a database meaning that you need to do _something_, you're really not far off.
One could complain that `my_list.save()` doesn't magically know to save all of your items in your one-to-many. But I think your complaint is less about the relational model and much more about the "data persistence" question. And Django gives you plenty of tools to choose how to resolve the data persistence question very easily (including overriding `save` to save some list of objects you have on your main object! It's just a for loop!)