TransactionManagementError“在使用信号的时候,你不能执行查询直到”primefaces“块结束”,而只能在unit testing

我试图保存一个Django的用户模型实例,并在其post_save信号,我正在保存一些模型,有用户作为外键得到TransactionManagementError。

使用信号时 ,上下文和错误与django TransactionManagementError类似

但是,在这种情况下,错误仅在unit testing时发生。

它在手动testing中运行良好,但是unit testing失败。

有什么我失踪?

以下是代码片段:

views.py

@csrf_exempt def mobileRegister(request): if request.method == 'GET': response = {"error": "GET request not accepted!!"} return HttpResponse(json.dumps(response), content_type="application/json",status=500) elif request.method == 'POST': postdata = json.loads(request.body) try: # Get POST data which is to be used to save the user username = postdata.get('phone') password = postdata.get('password') email = postdata.get('email',"") first_name = postdata.get('first_name',"") last_name = postdata.get('last_name',"") user = User(username=username, email=email, first_name=first_name, last_name=last_name) user._company = postdata.get('company',None) user._country_code = postdata.get('country_code',"+91") user.is_verified=True user._gcm_reg_id = postdata.get('reg_id',None) user._gcm_device_id = postdata.get('device_id',None) # Set Password for the user user.set_password(password) # Save the user user.save() 

signal.py

 def create_user_profile(sender, instance, created, **kwargs): if created: company = None companycontact = None try: # Try to make userprofile with company and country code provided user = User.objects.get(id=instance.id) rand_pass = random.randint(1000, 9999) company = Company.objects.get_or_create(name=instance._company,user=user) companycontact = CompanyContact.objects.get_or_create(contact_type="Owner",company=company,contact_number=instance.username) profile = UserProfile.objects.get_or_create(user=instance,phone=instance.username,verification_code=rand_pass,company=company,country_code=instance._country_code) gcmDevice = GCMDevice.objects.create(registration_id=instance._gcm_reg_id,device_id=instance._gcm_reg_id,user=instance) except Exception, e: pass 

tests.py

 class AuthTestCase(TestCase): fixtures = ['nextgencatalogs/fixtures.json'] def setUp(self): self.user_data={ "phone":"0000000000", "password":"123", "first_name":"Gaurav", "last_name":"Toshniwal" } def test_registration_api_get(self): response = self.client.get("/mobileRegister/") self.assertEqual(response.status_code,500) def test_registration_api_post(self): response = self.client.post(path="/mobileRegister/", data=json.dumps(self.user_data), content_type="application/json") self.assertEqual(response.status_code,201) self.user_data['username']=self.user_data['phone'] user = User.objects.get(username=self.user_data['username']) # Check if the company was created company = Company.objects.get(user__username=self.user_data['phone']) self.assertIsInstance(company,Company) # Check if the owner's contact is the same as the user's phone number company_contact = CompanyContact.objects.get(company=company,contact_type="owner") self.assertEqual(user.username,company_contact[0].contact_number) 

