Fast and Easy way to check if an instance of an Model exists in the Database

4,243 views
Skip to first unread message

Johannes Schneider

unread,
Jan 16, 2014, 8:27:09 AM1/16/14
to django...@googlegroups.com
Hi List,
I need to check, if a given instance of a Model already exists in the
Database. I cannot check 'instance.pk is None', because there are
manually given PKs (no discussion about this plz).

Up to now I check if 'instance._state.adding' is true. But I don't like
this solution.
Checking 'InstanceModel.objects.exists(pk=self.pk)' generates too much
queries, so this is not acceptable in my case.

bg
Johannes


--
Johannes Schneider
Webentwicklung
johannes....@galileo-press.de
Tel.: +49.228.42150.xxx

Galileo Press GmbH
Rheinwerkallee 4 - 53227 Bonn - Germany
Tel.: +49.228.42.150.0 (Zentrale) .77 (Fax)
http://www.galileo-press.de/

Gesch�ftsf�hrer: Tomas Wehren, Ralf Kaulisch, Rainer Kaltenecker
HRB 8363 Amtsgericht Bonn

Erik Cederstrand

unread,
Jan 16, 2014, 10:04:22 AM1/16/14
to Django Users
Den 16/01/2014 kl. 14.27 skrev Johannes Schneider <johannes....@galileo-press.de>:

> Hi List,
> I need to check, if a given instance of a Model already exists in the Database. I cannot check 'instance.pk is None', because there are manually given PKs (no discussion about this plz).
>
> Up to now I check if 'instance._state.adding' is true. But I don't like this solution.
> Checking 'InstanceModel.objects.exists(pk=self.pk)' generates too much queries, so this is not acceptable in my case.

Can you elaborate on “too much queries”? exists() is supposed to be the cheapest way of checking if the object exists. It seems like you want to check the database, without actually checking the database…

If you want to check a large number of objects at the same time, just do something like:

InstanceModel.objects.filter(id__in=(your, list, of, PKs)).values_list('id', flat=True)

to get all pre-existing PKs in one query.

Erik

Johannes Schneider

unread,
Jan 16, 2014, 11:50:39 AM1/16/14
to django...@googlegroups.com
The point is, I have to distinguish between an instance which is
created, but its save method is not yet called. And an instance coming
from the database via a manager.

bg,
Johannes

On 16.01.2014 16:04, Erik Cederstrand wrote:
> Den 16/01/2014 kl. 14.27 skrev Johannes Schneider <johannes....@galileo-press.de>:
>
>> Hi List,
>> I need to check, if a given instance of a Model already exists in the Database. I cannot check 'instance.pk is None', because there are manually given PKs (no discussion about this plz).
>>
>> Up to now I check if 'instance._state.adding' is true. But I don't like this solution.
>> Checking 'InstanceModel.objects.exists(pk=self.pk)' generates too much queries, so this is not acceptable in my case.
>
> Can you elaborate on �too much queries�? exists() is supposed to be the cheapest way of checking if the object exists. It seems like you want to check the database, without actually checking the database�
>
> If you want to check a large number of objects at the same time, just do something like:
>
> InstanceModel.objects.filter(id__in=(your, list, of, PKs)).values_list('id', flat=True)
>
> to get all pre-existing PKs in one query.
>
> Erik
>


--
Johannes Schneider
Webentwicklung
johannes....@galileo-press.de
Tel.: +49.228.42150.xxx

Galileo Press GmbH
Rheinwerkallee 4 - 53227 Bonn - Germany
Tel.: +49.228.42.150.0 (Zentrale) .77 (Fax)
http://www.galileo-press.de/

Gesch�ftsf�hrer: Tomas Wehren, Ralf Kaulisch, Rainer Kaltenecker
HRB 8363 Amtsgericht Bonn

Martin Marrese

unread,
Jan 16, 2014, 11:53:01 AM1/16/14
to django...@googlegroups.com
On Thu, Jan 16, 2014 at 1:50 PM, Johannes Schneider <johannes....@galileo-press.de> wrote:
The point is, I have to distinguish between an instance which is created, but its save method is not yet called. And an instance coming from the database via a manager.

bg,
Johannes

--
Martin Marrese
mar...@gmail.com
+54 911 5112 9448

Javier Guerra Giraldez

unread,
Jan 16, 2014, 12:03:51 PM1/16/14
to django...@googlegroups.com
On Thu, Jan 16, 2014 at 11:50 AM, Johannes Schneider
<johannes....@galileo-press.de> wrote:
> The point is, I have to distinguish between an instance which is created,
> but its save method is not yet called. And an instance coming from the
> database via a manager.


