PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Os cursores no Django são executados dentro da transação aberta?


Acredito que você precisaria de uma conexão de banco de dados separada para obter uma transação separada e simultânea. Também tenho certeza que o django gerencia apenas uma conexão por banco de dados. Mas você pode criar outro. Pode haver alguma boa razão para não fazer isso. A complexidade vem à mente.

Acho que algo assim funcionaria:
from django.conf import settings
from django.db.utils import ConnectionHandler

def my_view(request):
    """Flirt with complexity by using two connections to db"""
    private_connections = ConnectionHandler(settings.DATABASES)
    db = router.db_for_write(model)
    new_conn = private_connections[db]
    new_conn.enter_transaction_management()
    new_conn.managed(True)
    new_cur = new_conn.cursor()
    new_cur.execute("INSERT INTO ...")
    new_conn.commit()
    new_conn.close()

Observe que você não pode usar django.db.transaction porque opera nas instâncias de conexão global em django.db.connections , mas em qualquer caso, isso é apenas um wrapper fino em torno dos métodos de gerenciamento de transações no objeto de conexão.

Acho que a verdadeira questão é por que você quer fazer isso? E o que há de errado com a resposta de Lakshman Prasad? Você pode confirmar/reverter sempre que quiser, portanto, nada impede que você execute tarefas diferentes em transações distintas em uma única visualização. O fato de as transações serem paralelas e não sucessivas sugere alguma conexão lógica entre elas, o que, a meu ver, indicaria que realmente deveriam estar na mesma transação.

Se, por outro lado, você está apenas tentando emular algum tipo de processamento offline, cujo sucesso ou falha não é particularmente relevante para a visualização, considere configurar uma fila de mensagens e executar essas inserções em um processo. Aipo é um pacote popular para fazer exatamente isso. Se o tempo de resposta não for uma grande preocupação, no entanto, ainda acho que transações sucessivas devem ser suficientes.

Atualização:


Se você deseja que seu cache baseado em banco de dados opere no modo de confirmação automática enquanto ainda executa sua lógica de negócios em uma única transação (separada), existe uma maneira do django. Tudo o que você precisa fazer é garantir que o cache ocorra fora o commit_on_success :

  • Se você estiver apenas usando o middleware de cache, certifique-se de que esteja fora do TransactionMiddleware .

  • Se você usa decoradores de exibição de cache, eu me arrisco a adivinhar que você pode desabilitar TransactionMiddleware (ou coloque a visão do problema dentro de um autocommit decorador) e use o commit_on_success decorador dentro o decorador de cache. Parece engraçado, mas não sei por que não funcionaria:
    @transaction.autocommit
    @cache_page(500)
    @transaction.commit_on_success
    def my_view(request):
        "..."
    

  • Se você usa cache de modelo ou faz cache manual mais envolvido, também pode desabilitar TransactionMiddleware (ou coloque a visão do problema dentro de um autocommit decorador) e use commit_on_success como um gerenciador de contexto para colocar apenas o código que você precisa em uma transação gerenciada, deixando o resto da visão em autocommit.
    @transaction.autocommit
    def my_view(request):
        data = cache.get(some_key)
        with transaction.commit_on_success():
            context = do_some_processing(data)
        cache.set(some_key, context['data'])
        return render('template/with/cache/blocks.html', context=context)