> 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 be larger than xyz".
filter() can then look into its argument list and construct the filter criteria from the passed Field objects instead of the key value pairs as it does now.
SQLalchemy does that. One advantage of the Django syntax is that it can be (pretty much) directly dropped into a query string on any admin page or DRF query and filter the results. E.g. the admin page for all the events after noon today:
Being able to do ad-hoc queries using the same paradigm your app queries are written in, and then pass urls around with those queries included (e.g., quick one-off reports or answers to client questions) is so helpful.if self._midnight(today) returns a datetime object, than:
will evaluate to: While will evaluate to: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:
This gives: You can make python return arbitrary values for comparisons by overriding __gt__ (and lt, eq) on the first operand (which we control here since it is a Field class), it doesn't have to be a bool.Edit:
You can even make a little adapter to use this with the current filter system if you really want to:
This printsend__gt = 2024-01-01 00:00:00
If you change an operation that is meant to return a Boolean to return anything else, you are insta fired.
I would have agreed with this, and then they did the `pathlib.Path` bit of cuteness with the `/` operator: https://github.com/python/cpython/blob/5afbb60e0283caaf34990...
And despite my misgivings, it’s really ergonomic.
If you divide a Path by another Path, you get a Path. If you compare two Paths, you get a Boolean. It is not really the same.
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.
You mean like the numpy authors that let the comparison operators return arrays?
Also, apparently SQLAlchemy does exactly what I proposed so apparently they are erring in their ways too.
I honestly don’t find it that bad.
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.
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")`).
Yeah, but that's different from the operator. It's a different way of thinking about it. Maybe that's the reason they used dou le underscores for everything, to keep it consistent.