Postgres select function in Django annotation - django

I have old database and need custom select.
in sql i can use:
SELECT x(geometry) FROM table
but I dont know how to force x() function in django select.

You can create a custom function using Expressions.
class GeoX(Func):
function = 'X'
MyModel.objects.annotate(x=GeoX('field'))
This will result in the geometry X function being invoked and it's result being annotated to a field labeled x in your model. However this is the inferior solution. The better solution is to install geodjango. That provides full access to almost every single function in PostGIS. Also works with spatialite and msyql spatial extensions.

I managed to solve problem using Func()
Func(F('geometry'), function='x')

Related

GeoDjango + Postgis missing functions

So I've been using a Postgres database with the extension Postgis installed, and then using a Django setup to draw spatial data on a Leaflet OpenStreetMap. It has been a bit difficult translating my sql queries to the database functionality that Django is using whenever you're communicating with your database. Often I seem to be missing Postgis functions such as ST_LineCrossingDirection or ST_FrechetDistance.
How do I get to use those functions along with .annotate and .filter from Django without having to write custom sql queries and executing those?
I've tried to look into F() and Func() from Django as well, but I don't think that solves my issue as it seem to be using built in aggregate functions. I also tried to execute RawSQL in an annotate function to perform the function ST_LineCrossingDirection but it would require me to write a WHERE clause and the condition is something I'm not aware of until I get to the filter() call where I'm using intersects() between two geometries.
Anyway .. If anyone knows how to use what I assume is missing Postgis functions please let me know. Because my code is getting quite messy and ineffective.
Thanks, and all help is appreciated!
You should take a look at GeoFunc, it's the GeoDjango equivalent of Django's Func.
from django.contrib.gis.db.models.functions import GeoFunc
class LineCrossingDirection(GeoFunc):
function='ST_LineCrossingDirection'
class FrechetDistance(GeoFunc):
function='ST_FrechetDistance'

Querying Django Postgres for Fuzzy FTS + Typeahead

I'm using PostgreSQL 12.3 with Django 3.0.8. I'm trying to implement a typeahead functionality. I tried using Trigram similarity, but that didn't work too well since, if I were to have a text saying "chair," I would have to type "cha" before I get results.
I'm using corejavascript/twitter's typeahead JS library. Their first example (The Basics) allows you to type in a single letter and get results instantly, some of which are not even the prefix of the word.
How would I do that? You can view my current functionality here: https://github.com/Donate-Anything/Donate-Anything/blob/76348e9362d386d3d6375b9a75d47d5765960992/donate_anything/item/views.py#L21-L30
I thought that I should use to_tsvector with a SearchVectorField, but when I implemented that (with a query like this:
queryset = (
Item.objects.defer("is_appropriate")
.filter(name_search=str(query))
)
then I don't even see the results until I type in the full word. What would my implementation look like then? (Article for implementing the triggers for SearchVectorField)

Create function in database using django ORM

In my project I want to get people who have birthday between some days, I hope to find a solution which does not force any limitations to queries.
I have found this solution which seems efficient and suite for my problem. But now I have a second problem to create the function in database using django ORM, because this must be portable and works with test database also. I could not find any proper way to able to define the function and the index based on it in django.
In brief I want to create below function in database using django:
CREATE OR REPLACE FUNCTION indexable_month_day(date) RETURNS TEXT as $BODY$
SELECT to_char($1, 'MM-DD');
$BODY$ language 'sql' IMMUTABLE STRICT;
CREATE INDEX person_birthday_idx ON people (indexable_month_day(dob));
To answer your question, using RunSQL you can insert raw SQL into a migration
-- it looks like you should be able to put this raw SQL into a migration file, including the function that would create the custom index. So running the migration would create the custom in
But don't do this -- you should just use Django to index the dob field, i.e.
dob = models.DateField(db_index=True)
and use Django to write your queries as well.

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?

Proper way to call a database function from Django?

i'm triyng to make a full text search with postgresql and django So I've created a function search_client(text) which returns a list of clients. To call it from the DB i use something like this:
SELECT * FROM search_client('something')
and i'm not really sure how to call it from django. i know i could do something like
cursor = connection.cursor()
cursor.execute("SELECT * FROM search_client('something')")
result = cursor.fetchall()
but that will only return a list of values, and i'd like to have a list of objects, like when i use the "filter()" method.
Any ideas?? thanks for your time!
If your goal is a full-featured search engine, have a look at django-haystack. It rocks.
As for your question, the new (Django 1.2) raw method might work:
qs = MyModel.objects.raw("SELECT * FROM search_client('something')")
If you're using Django 1.2, you can use the raw() ORM method to execute custom SQL but get back Django models. If you're not, you can still execute the SQL via the extra() method on default QuerySet, and pump it into a custom method to either then go pull the real ORM records, or make new, temporary, objects
First, you probably don't want to do this. Do you have proof that your database function is actually faster?
Implement this in Python first. When you can prove that your Python implementation really is the slowest part of your transaction, then you can try a stored procedure.
Second, you have the extra method available in Django.
http://docs.djangoproject.com/en/1.2/ref/models/querysets/#django.db.models.QuerySet.extra
Note that compute-intensive database procedures are often slow.