django models - instance method to check if a model with matching attributes already exists in database

django models - instance method to check if a model with matching attributes already exists in database



I am using django 2.0.8 and Python 3.5 in a project.



I want to write an instance method on class Foo that checks to ensure that a "similar record" (i.e. same attributes) does not exist in the database.


Foo



I am aware that I could use R.I (referential integrity) rules in the DB, to enforce this, but I want to push this responsibility to the model, not the DB layer.



Here is the relevant portion of my code:


class Foo(models.Model):
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')

# Model specific fields
user = models.ForeignKey(settings.AUTH_USER_MODEL, blank=False, null=False, default=1, on_delete = models.CASCADE)

def is_available(self):
return not models.Manager().get_queryset().filter(
content_type=self.content_type,
object_id=self.object_id,
user=self.user).exists()



My question is how to correctly implement the instance method is_available(). As it currently stands, when I invoke that method, I get the following error message (note Foo has been initialised correctly - omitted for sake of brevity):


is_available()


>>> foo.is_available()
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/path/to/project_base/myapp/models.py", line 57, in is_available
user=self.user).exists()
File "/path/to/env/lib/python3.5/site-packages/django/db/models/query.py", line 836, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/path/to/env/lib/python3.5/site-packages/django/db/models/query.py", line 854, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/path/to/env/lib/python3.5/site-packages/django/db/models/sql/query.py", line 1253, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "/path/to/env/lib/python3.5/site-packages/django/db/models/sql/query.py", line 1277, in _add_q
split_subq=split_subq,
File "/path/to/env/lib/python3.5/site-packages/django/db/models/sql/query.py", line 1153, in build_filter
lookups, parts, reffed_expression = self.solve_lookup_type(arg)
File "/path/to/env/lib/python3.5/site-packages/django/db/models/sql/query.py", line 1015, in solve_lookup_type
_, field, _, lookup_parts = self.names_to_path(lookup_splitted, self.get_meta())
File "/path/to/env/lib/python3.5/site-packages/django/db/models/sql/query.py", line 284, in get_meta
return self.model._meta
AttributeError: 'NoneType' object has no attribute '_meta'





Please show the full traceback when including errors, so that it's clear where the error is occuring. The filter() method returns a queryset, so temp is None will never be True. Perhaps you want to could test temp.exists() instead.
– Alasdair
Sep 4 '18 at 19:54


filter()


temp is None


True


temp.exists()





Maybe also show what code you are using to call the method. Have you tried: return Foo.objects.filter(content_type=self.content_type, object_id=self.object_id, user=self.user).exists() Also, I don't think you can just create a new Manager, how should it know which model you want the query to be associated with? It has to be assigned to a model property. (or simply use Foo.objects)
– herbert
Sep 4 '18 at 20:04


return Foo.objects.filter(content_type=self.content_type, object_id=self.object_id, user=self.user).exists()


Foo.objects





Question edited to reflect changes requested
– Homunculus Reticulli
Sep 4 '18 at 21:08




1 Answer
1



You can't use a generic Manager() to do this, because it will not have the context of the model that you're trying to query. You can just use the model's defined manager (objects) instead - something like this:


Manager()


objects


def is_available(self):
return Foo.objects.filter(
content_type=self.content_type,
object_id=self.object_id,
user=self.user
).exists()



Note that doing this at the model level means you're not safe from race conditions, and it is still possible to end up saving "duplicate" objects to the database. Also,the result will change depending on whether the instance (self) has been saved or not - which might be an argument for doing this in a class method instead.


self



Thanks for contributing an answer to Stack Overflow!



But avoid



To learn more, see our tips on writing great answers.



Some of your past answers have not been well-received, and you're in danger of being blocked from answering.



Please pay close attention to the following guidance:



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)