我有两个模型,即Project和Hourly。每当创建一个新项目时,我还想生成8760个新的每小时实例。
有两种方法,一种是非常昂贵的,因为8760次新数据写入数据库,即:
for i in range(0, 24):
clock_time=i*3600
hourly = Hourly.objects.create(project=project, clock_time=clock_time)
hourly.save()
另一种方法是使用Django bulk_create(hourlys)方法,只要我使用默认的Hourly()构造函数,它就可以正常工作。但是我想使用我的自定义Hourly.objects.create()函数。但是,这给了hourly.id一个UNIQUE约束错误,即:
class HourlyManager(models.Manager):
""""""
def create(self, project, clock_time):
hourly = super().create(project=project, clock_time=clock_time)
hourly.local_civil_time = services.calc_local_civil_time(clock_time,
project.TMZ,
project.lon)
hourly.save()
return hourly
class ProjectManager(models.Manager):
""""""
def create(self, owner, project_name, TMZ, lat, lon):
project = super().create(owner=owner, project_name=project_name, TMZ=TMZ, lat=lat, lon=lon)
project.save()
hourlys = []
for i in range(0, 24):
hourlys.append(Hourly.objects.create(project=project, clock_time=clock_time))
Hourly.objects.bulk_create(hourlys)
return project
class Project(models.Model):
objects = ProjectManager()
owner = models.ForeignKey('auth.User', related_name='projects', on_delete=models.CASCADE)
project_name = models.CharField(max_length=200)
TMZ = models.FloatField(default=0)
lat = models.FloatField(default=0) # Radians
lon = models.FloatField(default=0) # Radians
class Hourly(models.Model):
objects = HourlyManager()
project = models.ForeignKey(Project, related_name='hourlys', on_delete=models.CASCADE)
clock_time = models.FloatField(default=0)
local_civil_time = models.FloatField(default=0)
答案 0 :(得分:2)
当您调用hourlys.append(Hourly.objects.create(project=project, clock_time=clock_time))
时,已在数据库中创建Hourly
模型的对象,并且您将该对象附加到hourlys
列表中。该列表中的每个对象都已与其关联id
。因此,当您尝试在下一行中执行bulk_create
时,django会尝试创建具有相同ID的新对象,从而无法使用唯一约束。
答案 1 :(得分:2)
@arne,这是bulk_create的错误方法。
hourlys = []
for i in range(0, 24):
hourlys.append(Hourly.objects.create(project=project,
clock_time=clock_time))
Hourly.objects.bulk_create(hourlys)
正确的方法是将属性传递给Hourly对象,创建一个列表。压缩版本如下所示。
hourlys = [Hourly(project=project, clock_time=i*3600) for i in range(24)]
hourlys_objects = Hourly.objects.bulk_create(hourlys)
有关详情,请参阅link here
如上所述,当您调用Hourly.objects.create时,会创建对象(对数据库的命中也会影响使用bulk_create优化的目的)。
答案 2 :(得分:0)
这是我最终得到的,似乎工作正常。我在ProjectManager中使用bulk_create,而不是为Hourly模型创建一个名为create()的新类方法(@classmethod)。这解决了每小时不具有唯一ID的问题。我不是为什么,但似乎确实很好。
class ProjectManager(models.Manager):
""""""
def create(self, owner, project_name, TMZ, lat, lon):
project = super().create(owner=owner, project_name=project_name, TMZ=TMZ, lat=lat, lon=lon) # "CREATED BY PROJECTMANAGER"
project.save()
hourlys = []
for i in range(0, 24):
clock_time = i*3600
hourlys.append(Hourly.create(project=project, clock_time=clock_time))
Hourly.objects.bulk_create(hourlys)
return project
class Project(models.Model):
objects = ProjectManager()
owner = models.ForeignKey('auth.User', related_name='projects', on_delete=models.CASCADE)
project_name = models.CharField(max_length=200)
TMZ = models.FloatField(default=0)
lat = models.FloatField(default=0) # Radians
lon = models.FloatField(default=0) # Radians
class Hourly(models.Model):
#objects = HourlyManager()
project = models.ForeignKey(Project, related_name='hourlys', on_delete=models.CASCADE)
clock_time = models.FloatField(default=0) # One year = 31557600 seconds primary_key=True,
declination = models.FloatField(default=0)
local_civil_time = models.FloatField(default=0)
equation_of_time = models.FloatField(default=0)
solar_time = models.FloatField(default=0)
solar_hour_angle = models.FloatField(default=0)
@classmethod
def create(cls, project, clock_time):
hourly = cls(project=project, clock_time=clock_time)
hourly.declination = services.calc_declination(clock_time)
hourly.local_civil_time = services.calc_local_civil_time(clock_time,
project.TMZ,
project.lon)
hourly.equation_of_time = services.calc_equation_of_time(clock_time)
hourly.solar_time = services.calc_solar_time(hourly.local_civil_time,
hourly.equation_of_time)
hourly.solar_hour_angle = services.calc_solar_hour_angle(hourly.solar_time)
return hourly