Re: How do you rollback a transaction outside the context of a request?
The difficulty with the decorator approach is that, at least in the case of my "DataError", in the course of executing modelinstance.save(), nobody has called transaction.set_dirty(), so the commit_on_success decorator's wrapper doesn't call rollback. If I caught the error inside of the wrapper, I could call rollback myself. But the wrapper has this nice handler that I'd like to use. So, if I call transaction.set_dirty() before the first save in my wrapped function, everything appears to work. For previous times through the loop, where there were no errors, commit_on_success's wrapper will have called commit. I'm assuming that the rollback will only roll back to the most recent commit, so I won't be loosing things from previous successful iterations of the loop that calls the wrapped function. So I don't need to become involved in savepoints. Does anyone spot a fallacy? Bill On Thu, Apr 15, 2010 at 11:27 AM, Bill Freeman wrote: > I'm following you now. I was reading through the transaction.py code after > David's post, and had just come to the same conclusion. > > I have a function (called in a loop) that contains all my model get's and > saves, > so I tried the commit_on_success decorator. Sadly, the next database > interaction after the failing save, which is a get in the beginning of the > function on the next time through the loop, fails with: > > current transaction is aborted, commands ignored until end of > transaction block > > Perchance I also need to create a savepoint and do savepoint_rollback? > > Bill > > On Thu, Apr 15, 2010 at 11:03 AM, Thomas Guettler wrote: >> >> >> Bill Freeman wrote: >>> How does this apply when there is no request? I'm not following you. >> >> I forgot to say, that I would create a temporary script file which >> uses the decorator commit_on_success instead of using "manage.py shell". >> >> Thomas >> >> >> -- >> Thomas Guettler, http://www.thomas-guettler.de/ >> E-Mail: guettli (*) thomas-guettler + de >> >> -- >> You received this message because you are subscribed to the Google Groups >> "Django users" group. >> To post to this group, send email to [email protected]. >> To unsubscribe from this group, send email to >> [email protected]. >> For more options, visit this group at >> http://groups.google.com/group/django-users?hl=en. >> >> > -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
Re: How do you rollback a transaction outside the context of a request?
I'm following you now. I was reading through the transaction.py code after David's post, and had just come to the same conclusion. I have a function (called in a loop) that contains all my model get's and saves, so I tried the commit_on_success decorator. Sadly, the next database interaction after the failing save, which is a get in the beginning of the function on the next time through the loop, fails with: current transaction is aborted, commands ignored until end of transaction block Perchance I also need to create a savepoint and do savepoint_rollback? Bill On Thu, Apr 15, 2010 at 11:03 AM, Thomas Guettler wrote: > > > Bill Freeman wrote: >> How does this apply when there is no request? I'm not following you. > > I forgot to say, that I would create a temporary script file which > uses the decorator commit_on_success instead of using "manage.py shell". > > Thomas > > > -- > Thomas Guettler, http://www.thomas-guettler.de/ > E-Mail: guettli (*) thomas-guettler + de > > -- > You received this message because you are subscribed to the Google Groups > "Django users" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]. > For more options, visit this group at > http://groups.google.com/group/django-users?hl=en. > > -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
Re: How do you rollback a transaction outside the context of a request?
Bill Freeman wrote: > How does this apply when there is no request? I'm not following you. I forgot to say, that I would create a temporary script file which uses the decorator commit_on_success instead of using "manage.py shell". Thomas -- Thomas Guettler, http://www.thomas-guettler.de/ E-Mail: guettli (*) thomas-guettler + de -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
Re: How do you rollback a transaction outside the context of a request?
Bill Freeman wrote: > How does this apply when there is no request? I'm not following you. > I wrote: >> Only methods that are called from the shell (scripts in bin/...) have the >> commit_on_success decorator. With shell I mean a unix like shell, cron-job or something like this, where you have no request. I explained it in my first post. Thomas -- Thomas Guettler, http://www.thomas-guettler.de/ E-Mail: guettli (*) thomas-guettler + de -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
Re: How do you rollback a transaction outside the context of a request?
On 14/04/10 23:15, Bill Freeman wrote: The trouble is, I don't know how. Just calling django.db.transaction.rollback() doesn't work, and neither do several other guesses. N.B. Despite eventually signalling a TransactionManagementError if django doesn't "think" it's in a transaction-managed chunk, that method typically _does_ successfully roll back the current db transaction (ultimately with the connection._rollback() private method already mentioned by Joe) prior to signalling the error. Which is a bit confusing, yes. Perhaps it would be nice if the interactive shell had an option to start up already in the transaction managed mode*, but in the meantime you can manage it yourself - "just" interactively pretend to be some of the transaction management setup code at the shell prompt, and you can avoid that error being raised upon rollback() - i.e. before and after your stuff, type in what @commit_manually does before and after the functions it decorates to switch into and out of managed mode: See source, but basically just transaction.enter_transaction_management() then transaction.managed(True) before and transaction.leave_transaction_management() after - the latter will rollback and raise an error if you forgot to commit or rollback, and remember to commit and rollback as necessary during your stuff. This is useful to know how to do anyway for complex interactive manipulations from the shell you might want to rollback as a whole. [Loosely related - there is also the autocommit django setting for postgresql to consider, I haven't really 100% got my head around all ramifications of it yet - this blog post has been very helpful though: http://thebuild.com/blog/2009/11/07/django-postgresql-and-autocommit/ http://docs.djangoproject.com/en/dev/ref/databases/#autocommit-mode - note in particular turning it on apparently doesn't preclude sections of code being under full transaction management (as the name might suggest to some people)] * say: current behaviour (which is same as @autocommit), line-by-line commit on successful line or rollback if the line raises an error, a session commit on successful exit, (two conceivably variations analogous to @commit_on_success) full manual management (analogous to @commit_manually) -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
Re: How do you rollback a transaction outside the context of a request?
How does this apply when there is no request? I'm not following you. Bill On Thu, Apr 15, 2010 at 4:20 AM, Thomas Guettler wrote: > Hi, > > here is the way I do it: I use the TransactionMiddleware. Every request gets > commited or rollbacked (A of ACID (atomar)). > > Only methods that are called from the shell (scripts in bin/...) have the > commit_on_success decorator. > > If methods get used from the shell and from views, they do not use the > commit_on_success > decorator. Only the calling script in bin/ uses this. > > I would not use django.db.transaction.rollback() or something. Use the > available decorators. Maybe you need to restructure your code to > put the statements which can fail into an new decorated method. > > HTH, > Thomas > > Bill Freeman wrote: >> I'm running code from the manage.py shell to load stuff (from an XML export >> from >> an excel read of a SQL Server dump, of all things), which gets a database >> error >> (Postgersql correctly noticing that a value is too long for a field, >> for instance) upon >> calling the save method of a model. I'd like to catch the exception, log >> about >> what instance failed, and continue. >> >> But now the db connection is within a transaction, which I assume needs to be >> rolled back, and the connection won't talk to me until I do so. >> >> The trouble is, I don't know how. Just calling >> django.db.transaction.rollback() >> doesn't work, and neither do several other guesses. >> >> I presume that the view decorators won't do it since this isn't a request >> coming through the middleware to a view function. >> >> Can someone tell me the appropriate incantations? >> >> Bill >> > > -- > Thomas Guettler, http://www.thomas-guettler.de/ > E-Mail: guettli (*) thomas-guettler + de > > -- > You received this message because you are subscribed to the Google Groups > "Django users" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]. > For more options, visit this group at > http://groups.google.com/group/django-users?hl=en. > > -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
Re: How do you rollback a transaction outside the context of a request?
Yes. I saw that in the implementation of django.db.transaction.rollback(). I hesitate to use "private" methods, but since it's an odd requirement, I may well go this way. Thanks, Bill On Wed, Apr 14, 2010 at 7:25 PM, Joe wrote: > On Apr 14, 6:15 pm, Bill Freeman wrote: >> I'm running code from the manage.py shell to load stuff (from an XML export >> from >> an excel read of a SQL Server dump, of all things), which gets a database >> error >> (Postgersql correctly noticing that a value is too long for a field, >> for instance) upon >> calling the save method of a model. I'd like to catch the exception, log >> about >> what instance failed, and continue. >> >> But now the db connection is within a transaction, which I assume needs to be >> rolled back, and the connection won't talk to me until I do so. >> >> The trouble is, I don't know how. Just calling >> django.db.transaction.rollback() >> doesn't work, and neither do several other guesses. >> >> I presume that the view decorators won't do it since this isn't a request >> coming through the middleware to a view function. > > I found this ticket useful for an example of handling DatabaseErrors > in the shell: > http://code.djangoproject.com/ticket/10813 > > Maybe try something like the following? > > from django.db import connection, DatabaseError > try: > pass # your code that will throw the error > except DatabaseError: > connection._rollback() > > > > -- > You received this message because you are subscribed to the Google Groups > "Django users" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]. > For more options, visit this group at > http://groups.google.com/group/django-users?hl=en. > > -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
Re: How do you rollback a transaction outside the context of a request?
Hi, here is the way I do it: I use the TransactionMiddleware. Every request gets commited or rollbacked (A of ACID (atomar)). Only methods that are called from the shell (scripts in bin/...) have the commit_on_success decorator. If methods get used from the shell and from views, they do not use the commit_on_success decorator. Only the calling script in bin/ uses this. I would not use django.db.transaction.rollback() or something. Use the available decorators. Maybe you need to restructure your code to put the statements which can fail into an new decorated method. HTH, Thomas Bill Freeman wrote: > I'm running code from the manage.py shell to load stuff (from an XML export > from > an excel read of a SQL Server dump, of all things), which gets a database > error > (Postgersql correctly noticing that a value is too long for a field, > for instance) upon > calling the save method of a model. I'd like to catch the exception, log > about > what instance failed, and continue. > > But now the db connection is within a transaction, which I assume needs to be > rolled back, and the connection won't talk to me until I do so. > > The trouble is, I don't know how. Just calling > django.db.transaction.rollback() > doesn't work, and neither do several other guesses. > > I presume that the view decorators won't do it since this isn't a request > coming through the middleware to a view function. > > Can someone tell me the appropriate incantations? > > Bill > -- Thomas Guettler, http://www.thomas-guettler.de/ E-Mail: guettli (*) thomas-guettler + de -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
Re: How do you rollback a transaction outside the context of a request?
On Apr 14, 6:15 pm, Bill Freeman wrote: > I'm running code from the manage.py shell to load stuff (from an XML export > from > an excel read of a SQL Server dump, of all things), which gets a database > error > (Postgersql correctly noticing that a value is too long for a field, > for instance) upon > calling the save method of a model. I'd like to catch the exception, log > about > what instance failed, and continue. > > But now the db connection is within a transaction, which I assume needs to be > rolled back, and the connection won't talk to me until I do so. > > The trouble is, I don't know how. Just calling > django.db.transaction.rollback() > doesn't work, and neither do several other guesses. > > I presume that the view decorators won't do it since this isn't a request > coming through the middleware to a view function. I found this ticket useful for an example of handling DatabaseErrors in the shell: http://code.djangoproject.com/ticket/10813 Maybe try something like the following? from django.db import connection, DatabaseError try: pass # your code that will throw the error except DatabaseError: connection._rollback() -- You received this message because you are subscribed to the Google Groups "Django users" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

