2010-06-15 13 views
13

In Django è possibile utilizzare l'esclusione per creare SQL simile a not equal. Un esempio potrebbe essere.Come escludere i risultati con get_object_or_404?

Model.objects.exclude(status='deleted') 

Ora questo funziona perfettamente ed è molto flessibile. Poiché sono un po 'pigro, mi piacerebbe avere questa funzionalità quando uso get_object_or_404, ma non ho trovato un modo per farlo, dal momento che non è possibile utilizzare l'esclusione su get_object_or_404.

Quello che voglio è quello di fare qualcosa di simile:

model = get_object_or_404(pk=id, status__exclude='deleted') 

Ma purtroppo questo non funziona in quanto non v'è un filtro di query escludere o simili. Il migliore che è venuta in mente finora sta facendo qualcosa di simile:

object = get_object_or_404(pk=id) 
if object.status == 'deleted': 
    return HttpResponseNotfound('text') 

fare qualcosa del genere, in realtà sconfigge il punto di usare get_object_or_404, dal momento che non è più un comodo one-liner.

In alternativa avrei potuto fare:

object = get_object_or_404(pk=id, status__in=['list', 'of', 'items']) 

Ma non sarebbe molto mantenibile, come avrei bisogno di mantenere l'elenco aggiornato.

Mi chiedo se mi manca qualche trucco o funzione in django per utilizzare get_object_or_404 per ottenere il risultato desiderato?

+0

Non è davvero una risposta, ma sembra che in realtà non si voglia 404 per un oggetto eliminato. L'intero punto della cancellazione soft è di mantenere l'oggetto intorno "nel caso in cui". –

risposta

17

Uso django.db.models.Q:

from django.db.models import Q 

model = get_object_or_404(MyModel, ~Q(status='deleted'), pk=id) 

Gli oggetti Q consente di non (con ~ operatore) e OR (con | dell'operatore) in aggiunta e.

Si noti che l'oggetto Q deve arrivare prima di pk=id, perché gli argomenti delle parole chiave devono arrivare per ultimi in Python.

+0

Di causa l'oggetto Q. Non sapevo che avrebbe funzionato in quella gara. Grazie. – googletorp

+1

Oltre a un modello, è anche possibile passare un gestore o un set di query come primo parametro. Vedi http://stackoverflow.com/a/26476339/336694 – Heliodor

1

C'è un altro modo invece di utilizzare oggetti Q. Invece di passare il modello di get_object_or_404 solo passare il QuerySet alla funzione invece:

effetto

model = get_object_or_404(MyModel.objects.filter(pk=id).exclude(status='deleted'))

Un lato di questo, tuttavia, è che solleverà un'eccezione MultipleObjectsReturned se il QuerySet restituisce più risultati.

6

Il caso di utilizzo più comune è passare un modello. Tuttavia, è anche possibile passare un'istanza QuerySet:

queryset = Model.objects.exclude(status='deleted') 
get_object_or_404(queryset, pk=1) 

Django documenti esempio: https://docs.djangoproject.com/en/1.10/topics/http/shortcuts/#id2

+0

Penso che questa sia una soluzione più facile da seguire rispetto alla risposta accettata. Voglio dire, se guardo il mio codice da 6 mesi fa, vorrei prendere a pugni in faccia se ho usato un oggetto Q invece di filtrare con un'esclusione. –

0

get_object_or_404 utilizza il metodo del gestore oggetti get_queryset. Se si sostituisce il metodo get_queryset per restituire solo gli articoli che non sono "cancellati", allora get_object_or_404 si comporterà automaticamente come si desidera. Tuttavia, sovrascrivere lo get_queryset in questo modo probabilmente avrà problemi altrove (forse nelle pagine di amministrazione), ma è possibile aggiungere un gestore alternativo per quando è necessario accedere agli elementi eliminati software.

from django.db import models 

class ModelManger(models.Manger): 
    def get_queryset(self): 
     return super(ModelManger, self).get_queryset().exclude(status='deleted') 

class Model(models.Model): 
    # ... model properties here ... 

    objects = ModelManager() 
    all_objects = models.Manager() 

quindi se avete bisogno solo gli elementi non eliminati si possono fare get_object_or_404(Models, id=id) ma se avete bisogno di tutti gli elementi si può fare get_object_or_404(Models.all_objects, id=id).

Problemi correlati