AFAIK, if it has a 'pk' property, it has been saved.

--
Javier

Johannes Schneider

unread,
Jan 16, 2014, 12:22:36 PM1/16/14
to django...@googlegroups.com
No, just if you use auto generated PKs. Exactly this is the point. We
use manually generated PKs, so can not use this check.
Johannes Schneider
Webentwicklung
johannes....@galileo-press.de
Tel.: +49.228.42150.xxx

Galileo Press GmbH
Rheinwerkallee 4 - 53227 Bonn - Germany
Tel.: +49.228.42.150.0 (Zentrale) .77 (Fax)
http://www.galileo-press.de/

Geschäftsführer: Tomas Wehren, Ralf Kaulisch, Rainer Kaltenecker
HRB 8363 Amtsgericht Bonn

Johannes Schneider

unread,
Jan 16, 2014, 12:23:38 PM1/16/14
to django...@googlegroups.com
This could be a way to it, but we need this information while handling
the Pre_save singal. So this does not work too.

On 16.01.2014 17:53, Martin Marrese wrote:
> On Thu, Jan 16, 2014 at 1:50 PM, Johannes Schneider
> <johannes....@galileo-press.de
> <mailto:johannes....@galileo-press.de>> wrote:
>
> The point is, I have to distinguish between an instance which is
> created, but its save method is not yet called. And an instance
> coming from the database via a manager.
>
> bg,
> Johannes
>
>
> Perhaps get_or_create
> (https://docs.djangoproject.com/en/dev/ref/models/querysets/#get-or-create)
> ?
>
> Mart�n
>
> --
> Martin Marrese
> mar...@gmail.com <mailto:mar...@gmail.com>
> +54 911 5112 9448
>
> --
> You received this message because you are subscribed to the Google
> Groups "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to django-users...@googlegroups.com.
> To post to this group, send email to django...@googlegroups.com.
> Visit this group at http://groups.google.com/group/django-users.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-users/CAKQdVACvdMxrQERzB18dBDXPT4bDMXWOuV5NXpkE68eX-rfL9A%40mail.gmail.com.
> For more options, visit https://groups.google.com/groups/opt_out.


--
Johannes Schneider
Webentwicklung
johannes....@galileo-press.de
Tel.: +49.228.42150.xxx

Galileo Press GmbH
Rheinwerkallee 4 - 53227 Bonn - Germany
Tel.: +49.228.42.150.0 (Zentrale) .77 (Fax)
http://www.galileo-press.de/

Gesch�ftsf�hrer: Tomas Wehren, Ralf Kaulisch, Rainer Kaltenecker
HRB 8363 Amtsgericht Bonn

Erik Cederstrand

unread,
Jan 17, 2014, 3:35:40 AM1/17/14
to Django Users
Den 16/01/2014 kl. 17.50 skrev Johannes Schneider <johannes....@galileo-press.de>:

> The point is, I have to distinguish between an instance which is created, but its save method is not yet called. And an instance coming from the database via a manager.

Okay, then create an instance variable on the model instances when you create them manually. Something like this:

obj = InstanceModel()
obj.pk = 123
obj.manually_created = True

Then have your save() method check for this variable:

def save(self, *args, **kwargs):
if getattr(self, ‘manually_created’, False):
# Was created manually. Do something
else:
# From database. Do something else
super(self, InstanceModel).save(*args, **kwargs)
del obj.manually_created


Erik

Tom Evans

unread,
Jan 17, 2014, 8:39:36 AM1/17/14
to django...@googlegroups.com
On Thu, Jan 16, 2014 at 5:23 PM, Johannes Schneider
<johannes....@galileo-press.de> wrote:
> This could be a way to it, but we need this information while handling the
> Pre_save singal. So this does not work too.

Abuse the django model instance's internals and look to see what
database this instance was loaded from - if it is None, it hasn't come
from the database.

This is highly fragile - using an undocumented API that I know has
changed in recent versions. Personally I would test that the pk does
not exist in the database (and buy faster hardware.)


>>> u=User.objects.get(id=1)
>>> u2=User()
>>> u._state.db
'default'
>>> u2._state.db
>>>

Cheers

Tom

Johannes Schneider

unread,
Jan 20, 2014, 3:12:43 AM1/20/14
to django...@googlegroups.com
thnx for this suggestion. we use '_state.adding' now. Is there an
advantage of using '_state.database'?

bg,
Johannes
--
Johannes Schneider
Webentwicklung
johannes....@galileo-press.de
Tel.: +49.228.42150.xxx

Galileo Press GmbH
Rheinwerkallee 4 - 53227 Bonn - Germany
Tel.: +49.228.42.150.0 (Zentrale) .77 (Fax)
http://www.galileo-press.de/

Geschäftsführer: Tomas Wehren, Ralf Kaulisch, Rainer Kaltenecker
HRB 8363 Amtsgericht Bonn

Kelly Nicholes

unread,
Jan 20, 2014, 10:25:33 AM1/20/14
to django...@googlegroups.com
Wait-- Why aren't you using exists()? Don't even check the pk. Model.query.exists() was made for this.

Johannes Schneider

unread,
Jan 20, 2014, 11:13:15 AM1/20/14
to django...@googlegroups.com
I don't do, because I don't want do to have a query against the database.

On 20.01.2014 16:25, Kelly Nicholes wrote:
> Wait-- Why aren't you using exists()? Don't even check the pk. Model.query.exists() was made for this.
>


Avraham Serour

unread,
Jan 20, 2014, 12:21:23 PM1/20/14
to django...@googlegroups.com
well you have a problem then, the database is the one holding the data, if you want to know if the data exists will would need to ask the one responsible for it, if not the DB then who?

you could keep a copy in memory but then you will have two problems. are you actually having problems with exists() or is this just premature optimization?


On Mon, Jan 20, 2014 at 6:13 PM, Johannes Schneider <johannes....@galileo-press.de> wrote:
I don't do, because I don't want do to have a query against the database.


On 20.01.2014 16:25, Kelly Nicholes wrote:
Wait-- Why aren't you using exists()?  Don't even check the pk.  Model.query.exists() was made for this.



--
Johannes Schneider
Webentwicklung
johannes.schneider@galileo-press.de

Tel.: +49.228.42150.xxx

Galileo Press GmbH
Rheinwerkallee 4 - 53227 Bonn - Germany
Tel.: +49.228.42.150.0 (Zentrale) .77 (Fax)
http://www.galileo-press.de/

Geschäftsführer: Tomas Wehren, Ralf Kaulisch, Rainer Kaltenecker
HRB 8363 Amtsgericht Bonn

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.

To post to this group, send email to django...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.

Johannes Schneider

unread,
Jan 21, 2014, 2:58:33 AM1/21/14
to django...@googlegroups.com
maybe I I formulated it not precise enough.
I need to check if some instance of a model comes from some database
query (e.g. via get(..)) or is instanciated 'by hand'. and not jet
written to the database.
In this case I don't need to know, if there is an related object (e.g.
with the same pk or same values for its attributes) in the database.

