我正在为允许用户上传文件的视图添加一个附件,这在我使用runserver
进行测试时非常有效。但是,当我使用Django测试用例时,我得到IntegrityError: null value in column "created_at" violates not-null constraint
,其中created_at
是一个DateTimeField。
class Proposal(IsPrimeMixin, PSortMixin, models.Model):
number = models.OneToOneField(ProjectNumber, on_delete=models.CASCADE, primary_key=True)
created_at = models.DateTimeField(auto_now_add=True)
...
悖论是,从父节省方法中引发IntegrityError
错误的地方。
...
File "/Users/feldman/workspace/intranet/proposals/models.py", line 329, in save
super(Proposal, self).save(*args, **kwargs)
...
但是,according to django此字段应为空,因为auto_now
中设置了pre_save
字段。当我使用runserver
时,会重申这一点; self.created_at
为空,直到调用父保存方法的第329行之后。只有在那之后它才有价值。
> /Users/feldman/workspace/intranet/proposals/models.py(329)save()
(Pdb) self.created_at
(Pdb) next
> /Users/feldman/workspace/intranet/proposals/models.py(330)save()
-> next_number.assigned_at = timezone.now()
(Pdb) next
> /Users/feldman/workspace/intranet/proposals/models.py(331)save()
-> next_number.save()
(Pdb) self.created_at
datetime.datetime(2017, 4, 26, 18, 45, 40, 65870, tzinfo=<UTC>)
因此,为什么在非测试用例中通常会填充IntegrityError
?
我正在运行Django 1.10
class ProposalTests(TestCase):
def setUp(self):
...
self.form_data = {
'city': 'Test City',
'gng_chance_of_winning': 'high',
'gng_effort_required': 2,
'market_area': self.marketarea.id,
'project_director': self.proj_director.id,
'project_manager': self.proj_manager.id,
'project_type': 'PU',
'role': self.cc.role,
'title': self.cc.title,
'ultimate_organization': self.ult_org.id,
'ultimate_contact': self.ult_contact.id,
'created_at': timezone.now()
}
class TestProposalNewView(ProposalTests):
def test_adding_proposal_documents(self):
ProjectNumber.objects.create(number=72712)
self.client.login(username='testerton', password='bologna')
with open('core/test_data/test_case.pdf') as pd:
self.form_data.update({'conflict_check': self.cc.id, 'files': pd})
response = self.client.post(reverse('proposals:new'), self.form_data)
import pdb; pdb.set_trace()
模型的保存方法的相关部分,
def save(self, *args, **kwargs):
log_entry = kwargs.pop('log_entry', True)
if self.pk is None:
next_number = ProjectNumber.objects.next_number()
self.number = next_number
super(Proposal, self).save(*args, **kwargs) # line 329
和追溯
Internal Server Error: /proposals/new
Traceback (most recent call last):
File "/Users/feldman/.virtualenvs/intranettwopointoh/lib/python2.7/site-packages/django/core/handlers/exception.py", line 42, in inner
response = get_response(request)
File "/Users/feldman/.virtualenvs/intranettwopointoh/lib/python2.7/site-packages/django/core/handlers/base.py", line 187, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/Users/feldman/.virtualenvs/intranettwopointoh/lib/python2.7/site-packages/django/core/handlers/base.py", line 185, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/feldman/.virtualenvs/intranettwopointoh/lib/python2.7/site-packages/django/contrib/auth/decorators.py", line 23, in _wrapped_view
return view_func(request, *args, **kwargs)
File "/Users/feldman/workspace/intranet/proposals/views.py", line 66, in proposal_new
proposal.save()
File "/Users/feldman/workspace/intranet/proposals/models.py", line 329, in save
super(Proposal, self).save(*args, **kwargs)
File "/Users/feldman/.virtualenvs/intranettwopointoh/lib/python2.7/site-packages/django/db/models/base.py", line 796, in save
force_update=force_update, update_fields=update_fields)
File "/Users/feldman/.virtualenvs/intranettwopointoh/lib/python2.7/site-packages/django/db/models/base.py", line 824, in save_base
updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
File "/Users/feldman/.virtualenvs/intranettwopointoh/lib/python2.7/site-packages/django/db/models/base.py", line 889, in _save_table
forced_update)
File "/Users/feldman/.virtualenvs/intranettwopointoh/lib/python2.7/site-packages/django/db/models/base.py", line 939, in _do_update
return filtered._update(values) > 0
File "/Users/feldman/.virtualenvs/intranettwopointoh/lib/python2.7/site-packages/django/db/models/query.py", line 654, in _update
return query.get_compiler(self.db).execute_sql(CURSOR)
File "/Users/feldman/.virtualenvs/intranettwopointoh/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 1148, in execute_sql
cursor = super(SQLUpdateCompiler, self).execute_sql(result_type)
File "/Users/feldman/.virtualenvs/intranettwopointoh/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 835, in execute_sql
cursor.execute(sql, params)
File "/Users/feldman/.virtualenvs/intranettwopointoh/lib/python2.7/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
File "/Users/feldman/.virtualenvs/intranettwopointoh/lib/python2.7/site-packages/django/db/utils.py", line 94, in __exit__
six.reraise(dj_exc_type, dj_exc_value, traceback)
File "/Users/feldman/.virtualenvs/intranettwopointoh/lib/python2.7/site-packages/django/db/backends/utils.py", line 64, in execute
return self.cursor.execute(sql, params)
IntegrityError: null value in column "created_at" violates not-null constraint
DETAIL: Failing row contains (456, null, 2017-04-26 18:59:03.693245+00, Test Case, , null, open, SO, f, PU, null, null, , f, f, f, f, f, f, f, high, 2, null, null, null, null, null, Test City, null, 456.
@login_required
def proposal_new(request):
recent_conflict_checks = None
conflict_check = None
has_proposal = False
existing_proposals = None
if request.method == 'POST':
go_no_go = True
prime = True
if 'cancel' in request.POST:
return HttpResponseRedirect(reverse('projects:list'))
if 'conflict_check' in request.POST:
try:
conflict_check = ConflictCheck.objects.get(pk=int(request.POST['conflict_check']))
except ValueError:
pass
else:
go_no_go = conflict_check.is_go_no_go
prime = conflict_check.is_prime
form = forms.proposal_new_form_factory(request.POST, go_no_go=go_no_go, prime=prime)
pdform = forms.ProposalDocumentForm(request.POST, request.FILES, prefix='proposal_docs')
if form.is_valid() and pdform.is_valid():
proposal = form.save(commit=False)
proposal.created_by = request.user.employee
try:
proposal.save() # line 66
except NoProjectNumbers:
messages.error(request, 'No project numbers remain in the database, please contact an administrator.')
else:
...
表格工厂(其中AForm,BForm,CForm和&amp; DForm只是exclude
和fieldsets
的不同组合)
def choose_base_class(go_no_go, prime):
if go_no_go and prime:
return AForm
elif go_no_go and not prime:
return BForm
elif not go_no_go and prime:
return CForm
elif not go_no_go and not prime:
return DForm
else:
raise ValueError('How did this happen...')
def proposal_new_form_factory(*args, **kwargs):
go_no_go = kwargs.get('go_no_go', True)
prime = kwargs.get('prime', True)
base_class = choose_base_class(go_no_go, prime)
class ProposalNewForm(base_class):
class Meta(base_class.Meta):
# Add status to exclude
base_class.Meta.exclude.append('status')
# Add description for demographics and marketing fieldset
fieldsets = deepcopy(base_class.Meta.fieldsets)
marketing_fieldset = filter(lambda x: x[0] == 'Demographics and Marketing', fieldsets)[0]
marketing_index = fieldsets.index(marketing_fieldset)
fieldsets[marketing_index][1]['description'] = ('Either city or state is required for a new proposal.')
return ProposalNewForm(*args, **kwargs)
很乐意提供更多需要的信息