Django: List of valid field lookup operators - django

Does Django have an accessible list of all valid field lookup operators (those that are used by the QuerySet API, e.g. 'contains', 'in', 'lt', etc)?
Thanks
EDIT: For clarification, I mean an in-code list that I can import so, for example, I can check if a given string matches a valid operator.

After searching the source for the operators, it lives in django.db.models.sql.constants.QUERY_TERMS.
A dictionary with lookup strings mapped to None.
'exact' in QUERY_TERMS
Thanks for this! Never would have gone looking, but I could definitely use this.

As of Django 2.1, django.db.models.sql.constants.QUERY_TERMS constant is removed. Per the release notes, Django recommends the get_lookups() method of the Lookup Registration API as an alternative.
For a given field on a model, it can be accessed via:
MyModel._meta.get_field('my_field').get_lookups()

they are in
your_model._meta.fields[index].class_lookups
It’s a dict.

Related

Django-dsl-drf Exclude phrase query

I am working on integrating Elastic Search in my existing Django REST application. I am using the django-dsl-drf module provided in the link below:
https://django-elasticsearch-dsl-drf.readthedocs.io/
In their documentation 'exclude' query param is provided. But the query only when we provide the full field value.
search-url?exclude=<field-value
For eg: If I have a value 'Stackoverflow' in field 'name'. I'll have to provide query param a
?name__exclude=Stackoverflow to exclude records having 'Stackoverflow' as name in the result. I would like to implement a search in such a way that when I provide 'over', I need to exclude these records, similar to ?name__exclude=over
I checked the above tutorial, but I couldn't find it. Is there any work around so that I can exclude records, fields containing terms instead of providing full field value, which is also case-insensitive.
Thanks a lot.
Using the contains functional filter, you can target documents that have their name field value containing the characters over anywhere in their terms:
?name__contains=over
However, as far as I know, there is no way to negate that filter in django-dsl-drf. You can create an issue requesting that feature, though, because odds are high that you're not the only who needs that, since it's a pretty common way of searching.

Custom index name in South/Django

Is there a way to set our own index name in Django models? Currently, the migration scripts would create a name in format [table_name]_9fcb4ba3 and I'd like to have the name more descriptive, i.e. [table_name]_[column_name] or so.
On the Django's Model Field Reference page, it doesn't seem to have such option (https://docs.djangoproject.com/en/1.8/ref/models/fields/#db-index)
For anyone finding its way from Google - seems Django 1.11 allows you now to have a custom name for indexes. Following the documentation as described here:
Index.name
The name of the index. If name isn’t provided Django will auto-generate a name. For compatibility with different databases, index names cannot be longer than 30 characters and shouldn’t start with a number (0-9) or underscore (_).
There is no way of customizing the name for indexes as these are generated by hashing (the index name calculation uses some hashing techniques)

Django: can I add a list of new model instances to the database via a single method call?

If I am creating a list of new model objects based on some form input, e.g.,
new_items = []
for name, value in self.cleaned_data.items():
if name.startswith('content_item_'):
new_items.append(ContentItem(item=value))
# can I add the entire new_items list to the database in one swoop?
I'm having trouble finding whether this in the docs, which generally refer to creating objects one at a time via the .save() method. But one-at-a-time seems inefficient when you have a whole list of objects to add.
Thanks!
https://docs.djangoproject.com/en/dev/ref/models/querysets/#bulk-create
Edit: Unfortunately this is not on 1.3
Original Answer
Thank god for bulk_create!
You could then do something like this:
ContentItem.objects.bulk_create(new_items)
For those too lazy to click the link, here is the example from the docs:
>>> Entry.objects.bulk_create([
... Entry(headline="Django 1.0 Released"),
... Entry(headline="Django 1.1 Announced"),
... Entry(headline="Breaking: Django is awesome")
... ])
I believe Brandon Konkle's reply to a similar question is still valid: Question about batch save objects in Django
In summary: Sadly, no, you'll have to use django.db.cursor with a manual query to do so. If the dataset is small, or the performance is of less importance though, looping through isn't really THAT bad, and is the simplest solution.
Also, see this ticket: https://code.djangoproject.com/ticket/661

django-non rel and dbindexer ordering property

I am working on a test project using django-nonrel.
After enabling the admin interface and adding some entities to the database, I added a search_field to the ModelAdmin class. As I tried to search I got the following error:
DatabaseError: Lookup type 'icontains' isn't supported
In order to fix this, I added an index like this:
from models import Empresa
from dbindexer.api import register_index
register_index(Empresa, {'nombre': 'icontains'})
But now I am getting the following error:
First ordering property must be the same as inequality filter property, if specified for this query; received key, expected idxf_nombre_l_icontains
Am I trying to do something that is not supported by django-nonrel and dbindex yet?
Thanks in advance for any help
I have the same problem (on another case), know the cause of it, but currently have no solution.
It is because of GAE's database limitation in which if a query contain an inequality comparison, that is ' < , > , >= ' or something like that, any ordering of any member of the entities (other than the member that use the inequality comparison) must be preceded by an ordering of the member with inequality comparison first.
If we are directly using GAE's database, this limitation can easily be overcome by first set the order by the member that use the inequality first, than sort with whatever you want to sort.
Unfortunately, the django-nonrel and djangoappengine's database wrapper seems to be unable to do that (I've tried the order by first technique using django model, still error, maybe it's just me), not to mention the use of dbindexer as the wrapper of djangoappengine.db which itself is a wrapper of GAE's database......
Bottomline, debugging can be a hell for this mess. You may want to use GAE datastore directly just for this case, or wait for djangoappengine team to come up with better alternative.
I kind of fixed it by changing the ordering property in the ModelAdmin subclass:
class EmpresaAdmin(admin.ModelAdmin):
search_fields = ('nombre',)
#order by the atribute autogenerated by dbindex
ordering = ('idxf_nombre_l_icontains',)
Does anyone know a better way to fix this?

GAE: Using properties for keys() in ModelChoiceProperty boxes

I have a model User which appears as a ReferenceProperty in another model, Group.
When I create a form for Group, using Meta, the form's values contain lots of generated strings. I'd like to stop this, and use the username field of User instead.
I already define a key_name. However, str(user.key()) still gives a generated string. I could override key(), but that would be bad. Any thoughts? I want the Group form to use usernames for the ModelChoiceProperty values, and the form to still validate and save. Currently the form prints the string value of key(), according to the source.
The key() in a db.model is an object that contains a bunch of different information, including the kind of object, its name and an id.
So I'm thinking that key().name() would return what you want?
In the docs, it describes all of this.
Having thought about this a little bit harder, I think the correct answer is "don't do that". The Entitys will still have keys, and those keys will correspond to a generated string. The form would have to be hacked to make it work too, so this looks like a ton of hassle to essentially make the code a tiny bit prettier looking.