bg,
Johannes

On 20.01.2014 18:21, Avraham Serour wrote:
> well you have a problem then, the database is the one holding the data,
> if you want to know if the data exists will would need to ask the one
> responsible for it, if not the DB then who?
>
> you could keep a copy in memory but then you will have two problems. are
> you actually having problems with exists() or is this just premature
> optimization?
>
>
> On Mon, Jan 20, 2014 at 6:13 PM, Johannes Schneider
> <johannes....@galileo-press.de
> <mailto:johannes....@galileo-press.de>> wrote:
>
> I don't do, because I don't want do to have a query against the
> database.
>
>
> On 20.01.2014 16:25, Kelly Nicholes wrote:
>
> Wait-- Why aren't you using exists()? Don't even check the pk.
> Model.query.exists() was made for this.
>
>
>
> --
> Johannes Schneider
> Webentwicklung
> johannes.schneider@galileo-__press.de
> <mailto:johannes....@galileo-press.de>
> Tel.: +49.228.42150 <tel:%2B49.228.42150>.xxx
>
> Galileo Press GmbH
> Rheinwerkallee 4 - 53227 Bonn - Germany
> Tel.: +49.228.42.150.0 <tel:%2B49.228.42.150.0> (Zentrale) .77 (Fax)
> http://www.galileo-press.de/
>
> Gesch�ftsf�hrer: Tomas Wehren, Ralf Kaulisch, Rainer Kaltenecker
> HRB 8363 Amtsgericht Bonn
>
> --
> You received this message because you are subscribed to the Google
> Groups "Django users" group.
> To unsubscribe from this group and stop receiving emails from it,
> send an email to django-users+unsubscribe@__googlegroups.com
> <mailto:django-users%2Bunsu...@googlegroups.com>.
> To post to this group, send email to django...@googlegroups.com
> <mailto:django...@googlegroups.com>.
> Visit this group at http://groups.google.com/__group/django-users
> <http://groups.google.com/group/django-users>.
> To view this discussion on the web visit
> https://groups.google.com/d/__msgid/django-users/52DD4B1B.__9020508%40galileo-press.de
> <https://groups.google.com/d/msgid/django-users/52DD4B1B.9020508%40galileo-press.de>.
>
> For more options, visit https://groups.google.com/__groups/opt_out
> <https://groups.google.com/groups/opt_out>.
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to django-users...@googlegroups.com.
> To post to this group, send email to django...@googlegroups.com.
> Visit this group at http://groups.google.com/group/django-users.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-users/CAFWa6tLNikRya2Fyji_WSgFd9QE9qDNmrhNEsUDj2hQd2t7ieQ%40mail.gmail.com.
> For more options, visit https://groups.google.com/groups/opt_out.


