我正在尝试在我的Django项目中添加一个名为“clinicaltrials”(CT)的应用程序,该应用程序存储来自clinicaltrial.gov API的数据。每个试验可能有多个合作者和多种疾病,因此我使用ManyToManyField为它们设置了其他模型。 (注意:我最初尝试将CT直接连接到我的公司模型,但并非所有可能的公司都在我的数据库中,因此我在CT模型中也捕获了名称)
我遇到的问题是当我尝试将CT记录添加到其他任何一个模型时,我收到错误TypeError: 'NoneType' object is not iterable
。我认为通过pk
查找它可以正常工作。这是我第一次使用ManyToManyField,过去两天我一直在努力。我在哪里错了?
这是我用来写模型的功能:
def write_database(data):
for trial in range(len(data)):
# if the trial exists in the database continue to the next one
if ClinicalTrial.objects.filter(nct_id=data[trial].get('nct_id')).exists():
continue
# create list of collaborators for later
if data[trial].get('collaborators') is not None:
collaborators = []
collaborator_len = len(data[trial].get('collaborators'))
for x in range(collaborator_len):
collaborators.append(data[trial].get('collaborators')[x].get('name'))
else:
collaborators = None
print(collaborators)
# write trial info to database
ct = ClinicalTrial()
ct.nct_id = data[trial].get('nct_id')
ct.status = data[trial].get('current_trial_status')
ct.status_date = data[trial].get('current_trial_status_date')
ct.start_date = data[trial].get('start_date')
ct.start_date_type_code = data[trial].get('start_date_type_code')
ct.completion_date = data[trial].get('completion_date')
ct.record_verification_date = data[trial].get('record_verification_date')
ct.completion_date_type_code = data[trial].get('completion_date_type_code')
ct.brief_title = data[trial].get('brief_title')
ct.official_title = data[trial].get('official_title')
ct.brief_title = data[trial].get('brief_title')
ct.brief_summary = data[trial].get('brief_summary')
ct.primary_purpose_code = data[trial].get('primary_purpose').get('primary_purpose_code')
ct.phase = data[trial].get('phase').get('phase')
ct.minimum_target_accrual_number = data[trial].get('minimum_target_accrual_number')
ct.number_of_arms = data[trial].get('number_of_arms')
ct.lead_org_name = data[trial].get('lead_org')
try:
ct.lead_org_fk = Company.objects.get(company_name__startswith=data[trial].get('lead_org'))
except:
pass
ct.save()
pk = ct.pk # added this to try and get the below to work
# add collaborators
if collaborators is not None:
for x in range(len(collaborators)):
try:
# add m2m key to ClinicalTrial model
key = Company.objects.get(company_name__startswith=collaborators[x])
ct.collaborators = ct.collaborators.add(key)
print('ct.collab added')
ct.save()
# not all companies will be linked above due to syntax, this adds the text name to a separate table
c, _ = Collaborator.objects.get_or_create(company=collaborators[x])
c.save()
ct = ClinicalTrial.objects.get(pk=pk)
c.clinical_trials = c.clinical_trials.add(ct)
c.save()
except:
pass
# add diseases
if data[trial].get('diseases') is not None:
len_diseases = len(data[trial].get('diseases'))
for x in range(len_diseases):
d, _ = Disease.objects.get_or_create(
disease_code=data[trial].get('diseases')[x].get('disease_code'),
preferred_name=data[trial].get('diseases')[x].get('preferred_name'),
display_name=data[trial].get('diseases')[x].get('display_name'))
d.save()
ct = ClinicalTrial.objects.get(pk=pk)
d.clinical_trials = d.clinical_trials.add(ct)
d.save()
return
以下是我的models.py的样子:
from django.db import models
from dashboard.models import Company
class ClinicalTrial(models.Model):
# companies involved
lead_org_name = models.CharField(max_length=200)
lead_org_fk = models.ForeignKey(Company, related_name='ct_lead_org', null=True)
collaborators_m2m = models.ManyToManyField(Company)
# model details
nct_id = models.CharField(max_length=50, unique=True, default=0)
status = models.CharField(max_length=200, blank=True)
status_date = models.DateField(null=True)
start_date = models.DateField(null=True)
start_date_type_code = models.CharField(max_length=200, blank=True, default='')
completion_date = models.DateField(null=True)
completion_date_type_code = models.CharField(max_length=200, blank=True, default='', null=True)
record_verification_date = models.CharField(max_length=200, blank=True)
brief_title = models.CharField(max_length=200, blank=True)
official_title = models.CharField(max_length=200, blank=True)
brief_summary = models.CharField(max_length=200, blank=True)
study_protocol_type = models.CharField(max_length=200, blank=True)
primary_purpose_code = models.CharField(max_length=200, blank=True)
phase = models.CharField(max_length=200, blank=True)
minimum_target_accrual_number = models.CharField(max_length=200, blank=True)
number_of_arms = models.CharField(max_length=200, blank=True)
def __str__(self):
return self.official_title
class Disease(models.Model):
clinical_trials = models.ManyToManyField(ClinicalTrial, related_name='disease')
disease_code = models.CharField(max_length=200, blank=True, null=True)
preferred_name = models.CharField(max_length=200, blank=True)
display_name = models.CharField(max_length=200, blank=True)
class Collaborator(models.Model):
clinical_trials = models.ManyToManyField(ClinicalTrial, related_name='collaborator')
company = models.CharField(max_length=200)
答案 0 :(得分:0)
我不知道为什么,但我似乎无法在网上找到有关如何将值实际发布到ManyToManyField的任何代码示例。无论如何,这就是我能够让其他人面对类似问题的方法。
从根本上说,我学到了两件事。首先,这是如何将项添加到ManyToManyField d.clinical_trials.add(ct.pk)
。其次,如果使用get_or_create()命令,则在添加ManyToManyField值之前不需要保存模型。
这是OP中函数的代码片段与我更改的内容。
#----------------------------------------------------------------
# ORIGINAL CODE FROM OP
#----------------------------------------------------------------
# add m2m key to ClinicalTrial model
key = Company.objects.get(company_name__startswith=collaborators[x])
ct.collaborators = ct.collaborators.add(key)
print('ct.collab added')
ct.save()
# not all companies will be linked above due to syntax, this adds the text name to a separate table
c, _ = Collaborator.objects.get_or_create(company=collaborators[x])
c.save()
ct = ClinicalTrial.objects.get(pk=pk)
c.clinical_trials = c.clinical_trials.add(ct)
c.save()
# add diseases
if data[trial].get('diseases') is not None:
len_diseases = len(data[trial].get('diseases'))
for x in range(len_diseases):
d, _ = Disease.objects.get_or_create(
disease_code=data[trial].get('diseases')[x].get('disease_code'),
preferred_name=data[trial].get('diseases')[x].get('preferred_name'),
display_name=data[trial].get('diseases')[x].get('display_name'))
d.save()
ct = ClinicalTrial.objects.get(pk=pk)
d.clinical_trials = d.clinical_trials.add(ct)
d.save()
#----------------------------------------------------------------
# NEW CODE
#----------------------------------------------------------------
# add m2m key to ClinicalTrial model
key = Company.objects.get(company_name__startswith=collaborators[x])
ct.collaborators = ct.collaborators.add(key.PK)
# not all companies will be linked above due to syntax, this adds the text name to a separate table
c, _ = Collaborator.objects.get_or_create(company=collaborators[x])
c.clinical_trials.add(ct.pk)
c.save()
# add diseases
if data[trial].get('diseases') is not None:
len_diseases = len(data[trial].get('diseases'))
for x in range(len_diseases):
d, _ = Disease.objects.get_or_create(
disease_code=data[trial].get('diseases')[x].get('disease_code'),
preferred_name=data[trial].get('diseases')[x].get('preferred_name'),
display_name=data[trial].get('diseases')[x].get('display_name'))
d.clinical_trials.add(ct.pk)
d.save()