你如何导入嵌套的JSON领域到Django模型?

时间:2019-02-02 20:14:55

标签: json django-2.1

目标: 为Magic the Gathering卡创建并填充数据库模型。

问题: 我有JSON格式的数据,并希望使用命令将其导入。由于JSON结构是嵌套的,因此我的理解是,我需要卡的表示形式的某些字段才能链接到单独的模型的ManyToManyField。由于存在具有嵌套内容的多个字段,因此需要多个模型来表示这些字段的内容。

问题: 是否可以根据需要为这些单独的模型创建实例,以通过ManyToManyField的相关模型推断所需的模块?

这已经现在缠着我了一整天,显然我一直在问谷歌的错题,所以也许我完全误导了我的做法,但希望你能帮助我在正确的轨道上:)

实施例(这是模型的稍微精简版):

models.py

class MagicCard(models.Model):
  id = models.CharField(max_length=36, primary_key=True, unique=True)
  name = models.CharField(max_length=150)
  card_faces = models.ManyToManyField('MagicCardFaces', blank=True, related_name='magic_card_faces')
  legalities = models.ManyToManyField('MagicLegalities', related_name='magic_legalities')

class MagicLegalities(models.Model):
  related_card = models.ForeignKey('MagicCard', on_delete=models.CASCADE)
  format = models.ManyToManyField('MagicFormats', related_name='magic_legalities')

class MagicCardFaces(models.Model):
  related_card = models.ForeignKey('MagicCard', on_delete=models.CASCADE)

  artist = models.CharField(max_length=40, blank=True, null=True)
  color_indicator = models.ManyToManyField('MagicColors', related_name="magic_card_face_color_indicator_name",
                                           blank=True)
  colors = models.ManyToManyField('MagicColors', related_name="magic_card_face_color_name", blank=True)
  flavor_text = models.CharField(max_length=500, blank=True, null=True)
  illustration_id = models.CharField(max_length=36, blank=True, null=True)
  image_uris = models.ManyToManyField('MagicImageUris', related_name='magic_card_face_image_uris', blank=True)
  loyalty = models.CharField(max_length=2, blank=True, null=True)
  mana_cost = models.CharField(max_length=36)
  name = models.CharField(max_length=150)
  object = models.CharField(max_length=9)
  oracle_text = models.CharField(max_length=500, blank=True, null=True)
  power = models.CharField(max_length=3, blank=True, null=True)
  printed_name = models.CharField(max_length=150, blank=True, null=True)
  printed_text = models.CharField(max_length=500, blank=True, null=True)
  printetd_type_line = models.CharField(max_length=60, blank=True, null=True)
  toughness = models.CharField(max_length=3, blank=True, null=True)
  type_line = models.CharField(max_length=60, blank=True, null=True)

cards.json

{
    "id":"f855144c-6adb-4cde-8a37-5fb0be775e5d",
    "name":"Wax // Wane",
    "card_faces":
        [
            {
                "object":"card_face",
                "name":"Wax",
                "mana_cost":"{G}",
                "type_line":"Instant",
                "oracle_text":"Target creature gets +2/+2 until end of turn.",
                "artist":"Ben Thompson",
                "illustration_id":"7a8109cf-aa8f-43db-bafd-b300bc7cf21d"
            },
            {
                "object":"card_face",
                "name":"Wane",
                "mana_cost":"{W}",
                "type_line":"Instant",
                "oracle_text":"Destroy target enchantment.",
                "artist":"Ben Thompson"
            }
        ],
    "legalities":
        {
            "standard":"not_legal",
            "future":"not_legal",
            "frontier":"not_legal",
            "modern":"not_legal",
            "legacy":"legal",
            "pauper":"not_legal",
            "vintage":"legal",
            "penny":"not_legal",
            "commander":"legal",
            "1v1":"legal",
            "duel":"legal",
            "oldschool":"not_legal",
            "brawl":"not_legal"
        },
}

import.py

from django.core.management.base import BaseCommand
from MKM_Toolkit.models import MagicCard, MagicCardFaces, MagicLegalities
import json

class Command(BaseCommand):
  fieldList = MagicCard._meta.get_fields()

  def importCards(self):
    importCount = 0
    with open('cards.json') as cardfile:
      isNewCard = False
      cards = json.load(cardfile)

      for card in cards:
        results = MagicCard.objects.filter(id__exact=card['id'])
        if results.count() == 0:
          isNewCard = True
          newCard = MagicCard()
          print('Adding %s' % (card['name']))
        else:
          isNewCard = False
          existingCard = results[0]
          print("Skipping '%s': already in database" % (card['name']))

        if isNewCard:
          fieldsToImportLater = []

          for field in self.fieldList:
            if field.get_internal_type() in ['ForeignKey', 'ManyToManyField']:
              fieldsToImportLater.append(field)
              continue
            if field.name in card:
              setattr(newCard, field.name, card[field.name])
            else:
              pass # for now
          # newCard.save() # not for now, but probably needed before manytomany import
          importCount += 1 
          for field in fieldsToImportLater:
            if field.get_internal_type() == 'ForeignKey':
              continue # for now
            elif field.name in card:
              self.importManyToManyField(field, field.name, card, newCard)
          if importCount == 1: # only try one for now
            return
        else:
          pass # for now

  def importManyToManyField(self, modelField, cardFieldName, card, related_card):
    if isinstance(card[cardFieldName], list):
      for entry in card[cardFieldName]:

        print("???") # here is where i don't know how to create a new instance for the related model

  def handle(self, *args, **options):
    self.importCards()

0 个答案:

没有答案