2014-07-25 18 views
8

È possibile aggiungere una connessione a un database in modo che quando vengono utilizzate solo le query di selezione siano consentite?Crea connessione di database MySQL di sola lettura in Django

Qualcosa di simile a questo sarebbe grande:

DATABASES = { 
    #can do update, insert, etc... 
    'default': { 
     'ENGINE': 'django.db.backends.mysql', 
     'USER': 'root', 
     'PASSWORD': '12345', 
    } 
    #select only 
    'default_readonly': { 
     'ENGINE': 'django.db.backends.mysql', 
     'NAME': 'mydb', 
     'PASSWORD': '12345', 
     'READONLY': True, 

    } 
} 

non ho trovato nulla di semplice.

risposta

5

Per quanto ne so, Django non fornisce alcuna opzione per limitare la connessione del database a una modalità di "sola lettura". Tuttavia, puoi farlo creando un utente readonly nel tuo motore di database MySQL.

Un'altra idea, sul lato codice Django, sarebbe quella di creare il proprio cursore, che genera un'eccezione se viene chiamato execute o executemany. Puoi guardare this module django-db-readonly.

5

È necessario impostare le autorizzazioni per l'utente utilizzato per la connessione (anziché "root").

Questo fa sì inserimento/aggiornamento/delete query sollevano errori, che si dovrebbe gestire in voi viste (in necessario)

+1

Grazie Don! Comunque preferisco la soluzione Maxime in quanto mi tiene dentro Django (e quindi all'interno di Git) – YardenST

3

Da Django 1.2 è possibile specificare una classe di router per query 'percorso' a diversi database (https://docs.djangoproject.com/en/dev/topics/db/multi-db/) .

Per utilizzare uno db per la lettura e uno per la scrittura è possibile definire una classe di router come questo:

Class MyRouter(object): 
    def db_for_read(self, model, **hints): 
     return 'default_readonly' 

    def db_for_write(self, model, **hints): 
     return 'default' 

    def allow_syncdb(self, db, model): 
     return db == 'default' 

e collocarlo nel vostro settings.py

DATABASE_ROUTERS = ['path.to.MyRouter'] 

Questo sta lavorando per me finché non utilizzo select_for_update(), che è considerato un'operazione di lettura, ma richiede l'accesso in scrittura al database. L'unica soluzione che ho trovato finora è di sovrascrivere select_for_update in una classe Manager in modo simile:

class MyManager(Manager): 

    def select_for_update(self, *args, **kwargs): 
     return super(MyManager, self).using('default').select_for_update(*args, **kwargs) 
+0

In realtà mi accorgo che il problema select_for_update è risolto in Django 1.7 considerando un select_for_update un'operazione di scrittura. – Oberix

Problemi correlati