Domanda

Utilizzando la logica distanza dal questo SO inviare , sto tornando un insieme adeguatamente filtrato di oggetti con questo codice:

class LocationManager(models.Manager):
    def nearby_locations(self, latitude, longitude, radius, max_results=100, use_miles=True):
        if use_miles:
            distance_unit = 3959
        else:
            distance_unit = 6371

        from django.db import connection, transaction
        cursor = connection.cursor()

        sql = """SELECT id, (%f * acos( cos( radians(%f) ) * cos( radians( latitude ) ) *
        cos( radians( longitude ) - radians(%f) ) + sin( radians(%f) ) * sin( radians( latitude ) ) ) )
        AS distance FROM locations_location HAVING distance < %d
        ORDER BY distance LIMIT 0 , %d;""" % (distance_unit, latitude, longitude, latitude, int(radius), max_results)
        cursor.execute(sql)
        ids = [row[0] for row in cursor.fetchall()]

        return self.filter(id__in=ids)

Il problema è che non riesco a capire come mantenere la lista / set di query ordinati per il valore della distanza. Io non voglio fare questo come metodo aggiuntivo call () per motivi di prestazioni (una query rispetto a una query su ogni posizione potenziale nel mio database). Un paio di domande:

  1. Come posso ordinare la mia lista di distanza? Neanche togliersi il tipo nativo ho definito nel mio modello e l'utilizzo di "order_by ()", è ancora l'ordinamento per qualcos'altro (id, credo).
  2. Mi sbaglio circa la cosa prestazioni e Django ottimizzerà la query, quindi dovrei usare extra (), invece?
  3. È questo il modo totalmente sbagliato per fare questo e devo utilizzare la biblioteca geo invece di questo come un putz per arrotolare sigarette?
È stato utile?

Soluzione

Per prendere le vostre domande in ordine inverso:

Re 3) Sì, si dovrebbe assolutamente approfittare di PostGIS e GeoDjango se si sta lavorando con i dati geospaziali. E 'solo stupido non farlo.

Re 2) non credo che si poteva ottenere abbastanza Django per fare questa query per voi utilizzando .extra () (salvo accettazione della questo biglietto ), ma è un ottimo candidato per il nuovo metodo .raw () in Django 1.2 (vedi sotto).

Re 1) Hai trovato un elenco di ID dal tuo primo query e quindi con un "in" la query per ottenere un QuerySet degli oggetti corrispondenti a tali ID. La vostra seconda query non ha accesso alla distanza calcolata dalla prima query; è solo andare a prendere un elenco di ID (e non importa in che ordine che fornisci gli ID a, o).

Possibili soluzioni (a corto di ammaraggio tutto questo e utilizzando GeoDjango):

  1. Aggiornamento a Django 1.2 beta e utilizzare il metodo nuova .raw () . In questo modo Django per interpretare in modo intelligente i risultati di una query SQL prime e di trasformarlo in un QuerySet di oggetti del modello attuale. Che ridurrebbe i tuoi attuali due query in una sola, e preservare l'ordinamento specificato in SQL. Questa è la migliore opzione se siete in grado di fare l'aggiornamento.

  2. Non preoccupatevi di costruire un set di query Django Django o modello oggetti a tutti, basta aggiungere tutti i campi necessari in SQL prime SELECT e quindi utilizzare quelle file direttamente dal cursore. Non può essere un'opzione se avete bisogno di metodi modello ecc in seguito.

  3. Eseguire una terza fase in codice Python, dove eseguire iterazioni sul set di query e costruire una lista Python di oggetti del modello nello stesso ordine in cui elencare gli ID di sei tornato dalla prima query. Torna quella lista invece di un QuerySet. Non funziona se hai bisogno di fare ulteriore filtraggio su tutta la linea.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top