目标: 为Magic the Gathering卡创建并填充数据库模型。
问题: 我有JSON格式的数据,并希望使用命令将其导入。由于JSON结构是嵌套的,因此我的理解是,我需要卡的表示形式的某些字段才能链接到单独的模型的ManyToManyField。由于存在具有嵌套内容的多个字段,因此需要多个模型来表示这些字段的内容。
问题: 是否可以根据需要为这些单独的模型创建实例,以通过ManyToManyField的相关模型推断所需的模块?
这已经现在缠着我了一整天,显然我一直在问谷歌的错题,所以也许我完全误导了我的做法,但希望你能帮助我在正确的轨道上:)
实施例(这是模型的稍微精简版):
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)
{
"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"
},
}
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()