Domanda

Ho qualche codice che getta cause syncdb di gettare un errore (perché tenta di accedere al modello prima si creano le tabelle).

C'è un modo per mantenere il codice in esecuzione su syncdb? qualcosa di simile:

if not syncdb:
    run_some_code()

Grazie:)

modifica :? PS - Ho pensato di usare il segnale post_init ... per il codice che accede al db, è che una buona idea

Maggiori informazioni

Ecco alcuni ulteriori informazioni come richiesto:)

Ho eseguito in questo un paio di volte, per esempio ... Mi era hacking su django-cron e determinato necessario per assicurarsi che i lavori non ci sono esistenti quando si carica Django (perché cerca tutte le applicazioni installate per posti di lavoro e li aggiunge al carico in ogni caso).

Così ho aggiunto il seguente codice all'inizio del file __init__.py:

import sqlite3

try:
        # Delete all the old jobs from the database so they don't interfere with this instance of django
        oldJobs = models.Job.objects.all()
        for oldJob in oldJobs:
                oldJob.delete()
except sqlite3.OperationalError:
        # When you do syncdb for the first time, the table isn't 
        # there yet and throws a nasty error... until now
        pass

Per ovvie ragioni questo è una schifezza. è legato a SQLite e io sono ci sono posti migliori per mettere questo codice (questo è solo come mi è capitato sul problema), ma funziona.

Come si può vedere l'errore che si ottiene è l'errore d'esercizio (in SQLite) e l'analisi dello stack dice qualcosa sulla falsariga di "tavolo django_cron_job non trovato"

Soluzione

Alla fine, l'obiettivo era di eseguire del codice prima che tutte le pagine sono state caricate .

Questo può essere realizzato eseguendo nel file urls.py, dal momento che deve essere importato prima che una pagina può essere servita (ovviamente).

E sono stato in grado di rimuovere quella brutta blocco try / except :) Grazie a Dio (e S. Lott)

È stato utile?

Soluzione

"edit:? PS - Ho pensato di usare il segnale post_init ... per il codice che accede al db, è che una buona idea"

Mai.

Se si dispone di codice che sta accedendo al modello prima si creano le tabelle, si hanno grandi, grossi problemi. Probabilmente stai facendo qualcosa di seriamente sbagliato.

In genere, si esegue syncdb circa una volta. Viene creato il database. E l'applicazione web utilizza il database.

A volte, hai fatto una modifica di progettazione, eliminare e ricreare il database. E poi l'applicazione web utilizza tale database per un lungo periodo di tempo.

(in genere) non è necessario il codice in un modulo __init__.py. Si dovrebbe (quasi) mai avere il codice eseguibile che fa il vero lavoro in un modulo __init__.py. E 'molto, molto raro, e inappropriato per Django.

Non sono sicuro che il motivo per cui si sta scherzi con __init__.py quando Django Cron dice che si fanno le modalità di programmazione in urls.py.


Modifica

record di compensazione è una cosa.

Nei guai con __init__.py e base.py di Django-cron sono chiaramente modi completamente sbagliato per farlo. Se è così complicato, si sta facendo male.

E 'impossibile dire quello che stai cercando di fare, ma dovrebbe essere di poco conto.

Il tuo urls.py può essere eseguito solo dopo syncdb e dopo tutto il materiale ORM è stato configurato e legato in modo corretto.

Il tuo urls.py potrebbe, per esempio, eliminare alcune righe e quindi aggiungere alcune righe a una tabella. A questo punto, tutte le questioni syncdb sono fuori strada.

Perché non avete la vostra logica nel urls.py?

Altri suggerimenti

Il codice che tenta di accedere ai modelli prima che vengano creati può tranquillamente esistere solo a livello di modulo; avrebbe dovuto essere eseguibile eseguire codice quando viene importato il modulo, come esempio indica. Questo è, come avete indovinato, la ragione per syncdb fallisce. Si cerca di importare il modulo, ma l'atto di importare il modulo di causa il codice a livello di applicazione per l'esecuzione; un "effetto collaterale", se volete.

Il desiderio di evitare le importazioni di moduli che causano effetti collaterali è così forte in Python che la convenzione if __name__ == '__main__': per gli script Python eseguibili è diventato un luogo comune. Quando solo il caricamento di una libreria di codice provoca un'applicazione per avviare l'esecuzione, mal di testa derivarne: -)

Per le applicazioni Django, questo diventa più di un mal di testa. Prendere in considerazione l'effetto di avere oldJob.delete() eseguito ogni volta che il modulo viene importato. Può sembrare come se fosse l'esecuzione solo una volta quando si esegue con il server di sviluppo Django, ma in un ambiente di produzione otterrà eseguita abbastanza spesso. Se si utilizza Apache, ad esempio, Apache frequentemente il fuoco su diversi processi figlio attesa intorno per gestire le richieste. Come un server a lungo in esecuzione progredisce, la tua app Django otterrà bootstrap ogni volta che un gestore è biforcuta per il server Web, il che significa che il modulo sarà importato e delete() sarà chiamato più volte, spesso in modo imprevedibile. Un segnale non aiuterà, purtroppo, come il segnale potrebbe essere licenziato ogni volta che un processo di Apache è inizializzato pure.

Non è, a proposito, solo un server web che potrebbe causare il codice per eseguire inavvertitamente. Se si utilizzano strumenti come epydoc, per esempio essi importare il codice per generare la documentazione API. Questo a sua volta potrebbe causare la logica dell'applicazione per avviare l'esecuzione, che è ovviamente un effetto collaterale indesiderato di appena l'esecuzione di un parser di documentazione.

Per questo motivo, il codice di pulitura come questo si sia gestito meglio da un job cron, che ricerca i lavori di stantio su base periodica e pulisce il DB. Questo script personalizzato può anche essere eseguito manualmente, o mediante qualsiasi processo (ad esempio durante una distribuzione, o come parte della vostra unità funzione di test setUp() per garantire una corsa di prova pulito). Non importa come lo fai, il punto importante è deve sempre essere eseguito che il codice come questo esplicitamente , anziché implicitamente come risultato di aprire il file di origine.

Mi auguro che aiuta. Lo so che non fornisce un modo per determinare se syncdb è in esecuzione, ma la questione syncdb magicamente svaniscono se si progetta il tuo Django app con distribuzione di produzione in mente.

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