Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django竞争条件:代码不获取新创建的记录_Python_Django_Postgresql - Fatal编程技术网

Python Django竞争条件:代码不获取新创建的记录

Python Django竞争条件:代码不获取新创建的记录,python,django,postgresql,Python,Django,Postgresql,我正在运行Django(1.11.20,带有原子_请求:True)和Postgres,并且有一个Django视图,基本上可以: job = Job(name='hello') job.save() files = JobFile.objects.create(job_id=job.id, file='myfile.txt') 大多数情况下,这种方法很好用。但有时,另一个进程(由cron执行)会检查JobFile表,发现它不包含给定现有作业的记录,执行以下操作时: jobs = Job.obje

我正在运行Django(1.11.20,带有
原子_请求:True
)和Postgres,并且有一个Django视图,基本上可以:

job = Job(name='hello')
job.save()
files = JobFile.objects.create(job_id=job.id, file='myfile.txt')
大多数情况下,这种方法很好用。但有时,另一个进程(由cron执行)会检查
JobFile
表,发现它不包含给定现有
作业的记录,执行以下操作时:

jobs = Job.objects.filter(timestamp=my_timestamp)
job_files = {}
for jf in JobFile.objects.filter(job__in=jobs):
  try:
    job_files[jf.job_id].add(jf.file)
  except KeyError:
    job_files[jf.job_id] = set([jf.file])

for job in jobs:
  files = job_files[job.id] if job.id in job_files else set()
  print('Job {} found with files {}'.format(job.id, files))

# output when this problem occurs is typically:
# Job found 123 with files set()
它报告说它在日志中发现了一个
作业
而没有
作业文件
,并且出现了错误,当我稍后检查时,DB包含一个
作业文件
很好


我在琢磨为什么它找不到
JobFile
记录,现在我调查发现,在最近发生的这个问题中,cron进程在记录创建之前大约0.1秒启动,之后很快完成,这让我怀疑是否存在某种时间问题。但我(有限的)理解是,当这一切都在一个视图中时,
原子请求将确保两个对象都存在。我的另一个疑点是
create
方法,但它在根据其属性调用save之后似乎返回得很好。我错过了什么?

看起来你有比赛条件。Django和Postgres使用隔离级别,这意味着您的cron作业中的查询将在提交事务后看到新对象

我已经在代码中添加了注释来解释这个问题

# This doesn't cause a query because Django querysets are lazy
jobs = Job.objects.filter(timestamp=my_timestamp)
job_files = {}
# This fetches the jobfiles for the jobs existing at this point
for jf in JobFile.objects.filter(job__in=jobs):
  try:
    job_files[jf.job_id].add(jf.file)
  except KeyError:
    job_files[jf.job_id] = set([jf.file])

# During the loop above, extra jobs and jobfiles are saved to the database

# This line causes the jobs queryset to be evaluated. It includes the new jobs
for job in jobs:
  files = job_files[job.id] if job.id in job_files else set()
  print('Job {} found with files {}'.format(job.id, files))
通过使用
list()
强制在脚本开头计算作业查询集,可以避免此错误

jobs = list(Job.objects.filter(timestamp=my_timestamp))

你确定每个
作业
都有一个
作业文件
?谢谢,编辑后添加了关于无作业和无作业文件的有效点。这个解释很有道理,我从未意识到所有
作业文件
都是从那里获取的。我需要一段时间才能看到没有错误发生(可能需要修复一种使此可测试的方法)。谢谢我从来没有意识到所有的作业文件都是从那里取来的——我的措辞并没有那么清楚。它获取在该点存在的匹配的
jobfile
s。问题是
.filter(
job\uu in=jobs)`中使用的作业与
中作业的
不一定相同。我确实理解了你的最后一句话,但这是否意味着
作业
会被评估两次,一次在
filter(job\uu in=jobs)
中,然后在迭代中再次评估,或者django是否形成某种类型的
JOIN
?按照我的建议使用
list()
,强制对
作业
进行一次评估。在此之前,
过滤器(job\uu in=jobs)
将是一个子查询,然后当您为job in job
调用
时,将获取
jobs
。你可以说Django在利用你自己。阅读上面的文档会很有用。