关于django事务
#@transaction.atomic def do_register(self, request):
按照视频的方法,如果使用这个自动提交事务的话,那因为下面用了try/except
try: # 对用户表插入一条数据 user = User.objects.create_user( username= username, password= password, nickname= nickname )
except Exception as e: print(e) return None
会导致这个自动提交事务,起不到作用。添加数据的时候如果出错,前面正确的添加还是会起效果。就不能达到必须所有数据都正确才新增数据。基于这点,我改成了手动提交事务。
但是如果手动提交事务的话,写在注册里面的登录就起不到作用,我的理解是手动开启事务的话,需要手动提交,那在所有的表验证完需要插入的数据后,会一起写入数据。那写在注册里面的登录功能,这时应该还找不到可以登录的对象,应该就无法登录吧。我不知道我的理解有没有问题,想请老师看一下我的想法。
这是我想问的第一个问题?
就是如果使用了手动提交事务,那是不是就不能把登录和注册写在一个方法里面了,因为这样的话,在运行到登录这个代码的时候,其实事务还没有提交,那数据库也不存在这条数据,就找不到这个对象,更无法登录。
然后,基于它无法登录。但我又想实现注册后登录的功能。我又在表单中新增了一个方法。
def register_to_login(self, request, user): # 执行登录 transaction.set_autocommit(True) login(request, user) user.last_login = now() user.save() # 对登录记录表插入一条数据 ip = request.META.get('REMOTE_ADDR', None) user.add_login_record( username=user.username, ip=ip, )
我测试多次发现,在这个方法中,必须要把自动开启事务重新变成true才能够登录成功,否则调用也不会执行。
这里我想问老师第二个问题?
就是我是在上一个方法中关闭了自动提交事务,从而去手动提交,那为什么还会影响到另一个方法?(我的调用是在视图里面通过验证且先执行了do_register方法后,再调用的这个方法)
def form_valid(self, form): result = form.do_register(request= self.request) if result is not None: user, profile = result data = { 'user': UserSerializer(user).to_dict(), 'profile': UserProfileSerializer(profile).to_dict() } form.register_to_login(request=self.request, user=user) return JsonResponse(data) else: return ServerErrorJsonResponse()
那关闭了自动提交事务的话,它影响的范围是什么样的?是在这个类中再定义任何方法,都会受到它的影响?那如果我在注册的方法中关闭了自动提交事务,会不会影响其他表单关于事务的使用?
正在回答
同学,你好!
1、transaction.atomic装饰器可以保证该函数中所有的数据库操作都在一个事务中,是要整体正确执行才可以正常插入数据,同学理解的是正确的,要先注册成功才可以登录成功
2、使用transaction.set_autocommit()时需要传入autocommit的值,True是自动提交,False是不自动提交
若放弃自动提交(transaction.set_autocommit(False))的话是需要手动提交的,执行transaction.commit()手动提交事务
例:手动提交需要在提交的代码后写代码提交事务才可以
# 放弃自动提交 transaction.set_autocommit(False) user = User.objects.create_user( username=data.get('username', None), password=data.get('password', None), nickname=data.get('nickname', None) ) # 手动提交事务 transaction.commit() # 2. 创建详细表 profile = Profile.objects.create( user=user, username=user.username, version=version, source=source ) # 手动提交事务 transaction.commit() # 3. 执行登录 login(request, user) # 4. 记录登录日志 user.last_login = now() user.save() ip = request.META.get('REMOTE_ADDR', '') user.add_login_record(username=user.username, ip=ip, source=source, version=version) # 手动提交事务 transaction.commit() return user, profile
3、在do_register()方法中设置手动提交并且事务正确提交的话是不会影响register_to_login()方法的,只会影响当前函数中的代码
祝学习愉快!
相似问题
登录后可查看更多问答,登录/注册
- 参与学习 人
- 提交作业 16233 份
- 解答问题 4470 个
全新版本覆盖5大热门就业方向:Web全栈、爬虫、数据分析、软件测试、人工智能,零基础进击Python全能型工程师,从大厂挑人到我挑大厂,诱人薪资在前方!
了解课程
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星