> It's more than a preference and it's very important to realise that. It > is not possible for it to work unless you pick a behaviour arbitrarily. > Suppose you have the following objects:
I don't think I've ever said anything about preferences (apologies if I had). It is, IMHO, a design choice as to whether to support something in an API or not. If the semantics of an operation could have several interpretations no clear correct one then it's a design choices as to whether to support that operation or not, and then if deciding to support it which interpretation to go for (with many external and internal factors feeding into that decision). I'm certainly not trying to suggest there's anything wrong with your design choices, I'm just trying to say where I'm coming from and find out where you're coming from! > > A : related to x1, x2, x3 > B : related to x1 and x3 > C : related to nothing. > > One possible "ordering" on the related m2m field here is C, B, A: using > a "result set size" ordering. Two others are "C, A, B" and "A, B, C", > using lexicographic ordering, after ordering the m2m set and with two > alternatives because there are two possibilities for how to order the > empty set. Another possibility is "A, B, C" based on doing it all in one > SQL query and picking the first row (so only the first many-to-many > result will have an effect) and where "A" happens to sort before "B" for > some reason. You happen to want A, B, A, A, B with C either first or > last (plus a couple of permutations depending upon how A and B order > themselves). > > All of these orderings are possible, although your one is probably the > least logical on the grounds that it changes the result set. The problem > is that none of them are particularly canonically correct. I've never commented on how logical my one is - just that it would be the most useful to me and I've given an example of why/what I'd use the behaviour for. The example I've given of how the data would be presented to the user when they request sorting a data table on such a multi value column is a pattern I became familiar with many years ago doing Lotus Notes development work and has been useful as a way of presenting data to users in the applications I've developed over the years in other platforms. I think of the ordering behaviour I'm after as being like a SQL join. In your example above you'd apply all the filtering to give your final set of primary objects and then because sorting is wanted on an attribute of the other class of objects you get the tuples (A,x1),(A,x2),(A,x3),(B,x1),(B,x2),(C,NULL) and you'd then sort those tuples. Regarding none of them being particularly canonically correct surely just means that there's no clear choice, not that none of them could ever be chosen (no clear choice unless other factors from an outside context come into play, for example, a common design pattern emerged in a large number of django applications that would find one of the orderings more useful than the others - in that case it may be the "arbitrary" choice is then to implement that and document that as the behaviour so as to serve the needs of that user base unless there are still compelling reasons not to). > > > > A queryset is going to return one object for each > > > distinct object if you do the equivalent of Contract.objects.all(), not > > > on per many-to-many result. > > > So the .distinct() method is going to become redundant in qf-rf > > because it will effectively always be the case? > > Not at all. I explicitly said the all() query, which is essentially what > you are doing. It's impossible to automatically tell if distinct() will > be wanted/needed or not, so it cannot be removed for the general > filtering case. There are still going to be cases when a query returns > multiple results unless you use distinct(). However, adjusting the > order_by() fragment will not be any of those. It only orders the result > set (at the SQL level), it does not change the result set. Probably my inexperience with django - but I wasn't sure if you meant "any query that starts from .all()" by that which is why I asked. > Queyrset-refactor doesn't introduce new magical powers to querysets. > They will still behave basically the way they did before, only with less > bugs. Your current attempt to order by a many-to-many happened to work > by accident, mostly because I didn't insert all the extra overhead to do > that checking (constructing a query is expensive enough as it is) and I > expected most people would work out that it isn't a well-defined > operation. I do appreciate the effort you're putting into queryset-refactor - I'm just trying to understand what may or may not be possible with it in this area, and now I know, so that's good! I'm not asking for it to support my behaviour, and I've certainly not suggested it should have magical powers. > accessing a many-to-many relation. I suggested one approach to solving > this, which would seem to be the most logical for most situations: if > you're driving off the suppliers, use that as the queryset root, rather > than trying to get multiple results for the contracts. Using extra() > might be a different solution; it depends on your circumstances and > query performance characteristics. For what I'm doing due to the circumstances, driving off suppliers is not the way to go, but thanks for the suggestion. > *All* I am trying to point out in this sub-thread is that expecting the > objects that are returned in the result to change because you put in an > order_by() is mistaken. Using order_by() only orders existing results > and it only does so at the SQL level. The fact that it didn't raise an > error when you passed in a many-to-many doesn't mean that should work. > It just confirms that there are many logically undefined things you can > do in programming and raising an error for every single situation isn't > always going to happen. The solution is "don't do that". You pointed out above various possible response to a request to sort on an m2m, so it's entirely possible for an API user to assume that one of the might happen if they specify an m2m field. If it then looks like one of them is actually happening then they could equally infer it might be supported behaviour. The django documentation isn't complete so I'm finding I'm having to do some trial and error and also reading of code to figure out what's supported when doing anything other than the simple cases in a few areas. This isn't a complaint, just an observation. Anyway sounds like the bottom line is specifying an m2m field in an order_by is not supported by django's queryset as there is no particularly canonically correct behaviour, which is fair enough and as I said in my previous reply I'll find another way of getting the behaviour I want with what is supported (which may involve .extras() or subclasses or something else). I appreciate you taking the time to chat this over - we both have different perspectives and are coming from different places - please take what I'm saying as me trying to put my perspective rather than anything else. I think we've probably talked this one to death now :) Matt --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/django-users?hl=en -~----------~----~----~----~------~----~------~--~---