--
Johannes Schneider
Webentwicklung
johannes....@galileo-press.de
Tel.: +49.228.42150.xxx

Galileo Press GmbH
Rheinwerkallee 4 - 53227 Bonn - Germany
Tel.: +49.228.42.150.0 (Zentrale) .77 (Fax)
http://www.galileo-press.de/

Gesch�ftsf�hrer: Tomas Wehren, Ralf Kaulisch, Rainer Kaltenecker
HRB 8363 Amtsgericht Bonn

Erik Cederstrand

unread,
Jan 21, 2014, 3:16:22 AM1/21/14
to Django Users
Den 21/01/2014 kl. 08.58 skrev Johannes Schneider <johannes....@galileo-press.de>:

> maybe I I formulated it not precise enough.
> I need to check if some instance of a model comes from some database query (e.g. via get(..)) or is instanciated 'by hand'. and not jet written to the database.
> In this case I don't need to know, if there is an related object (e.g. with the same pk or same values for its attributes) in the database.

Okay. Sounds like your best bet is to either roll your own, or use the undocumented API as suggested by Tom Evans.

Either way, make sure to write tests so this doesn’t break when you upgrade Django.

Erik

Avraham Serour

unread,
Jan 21, 2014, 4:07:28 AM1/21/14
to django...@googlegroups.com
wouldn't checking for the presence of an id enough? as far as I know instantiated objects don't have id's


--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users...@googlegroups.com.
To post to this group, send email to django...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.

Johannes Schneider

unread,
Jan 21, 2014, 4:55:55 AM1/21/14
to django...@googlegroups.com
yes, but the problem is that we manually give them a pk.

Maye it's the best to reduce the question to the following:
Which (undocumented) field is better for this case?
* instance._state.db (checking if this is None)
* instance_state.adding (checking for True)

bg,
Johannes


On 21.01.2014 10:07, Avraham Serour wrote:
> wouldn't checking for the presence of an id enough? as far as I know
> instantiated objects don't have id's
>
>
> On Tue, Jan 21, 2014 at 10:16 AM, Erik Cederstrand
> <erik+...@cederstrand.dk <mailto:erik+...@cederstrand.dk>> wrote:
>
> Den 21/01/2014 kl. 08.58 skrev Johannes Schneider
> <johannes....@galileo-press.de
> <mailto:johannes....@galileo-press.de>>:
>
> > maybe I I formulated it not precise enough.
> > I need to check if some instance of a model comes from some
> database query (e.g. via get(..)) or is instanciated 'by hand'. and
> not jet written to the database.
> > In this case I don't need to know, if there is an related object
> (e.g. with the same pk or same values for its attributes) in the
> database.
>
> Okay. Sounds like your best bet is to either roll your own, or use
> the undocumented API as suggested by Tom Evans.
>
> Either way, make sure to write tests so this doesn�t break when you
> upgrade Django.
>
> Erik
>
> --
> You received this message because you are subscribed to the Google
> Groups "Django users" group.
> To unsubscribe from this group and stop receiving emails from it,
> send an email to django-users...@googlegroups.com
> <mailto:django-users%2Bunsu...@googlegroups.com>.
> To post to this group, send email to django...@googlegroups.com
> <mailto:django...@googlegroups.com>.
> Visit this group at http://groups.google.com/group/django-users.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-users/78B3DC94-CBFC-4F38-A35C-73F54CAB572A%40cederstrand.dk.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>
> --
> You received this message because you are subscribed to the Google
> Groups "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to django-users...@googlegroups.com.
> To post to this group, send email to django...@googlegroups.com.
> Visit this group at http://groups.google.com/group/django-users.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-users/CAFWa6t%2Brm9REWaWUTqZHd4Wv3Pw212RLGSh89%2BWJwC7NFNM%3DqQ%40mail.gmail.com.
> For more options, visit https://groups.google.com/groups/opt_out.


