Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: get the first object from a filter query or create

In Django, queryset provides a method called get_or_create that either returns an objects or creates an object.

However, like the get method, get_or_create can throw an exception if the query returns multiple objects.

Is there an method to do this elegantly:

objects = Model.manager.filter(params) if len(objects) == 0:    obj = Model.objects.create(params) else:    obj = objects[0] 
like image 743
arustgi Avatar asked May 31 '11 16:05

arustgi


People also ask

How can you retrieve the first element from a query that returns multiple result in Django?

In Django, queryset provides a method called get_or_create that either returns an objects or creates an object. However, like the get method, get_or_create can throw an exception if the query returns multiple objects.

Which can be used to retrieve an object directly instead of a QuerySet?

Retrieving Single Objects from QuerySets We can do this using the get() method. The get() returns the single object directly. Let's see the following example. As we can see in both examples, we get the single object not a queryset of a single object.

What is first () in Django?

In my last Django project, we had a set of helper functions that we used a lot. The most used was helpers. first, which takes a query set and returns the first element, or None if the query set was empty. Instead of writing this: try: object = MyModel.objects.get(key=value) except model.DoesNotExist: object = None.

Does filter query the database Django?

Django does not perform a query when you call . filter(…) . You only construct a QuerySet . It is only when you consume a QuerySet , for example by iterating over it, subscripting, or calling len(…) on the object, you make a query.


2 Answers

get_or_create() is just a convenience function so there's nothing wrong with writing your own, like pavid has shown or

result = Model.objects.filter(field__lookup=value)[0] if not result:    result = Model.objects.create(...) return result 

EDIT As suggested, changed the [:1] slice (which returns a single-entry list) after the filter to [0] (which returns the actual object). The problem with this is it will raise an exception if there is not match to the query.

This will also raise a simliar exception:

Model.objects.filter(field_lookup=value).latest() 

Looking at the question again, I'm not sure whether the original poster is looking to return multiple objects/rows, or just a way to get around raising an exception when retrieving a single object/row.

Here's another option?

results = Model.objects.filter(...) if results.exists():     return results else:     return Model.objects.create(...) 

and another:

result = None try:     result = Model.objects.get(...) except Model.DoesNotExist:     result = Model.objects.create(...) 

There's nothing wrong with raising & catching exceptions!

like image 62
Timmy O'Mahony Avatar answered Sep 22 '22 20:09

Timmy O'Mahony


From django 1.6 there is a convenience method first() that returns the first result in a filter query, or None.

obj = Model.manager.filter(params).first() if obj is None:     obj = Model.objects.create(params) 
like image 44
Sean Avatar answered Sep 22 '22 20:09

Sean