2009-04-13 11 views
6

Costruisco un elenco di oggetti del modello Django effettuando diverse query. Quindi voglio rimuovere qualsiasi duplicato, (tutti questi oggetti sono dello stesso tipo con un PK auto_increment int), ma non posso usare set() perché non sono lavabili.Modelli Django: come filtrare i valori duplicati da PK dopo il fatto?

C'è un modo semplice e veloce per farlo? Sto considerando di usare un dict invece di una lista con l'id come chiave.

risposta

6

C'è un modo semplice e veloce per farlo? Sto considerando di usare un dict invece di una lista con l'id come chiave.

Questo è esattamente quello che farei se fossi bloccato nella tua attuale struttura di fare molte domande. Quindi un semplice dictionary.values() restituirà la lista.

Se si dispone di un po 'più di flessibilità, perché non utilizzare gli oggetti Q? Invece di effettuare effettivamente le query, memorizzare ogni query in un oggetto Q e utilizzare un bit per bit o ("|") per eseguire una singola query. Ciò consentirà di raggiungere il tuo obiettivo e salvare i risultati del database.

Django Q objects

+0

È così che vuoi afferrare gli oggetti quando gli ID di chiave esterna sono provenienti da più tabelle (un po 'come una query IN con più parti)? – wsorenson

+0

Davvero non sono sicuro di cosa intendi con questo. Non sono sicuro di come ne hai bisogno o di cosa si riferiscono gli ID di chiavi esterne. –

+0

Sono stato in grado di utilizzare oggetti Q per recuperare gli oggetti da più tabelle e relazioni spanning. – wsorenson

0

Se l'ordine non è importante, utilizzare un comando.

3

È possibile utilizzare un set se si aggiunge la funzione __hash__ alla definizione del modello in modo che restituisca l'id (supponendo che questo non interferisce con altri comportamenti hash si può avere nel vostro app):

class MyModel(models.Model): 

    def __hash__(self): 
     return self.pk 
0

Rimuovi "duplicati" dipende da come si definisce "duplicato".

Se si vuole che OGNI colonna (eccetto il PK) corrisponda, è un dolore al collo - è molto paragonabile.

Se, d'altra parte, si dispone di una colonna "chiave naturale" (o un breve insieme di colonne) di quanto si possa facilmente interrogare e rimuovere.

master = MyModel.objects.get(id=theMasterKey) 
dups = MyModel.objects.filter(fld1=master.fld1, fld2=master.fld2) 
dups.all().delete() 

Se è possibile identificare alcuni set di campi chiave più brevi per l'identificazione dei duplicati, questo funziona piuttosto bene.


Modifica

Se gli oggetti del modello non sono state salvate nel database ancora, si può fare un dizionario su una tupla di questi tasti.

unique = {} 
... 
key = (anObject.fld1,anObject.fld2) 
if key not in unique: 
    unique[key]= anObject 
12

In generale, è meglio combinare tutte le query in una singola query, se possibile. Vale a dire.

q = Model.objects.filter(Q(field1=f1)|Q(field2=f2)) 

invece di

q1 = Models.object.filter(field1=f1) 
q2 = Models.object.filter(field2=f2) 

Se la prima query sta tornando modelle duplicati quindi utilizzare distinti()

q = Model.objects.filter(Q(field1=f1)|Q(field2=f2)).distinct() 

Se la query è davvero impossibile da eseguire con un unico comando, poi dovrai ricorrere all'utilizzo di una dict o altra tecnica raccomandata nelle altre risposte. Potrebbe essere utile se hai pubblicato la query esatta su SO e abbiamo potuto vedere se sarebbe stato possibile combinare in una singola query. Nella mia esperienza, la maggior parte delle query può essere eseguita con un singolo queryset.

+1

Sono stato in grado di utilizzare gli oggetti Q e distinti() - grazie. – wsorenson

0

Io uso questo:

dict(zip(map(lambda x: x.pk,items),items)).values()