追溯:

 ====================================================================== ERROR: test_registration_api_post (nextgencatalogs.apps.catalogsapp.tests.AuthTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/Users/gauravtoshniwal1989/Developer/Web/Server/ngc/nextgencatalogs/apps/catalogsapp/tests.py", line 29, in test_registration_api_post user = User.objects.get(username=self.user_data['username']) File "/Users/gauravtoshniwal1989/Developer/Web/Server/ngc/ngcvenv/lib/python2.7/site-packages/django/db/models/manager.py", line 151, in get return self.get_queryset().get(*args, **kwargs) File "/Users/gauravtoshniwal1989/Developer/Web/Server/ngc/ngcvenv/lib/python2.7/site-packages/django/db/models/query.py", line 301, in get num = len(clone) File "/Users/gauravtoshniwal1989/Developer/Web/Server/ngc/ngcvenv/lib/python2.7/site-packages/django/db/models/query.py", line 77, in __len__ self._fetch_all() File "/Users/gauravtoshniwal1989/Developer/Web/Server/ngc/ngcvenv/lib/python2.7/site-packages/django/db/models/query.py", line 854, in _fetch_all self._result_cache = list(self.iterator()) File "/Users/gauravtoshniwal1989/Developer/Web/Server/ngc/ngcvenv/lib/python2.7/site-packages/django/db/models/query.py", line 220, in iterator for row in compiler.results_iter(): File "/Users/gauravtoshniwal1989/Developer/Web/Server/ngc/ngcvenv/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 710, in results_iter for rows in self.execute_sql(MULTI): File "/Users/gauravtoshniwal1989/Developer/Web/Server/ngc/ngcvenv/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 781, in execute_sql cursor.execute(sql, params) File "/Users/gauravtoshniwal1989/Developer/Web/Server/ngc/ngcvenv/lib/python2.7/site-packages/django/db/backends/util.py", line 47, in execute self.db.validate_no_broken_transaction() File "/Users/gauravtoshniwal1989/Developer/Web/Server/ngc/ngcvenv/lib/python2.7/site-packages/django/db/backends/__init__.py", line 365, in validate_no_broken_transaction "An error occurred in the current transaction. You can't " TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block. ---------------------------------------------------------------------- 

我自己遇到了同样的问题。 这是由于在Django的新版本中如何处理事务以及有意触发exception的unit testing的怪癖造成的。

我有一个unit testing,通过有目的地触发一个IntegrityErrorexception来检查确定一个唯一的列约束:

 def test_constraint(self): try: # Duplicates should be prevented. models.Question.objects.create(domain=self.domain, slug='barks') self.fail('Duplicate question allowed.') except IntegrityError: pass do_more_model_stuff() 

在Django 1.4中,这工作正常。 但是,在Django 1.5 / 1.6中,每个testing都被封装在一个事务中,所以如果发生exception,它会中断事务,直到你明确地回滚事务。 因此,该事务中的任何进一步的ORM操作(例如我的do_more_model_stuff()将会因该django.db.transaction.TransactionManagementErrorexception而失败。

像评论中提到的caio一样,解决scheme是使用transaction.atomic捕获exception,如:

 from django.db import transaction def test_constraint(self): try: # Duplicates should be prevented. with transaction.atomic(): models.Question.objects.create(domain=self.domain, slug='barks') self.fail('Duplicate question allowed.') except IntegrityError: pass 

这将防止有意抛出的exception破坏整个unit testing的事务。

由于@mkoistinen从来没有发表过他的评论 ,所以我会发表他的build议,这样人们就不用去挖掘评论。

考虑只是把你的testing类声明为一个TransactionTestCase而不是TestCase。

从文档 :一个TransactionTestCase可能会调用提交和回滚,并观察这些调用对数据库的影响。

我在使用django 1.9.7在我的create_test_data函数中运行unit testing时出现这个错误。 它在早期版本的Django中工作。

它看起来像这样:

 cls.localauth,_ = Organisation.objects.get_or_create(organisation_type=cls.orgtypeLA, name='LA for test', email_general='test@test.com', address='test', postcode='test', telephone='test') cls.chamber,_ = Organisation.objects.get_or_create(organisation_type=cls.orgtypeC, name='chamber for test', email_general='test@test.com', address='test', postcode='test', telephone='test') cls.lawfirm,_ = Organisation.objects.get_or_create(organisation_type=cls.orgtypeL, name='lawfirm for test', email_general='test@test.com', address='test', postcode='test', telephone='test') cls.chamber.active = True cls.chamber.save() cls.localauth.active = True cls.localauth.save() <---- error here cls.lawfirm.active = True cls.lawfirm.save() 

我的解决scheme是使用update_or_create来代替:

 cls.localauth,_ = Organisation.objects.update_or_create(organisation_type=cls.orgtypeLA, name='LA for test', email_general='test@test.com', address='test', postcode='test', telephone='test', defaults={'active': True}) cls.chamber,_ = Organisation.objects.update_or_create(organisation_type=cls.orgtypeC, name='chamber for test', email_general='test@test.com', address='test', postcode='test', telephone='test', defaults={'active': True}) cls.lawfirm,_ = Organisation.objects.update_or_create(organisation_type=cls.orgtypeL, name='lawfirm for test', email_general='test@test.com', address='test', postcode='test', telephone='test', defaults={'active': True}) 

我有同样的问题,但with transaction.atomic()TransactionTestCase没有为我工作。

python manage.py test -r而不是python manage.py test对我来说是好的,也许执行的顺序是至关重要的

那么我find一个关于在哪个testing执行顺序的文档,它提到哪个testing将首先运行。

所以,我使用TestCase进行数据库交互, unittest.TestCase进行其他简单的testing,现在就起作用!

我有同样的问题,而testing,并去search谷歌和stackoverflow。

在我的情况下,我正在这样做

  author.tasks.add(tasks) 

所以把它转换成

  author.tasks.add(*tasks) 

删除了那个错误。