News for hackers. Stuff that matters.
Re:Elixir for Humans Who Know Python by josevalim on Saturday February 25, 2023 @10:03AM (#34937160)
Thanks for the insights, I appreciate it! I will take some time to go through the docs and learn more. One last question for now (I hope): after the migrations are auto-generated, do you check them into version control?

> Models are for developers and generally developers have all the permissions any way

To clarify, the reason why you would want to have read-only models is rather in complex data model cases or for performance reasons. For example, if you have a large model with 50 fields, defining a subset with 10 fields can be beneficial to performance in several queries. Other than that, I agree with you.

Re:Elixir for Humans Who Know Python by Alir3z4 on Saturday February 25, 2023 @10:39AM (#34937441)
Yes. Migrations are checked into the source control. They're still the source of truth of the database changes.

Regarding read only models pointing to a tabel. It'd possible to use proxy models or even non managed models where with some mix of Managers it can provide what you're looking for.

For getting a subset of fields from a database tabel, Django provides ".only()" on the QuerySet which you can use to list all the fields explicitly and only them will be retrieved. It can even span to foreign field relations as well.

Diango ORM is indeed powerful and vrry flexible once you learn it. A novice developer can use it quickly and won't get in the way. An advanced developer can do very complex sfuff with it without touching any raw sql. Still, it's possible to write custom sql commands directly.

Re:Elixir for Humans Who Know Python by traverseda on Saturday February 25, 2023 @10:32AM (#34937374)
Yep, you do check the migrations into version control.

>For example, if you have a large model with 50 fields, defining a subset with 10 fields can be beneficial to performance in several queries. Other than that, I agree with you.

Nope, the django ORM has several helpers here. What you do in the most basic case is do something like

    MyTable.objects.filter(key__gte=12).only("field1","field2","field3")
Which will (during the initial request) only fetch the specified fields from the DB. There's an equivalent (defer) for telling it not to fetch those fields during the first query.

Of course is someone than tries to access "field4" in a template/view django will make an additional query to get that extra data.

It's a bit more complicated to make a nice chainable filter so you can call `MyTable.objects.only_foo_rows()`, you'd need to define a method on a custom object "manager", but that still wouldn't generally be handled at the model level.

There's also things like select_related, prefetch_related, and other tools to make the ORM layer more performant. Of course for really exotic things like tree-based data structures you can also perform raw SQL queries on an ORM object with `MyTable.object.raw("SQL goes here")` and have it still return ORM objects. Please don't do that though.

For a long time I didn't realize why people were so down on ORMs until I tried using a non-django ORM, it really does set the bar.

Re:Elixir for Humans Who Know Python by Alir3z4 on Saturday February 25, 2023 @10:44AM (#34937483)
> For a long time I didn't realize why people were so down on ORMs until I tried using a non-django ORM, it really does set the bar.

This. Very much this.

I have given up on one finding such. The closest and nicest one that comes to mind is SQLAlchemy. The rest of languages or frameworks have indeed nothing compared to Django ORM and SQLAlchemy. It's not even fair to compare them.

Re:Elixir for Humans Who Know Python by traverseda on Saturday February 25, 2023 @12:26PM (#34938413)
Peewee ORM can also be nice if you need support for more esoteric DB features (sqlite user-defined table functions?). No migrations though.
Re:Elixir for Humans Who Know Python by spapas82 on Saturday February 25, 2023 @02:20PM (#34939571)
My experience is also exactly like this. I have a project in java/spring and it uses hibernate as an ORM. I can't think of how much better is the Django ORM than hibernate. When people express hate for ORMs I understand where this hates comes from.

If I ever need to do another Java project I prefer to use raw jdbc sql than using hibernate.

Re:Elixir for Humans Who Know Python by josevalim on Saturday February 25, 2023 @10:51AM (#34937533)
Ack on migrations, tks!

---

For completeness, you can do the same in Ecto:

    from t in MyTable, where: t.key >= 12, select: ["field1", "field2", "field3"]
However, that will still allocate a "MyTable" struct in Ecto. And if that struct is large (say 50 fields), slots for it are allocated (but none of the actual data on the fields).

I am not familiar with Python Object Model enough but, if your Python example still allocates an object with slots for all 47 other fields besides the three selected, then you may still find yourself under circumstances you would rather have a "slim" version of the model and reduce memory allocation. This may be needed when you need to load thousands of entries into memory for processing or similar.

I am not saying this is a must have but I am just trying to clarify what my initial comment was about. :)

Re:Elixir for Humans Who Know Python by traverseda on Saturday February 25, 2023 @12:23PM (#34938391)
>I am not familiar with Python Object Model enough but, if your Python example still allocates an object with slots for all 47 other fields besides the three selected, then you may still find yourself under circumstances you would rather have a "slim" version of the model and reduce memory allocation.

Honestly at that point probably don't be using python. ORM objects don't use slots, they use a hashmap to look up everything every time, and probably that hashmap points to a method that points to another hashmap that points to some kind of data structure.

If you're worried about that than django probably is not for you. That being said it scales out very nicely, you probably are not loading dozens of thousands of entries in to memory at once but are instead using a celery distributed task queue. If you did need to load that much in to memory for some reason (presumably some kind of data science?) You can use the `in_bulk("field1","field2","etc")` query option to return raw data as dictionaries/lists instead of ORM objects. You don't get the benefit of ORM methods but you're not instantiating an ORM object for every row and probably for that kind of thing you're better off taking a more functional approach any way.

Re:Elixir for Humans Who Know Python by josevalim on Saturday February 25, 2023 @12:49PM (#34938649)
That’s great, thanks for taking the time! Appreciated.
Re:Elixir for Humans Who Know Python by Xzya on Saturday February 25, 2023 @12:57PM (#34938750)
> I am not familiar with Python Object Model enough but, if your Python example still allocates an object with slots for all 47 other fields besides the three selected, then you may still find yourself under circumstances you would rather have a "slim" version of the model and reduce memory allocation. This may be needed when you need to load dozens of thousands of entries into memory for processing or similar.

Alternatively you can also tell the ORM to return a dictionary rather than a model instance: https://docs.djangoproject.com/en/4.1/ref/models/querysets/#...

For example, you may get a list of dictionaries with only "field1", "field2" and "field3" from a model like this:

  SomeModel.objects.filter(...).values("field1", "field2", "field3")

  [{"field1": "foo", "field2": "bar", "field3": "baz"}]
Re:Elixir for Humans Who Know Python by spapas82 on Saturday February 25, 2023 @02:10PM (#34939482)
Please notice that nothing stops you from defining a non managed (ie Django migrations won't mess with it) model pointing to the same table and having declared only three of the fields of the original model.
Re:Elixir for Humans Who Know Python by traverseda on Saturday February 25, 2023 @03:02PM (#34939886)
That is more elegant than using a proxy model
Re:Elixir for Humans Who Know Python by spapas82 on Saturday February 25, 2023 @03:27PM (#34940126)
The Django docs also mention that https://docs.djangoproject.com/en/4.1/topics/db/models/#diff...

> If you are mirroring an existing model or database table and don’t want all the original database table columns, use Meta.managed=False.

Re:Elixir for Humans Who Know Python by neillyons on Saturday February 25, 2023 @02:27PM (#34939624)
You can use `managed = False` and `db_table` to have another model pointing to the same table. `managed = False` will stop Django automatically creating schema migrations.

eg.

```

class ReadOnlyUser(models.Model):

    email = models.CharField(max_length=255)

    class Meta:
        db_table = "users"
        managed = False
```
Re:Elixir for Humans Who Know Python by POiNTx on Saturday February 25, 2023 @02:31PM (#34939657)
Just wanted to say thank you for all the great work you've been doing. I'm a recent Elixir/Phoenix convert coming from a couple of years of full time Django and it makes me so happy to see you being interested in the way Django handles models. Imo it's one of the last things I'm struggling leaving behind (together with its tight integration of the Django admin, which you get for free).

I haven't looked close into Ash but to me it seems their approach is interesting and offers a solution, not the way Django does it but it is a solution, although a bit hard to grasp your head around at first. Django models are more simple and straightforward.