使用 save 方法的 kwargs 创建另一个对象



我的模型结构由两个模型组成,Counts和AccessRecords。每个AccessRecord都链接到一个Count和一个User。

在我当前的一个视图中,我通常创建Count对象,然后创建AccessRecord。像这样:

count = CountAddForm(request.POST).save()
AccessRecord.objects.create(user = request.user, count = count)

这是可行的,但我可能需要在其他视图中再次保存计数,并且我宁愿将AccessRecord创建绑定到保存方法。

count.save(**{'request_user':request.user})

并重新配置保存方法以创建AccessRecord:

class Count(models.Model):
task = models.ForeignKey(Task, related_name = 'counts', on_delete = models.CASCADE)
start_time = models.DateTimeField(null = True, blank = True)
end_time = models.DateTimeField(null = True, blank = True)
time_spent = models.PositiveIntegerField()
stamped_date = models.DateTimeField(null = True, blank = True)
def save(self, *args, **kwargs):
if self.start_time and self.end_time:
self.time_spent = date(self.end_time) - date(self.start_time)
super().save(*args, **kwargs)
if self.accesses.count() == 0:
if (not self.start_time):
self.stamped_date = timezone.now()
AccessRecord.objects.create(user = kwargs['request_user'], count = self)
class AccessRecord(models.Model):
date = models.DateTimeField(default = timezone.now)
user = models.ForeignKey(get_user_model(), related_name = 'accesses', on_delete = models.CASCADE)
count = models.ForeignKey(Count, related_name = 'accesses', on_delete = models.CASCADE)

然而,这给了我一个KeyError: 'request_user'AccessRecord.objects.create(user = kwargs['request_user'], count = self)

我不明白为什么会发生这种事,因为我的夸格是正确的。

编辑。追溯:

Environment:

Request Method: POST
Request URL: http://localhost:8000/counts/CBS%20Support/insert/
Django Version: 3.0.6
Python Version: 3.7.7
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'accounts',
'counts',
'django_filters',
'site_admin',
'invoicing_ch']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']

Traceback (most recent call last):
File "C:UsersTEX368AppDataLocalProgramsPythonPython37libsite-packagesdjangocorehandlersexception.py", line 34, in inner
response = get_response(request)
File "C:UsersTEX368AppDataLocalProgramsPythonPython37libsite-packagesdjangocorehandlersbase.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:UsersTEX368AppDataLocalProgramsPythonPython37libsite-packagesdjangocorehandlersbase.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:UsersTEX368DesktopDjango_Tutorialbollorebolloredecorators.py", line 8, in wrapper_func
return view_func(request, *args, **kwargs)
File "C:UsersTEX368DesktopDjango_Tutorialbollorebolloredecorators.py", line 20, in wrapper_func
return view_func(request, *args, **kwargs)
File "C:UsersTEX368DesktopDjango_Tutorialbollorecountsviews.py", line 42, in InsertCounts
count.save(**{'request_user':request.user})
File "C:UsersTEX368DesktopDjango_Tutorialbollorecountsmodels.py", line 110, in save
super().save(*args, **kwargs)
Exception Type: TypeError at /counts/CBS Support/insert/
Exception Value: save() got an unexpected keyword argument 'request_user'

@Jeffrey:

@authenticated_user
@department_auth
def InsertCounts(request, *args, **kwargs):
departmentTasks = Task.objects.filter(department = Department.objects.get(name = kwargs['department']))
favoriteTasks = sorted(departmentTasks, key = lambda x: x.quantity(), reverse = True)[:10]
tasks = tasksToDict(departmentTasks)
context = {'department':kwargs['department'], 'taskForm':TaskSelectForm, 'countForm':CountAddForm,
'favorite':favoriteTasks, 'tasks': tasks}
if request.method == 'POST':
try:
task = Task.objects.get(id = request.POST['task_id'])
except Task.DoesNotExist:
messages.error(request, 'This task does not exist.')
return HttpResponseRedirect(reverse_lazy('counts:insertPage', kwargs = kwargs))
else:
countForm = CountAddForm(request.POST)
count = countForm.save(commit = False)
count.task = task
count.save(**{'request_user':request.user})
if not sendExtraInfo(count, request.POST):
count.delete()
# else:
#     AccessRecord.objects.create(user = request.user, count = count)
messages.success(request, 'Count successfully inserted')

return render(request, r'countscounts_insert.html', context=context)

通常,使用kwargs来使用只有您的方法知道的关键字参数是一种反模式。这还不清楚,IDE无法自动完成您的操作。此外,您需要使用kwargs.pop((处理您的参数,因为否则您最终会通过super((方法将其传递给父类,而父类不知道该如何处理它,因此您会遇到您看到的TypeError。

更好的模式是:

class Count(models.Model):
task = models.ForeignKey(Task, related_name = 'counts', on_delete = models.CASCADE)
start_time = models.DateTimeField(null = True, blank = True)
end_time = models.DateTimeField(null = True, blank = True)
time_spent = models.PositiveIntegerField()
stamped_date = models.DateTimeField(null = True, blank = True)
def save(self, request_user=None, *args, **kwargs):
...
if self.accesses.count() == 0:
if (not self.start_time):
self.stamped_date = timezone.now()
AccessRecord.objects.create(user = request_user, count = self)
super().save(*args, **kwargs)

事实上,如果您要求始终将request_user传递给save((,则应该使用以下方法签名:def save(self, request_user, *args, **kwargs):

发生错误时,您的模型没有名为request_user的字段。

这可能是一个很好的解决方案:

def save(self, *args, **kwargs):
if self.start_time and self.end_time:
self.time_spent = date(self.end_time) - date(self.start_time)
super().save(*args, **kwargs)
if self.accesses.count() == 0:
if (not self.start_time):
self.stamped_date = timezone.now()
if "request_user" in kwargs: # make a check here
request_user = kwargs.pop('request_user') # must pop
AccessRecord.objects.create(user = request_user, count = self) 

最新更新