Хорошо, учитывая структуру данных, что-то вроде этого может работать для вас.
Это автономный код, кроме этого вызова .objects.bulk_create()
;как прокомментировано в коде, два определенных класса на самом деле будут моделями в вашем приложении Django.(Кстати, вы, вероятно, также хотите сохранить идентификатор CVE как уникальное поле.)
В вашем исходном коде было ошибочное предположение, что у каждой "конечной записи" в данных затронутой версии будет один и тот же поставщик, которыйможет не быть правдой.Вот почему структура модели здесь имеет отдельную модель продукта-версии, которая имеет поля поставщика, продукта и версии.(Если вы хотите немного оптимизировать вещи, вы можете дедуплицировать AffectedProductVersion
s даже через DataNist
s (что, помимо прочего, не является идеальным названием для модели)).
ИКонечно, как вы уже сделали в своем исходном коде, импорт должен выполняться внутри транзакции (transaction.atomic()
).
Надеюсь, это поможет.
import json
import os
import types
class DataNist(types.SimpleNamespace): # this would actually be a model
severity = ""
exp_score = ""
impact_score = ""
cvss_score = ""
def save(self):
pass
class AffectedProductVersion(types.SimpleNamespace): # this too
# (foreign key to DataNist here)
vendor_name = ""
product_name = ""
version_value = ""
def import_item(item):
database_object = DataNist()
try:
impact = item["impact"]["baseMetricV2"]
except KeyError: # no impact object available
pass
else:
database_object.severity = impact.get("severity", "")
database_object.exp_score = impact.get("exploitabilityScore", "")
database_object.impact_score = impact.get("impactScore", "")
if "cvssV2" in impact:
database_object.cvss_score = impact["cvssV2"]["baseScore"]
for description_data in item["cve"]["description"]["description_data"]:
database_object.description = description_data["value"]
break # only grab the first description
database_object.save() # save the base object
affected_versions = []
for vendor_data in item["cve"]["affects"]["vendor"]["vendor_data"]:
for product_data in vendor_data["product"]["product_data"]:
for version_data in product_data["version"]["version_data"]:
affected_versions.append(
AffectedProductVersion(
data_nist=database_object,
vendor_name=vendor_data["vendor_name"],
product_name=product_data["product_name"],
version_name=version_data["version_value"],
)
)
AffectedProductVersion.objects.bulk_create(
affected_versions
) # save all the version information
return database_object # in case the caller needs it
with open("nvdcve-1.0-2019.json") as infp:
data = json.load(infp)
for item in data["CVE_Items"]:
import_item(item)