#Is there a way to re-use a model instance when using it to filter for a related model via filter

27 messages · Page 1 of 1 (latest)

queen quest
#

Given

event = Event.objects.filter(location=loc).first()

obviously loc and event.location refer to the same row in the db

event.location == loc

but they refer to separate instances

id(event.location) != id(loc)  # they're separate instances. 

this can be solve with a basic assign statement

event.location = loc

But I'm wondering if there's a way to change the default behavior. so that the queryset returned by a filter re-uses any instances that were passed to it. Perhaps that requires a lot of overhead, I haven't looked into it too deeply myself. I thought I'd post here first in case I'm missing something obvious.

thanks!

#

Is there a way to re-use a model instance when using it to filter for a related model via filter

wheat siren
#

What would be the motivation for the two objects to refer to the same? Ultimately, django taps into the object and plucks the primary key from it. So, filter(location=loc) is similar to filter(location_id=loc.id)

queen quest
#

there are some areas of my code where the loc used to filter for the event has changes that are not yet saved to the database, or that are transient and only exist as a value on that instance. I want the event to be able to reference those values internally

wheat siren
#

I'm not familiar with a way to have said expectation done by default, sorry.

dry kettle
#

so you could go for sth like loc.event/s directly?

queen quest
#

locations can have many events

dry kettle
#

Can you share all three models? It will be easier for us to understand the case

queen quest
#
class Location(TimeStampedModel):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    ...  # nothing relevant to events
class Event(models.Model):
    location = ForeignKey(
        "location.Location", on_delete=models.CASCADE
    )
    ...
dry kettle
#

In that case, I'm missing how event.location = loc changes things. Having id(a) == id(b) doesn't affect how the orm filters work; or I'm missing the question too

queen quest
#
setattr(loc, "random_attr", True)
event = Event.objects.filter(location=loc).first()
getattr(event.location, "random_attr", None) == None

vs

setattr(loc, "random_attr", True)
event = Event.objects.filter(location=loc).first()
event.location = loc
getattr(event.location, "random_attr", None) == True
dry kettle
#

Oh okay so you are trying to attach non-ORM values and keep them there, am i right?

queen quest
#

I'm wondering if I can have the ORM assign loc as the .location instance for me

#

since I passed it into filter

#

instead of instantiating a new location

dry kettle
#

Nope, ORM doesn't touch non-field stuff there

#

Also, I wouldn't recommend passing non-field or non-annotated attributes to the ORM like that, it will be lost somewhere

queen quest
#

location instantiating is walled off from the filter call? I guses that makes sense

dry kettle
#

think it like this

#

nothing else is used, touched or kept

queen quest
#

I'll accept my use case as non-standard and probably not worth adding, but will maintain it would be a nice feature in a perfect world of infinite time

#

thanks for the help. I can rest easy knowing I'm not missing anything obvious

dry kettle
#

You are welcome 🌻

naive shoal
#

@queen quest I think if you use the reverse accessor (location.event_set.first() or something like that) you'll find that the location object is used directly. Search the Django source for _known_related_objects to find out how this is achieved. This is very internal and not documented and not to be relied upon of course, but I think it works fine.

#

That being said, I have been using and even manipulating this attribute in django-content-editor since 2016 and it has worked fine for me.