--
Johannes Schneider
Webentwicklung
johannes....@galileo-press.de
Tel.: +49.228.42150.xxx

Galileo Press GmbH
Rheinwerkallee 4 - 53227 Bonn - Germany
Tel.: +49.228.42.150.0 (Zentrale) .77 (Fax)
http://www.galileo-press.de/

Gesch�ftsf�hrer: Tomas Wehren, Ralf Kaulisch, Rainer Kaltenecker
HRB 8363 Amtsgericht Bonn

Avraham Serour

unread,
Jan 21, 2014, 6:59:20 AM1/21/14
to django...@googlegroups.com
pk is not necessarily id, in any case if you are the one adding it then you already know that the object didn't come from the db, in order to check that later I would add an attribute to the object and check it's presence, if not present it means it came from the db.


On Tue, Jan 21, 2014 at 11:55 AM, Johannes Schneider <johannes....@galileo-press.de> wrote:
yes, but the problem is that we manually give them a pk.

Maye it's the best to reduce the question to the following:
Which (undocumented) field is better for this case?
* instance._state.db (checking if this is None)
* instance_state.adding (checking for True)

bg,
Johannes



On 21.01.2014 10:07, Avraham Serour wrote:
wouldn't checking for the presence of an id enough? as far as I know
instantiated objects don't have id's


On Tue, Jan 21, 2014 at 10:16 AM, Erik Cederstrand
<erik+...@cederstrand.dk <mailto:erik+lists@cederstrand.dk>> wrote:

    Den 21/01/2014 kl. 08.58 skrev Johannes Schneider


     > maybe I I formulated it not precise enough.
     > I need to check if some instance of a model comes from some
    database query (e.g. via get(..)) or is instanciated 'by hand'. and
    not jet written to the database.
     > In this case I don't need to know, if there is an related object
    (e.g. with the same pk or same values for its attributes) in the
    database.

    Okay. Sounds like your best bet is to either roll your own, or use
    the undocumented API as suggested by Tom Evans.

    Either way, make sure to write tests so this doesn’t break when you

    upgrade Django.

    Erik

    --
    You received this message because you are subscribed to the Google
    Groups "Django users" group.
    To unsubscribe from this group and stop receiving emails from it,
    <mailto:django-users%2Bunsu...@googlegroups.com>.

    To post to this group, send email to django...@googlegroups.com

    Visit this group at http://groups.google.com/group/django-users.
    To view this discussion on the web visit
    https://groups.google.com/d/msgid/django-users/78B3DC94-CBFC-4F38-A35C-73F54CAB572A%40cederstrand.dk.
    For more options, visit https://groups.google.com/groups/opt_out.


--
You received this message because you are subscribed to the Google
Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send

To post to this group, send email to django...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.
To view this discussion on the web visit


--
Johannes Schneider
Webentwicklung
johannes.schneider@galileo-press.de

Tel.: +49.228.42150.xxx

Galileo Press GmbH
Rheinwerkallee 4 - 53227 Bonn - Germany
Tel.: +49.228.42.150.0 (Zentrale) .77 (Fax)
http://www.galileo-press.de/

Geschäftsführer: Tomas Wehren, Ralf Kaulisch, Rainer Kaltenecker
HRB 8363 Amtsgericht Bonn

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.

To post to this group, send email to django...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-users.

Erik Cederstrand

unread,
Jan 21, 2014, 8:06:10 AM1/21/14
to Django Users
Den 21/01/2014 kl. 10.55 skrev Johannes Schneider <johannes....@galileo-press.de>:

> yes, but the problem is that we manually give them a pk.
>
> Maye it's the best to reduce the question to the following:
> Which (undocumented) field is better for this case?
> * instance._state.db (checking if this is None)
> * instance_state.adding (checking for True)

Pick whichever works for you. But make sure to write tests for this, so it still works when you upgrade Django.

Erik

Johannes Schneider

unread,
Jan 21, 2014, 8:29:46 AM1/21/14
to django...@googlegroups.com
thnx guys for all that input.
--
Johannes Schneider
Webentwicklung
johannes....@galileo-press.de
Tel.: +49.228.42150.xxx

Galileo Press GmbH
Rheinwerkallee 4 - 53227 Bonn - Germany
Tel.: +49.228.42.150.0 (Zentrale) .77 (Fax)
http://www.galileo-press.de/

Gesch�ftsf�hrer: Tomas Wehren, Ralf Kaulisch, Rainer Kaltenecker
HRB 8363 Amtsgericht Bonn
Reply all
Reply to author
Forward
0 new messages