-
It seems to me more common for a data model to have one object with lists of children, than to have many objects referring to a single common object. I suspect most people more readily think of "w contains x, y, and z" than "x, y, and z each are contained by w". (Though my phrasing is a little leading.) However, SQL et. al. don't easily support the w-contains-list phrasing (because of having a static number of columns, basically), and the other way around is easier - x, y, z have a reference to w. But, they're more-or-less equivalent. Ormar supports both sides to a certain extent - given a ForeignKey field, it automatically generates a corresponding List on the linked object. But:
The data model I'm building ATM feels like it's halfway inside out - parts of it have relationships defined from the opposite way than makes natural sense to me. Questions:
|
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 4 replies
-
Also - is there a built-in way of doing ordered lists? Or do we have to manually do that, with e.g. an "order" field? Also, question 4 - yeah, this is a FastAPI question. The answer is |
Beta Was this translation helpful? Give feedback.
-
Ok a lot of questions :) Ad.1. No you cannot explicitly define a relation from reverse side, it's done for you when you declare a relation (foreignkey field) from child model like in sql database -> the model that has the actual foreign key side (so many-to-one). But you have this relation (one-to-many) constructed for you by Btw. I think I never saw a orm when you declare a ForeignKey from reverse side. (i.e. in sqlalchemy.orm you can declare relation from any side (or both) but the foreign key is always on child side, and When you want a list from thing to other things: Thing(ormar.Model):
# skip Meta for brevity
id: int = ormar.Integer(primary_key=True)
# you don't declare a "list" fk here
OtherThing(ormar.Model):
# skip Meta for brevity
id: int = ormar.Integer(primary_key=True)
# you declare a fk here and can customize the name present in Thing with related_name
thing: Optional[Thing] = ormar.ForeignKey(Thing, related_name="other_things")
#that way Thing have a field "other_things" which is a list of OtherThings (well actually it's a QuerysetProxy).
# so you can
thing = await Thing(id=1).save()
await thing.other_things.all() # <= will populate other_things etc. All methods of QuerysetProxy are available (check the docs) So you have both directions available and present, just the declaration is from one side. You do not declare relationships etc. like in example in Ad.2. Many to many is, well, a many to many -> so a list (QuerysetProxy) is available from both sides, I guess that's not what you want in this case. Ad.3. For many to many the through model (so the one linking related models) is saved when you call Rule of thumb is that operations that require Ad.4. Yes it's Ad.5. If you want to refresh all data including related models you should just use QuerySet methods: # when you have a existing Thing thing1
thing1 # already exists
# refresh all with queryset
thing1 = await Thing.objects.select_related("other_things").get(pk=thing1.pk)
# now thing1 is refreshed with all related other_things present and only one query was run (join was constructed for you) That way you select which related models to fetch (add them to Note that if you want to issue a separate queries for each of related models you can do it with As for the remark 3 from first 3 points, when you assign a list to other side of fk the relations are created but nothing is saved yet. Remember the rule of thumb that operations that require But, if you want to save children models from parent side you actually can -> that's the BTW. Would appreciate if you split your questions/remarks in more manageable pieces (maybe several discussions even), as i.e. excluding fields in response is not something directly related to one-to-many as the title suggest (and you have points 1-3 two times :D). It will be easier for me to answer and will be easier to find by other users in the future if they have similar questions. |
Beta Was this translation helpful? Give feedback.
-
Re.1 Ok I get your way of thinking, but you would like to just define the relation from other side or some kind of table linking like you described in Java? Re.2 You can, but remember that even if one side of the relation will have one model, so the link is many to one, both sides will return a list on access. So for one model it will be always one element list. Re.5. Yes you can go deep down with As for the list of relations there actually is a method You can open an enhancement issue for Or wait, maybe load all can be actually performed with use of queryset and generated list of relations, hmm, open the issues please and I will think about this. For now let's just leave it as it is in one discussion. |
Beta Was this translation helpful? Give feedback.
Re.1 Ok I get your way of thinking, but you would like to just define the relation from other side or some kind of table linking like you described in Java?
Re.2 You can, but remember that even if one side of the relation will have one model, so the link is many to one, both sides will return a list on access. So for one model it will be always one element list.
Re.5. Yes you can go deep down with
select_related
, you use double underscore in list of joins so when you select fromthing
in your example you canselect_related("other_things__more_things")
with relation names.As for the list of relations there actually is a method
extract_related_names
that returns a set of all field names wi…