【问题标题】:Create model instance from another model's instance in Django without link to original instance source在 Django 中从另一个模型的实例创建模型实例,而不链接到原始实例源
【发布时间】:2011-12-11 18:49:18
【问题描述】:

我正在制作游戏。玩家的库存中有武器。武器是武器模型的实例。创建新武器时,会从模板模型实例中随机选择一个武器模板。复制所有字段以创建武器实例。为此,我使用此功能:

class ItemModel(models.Model):
    def fromTemplate(self, templateInstance):
       if issubclass(type(self), type(templateInstance)):
          for field in templateInstance._meta.fields:
                setattr(self, str(field.name), getattr(templateInstance, field.name))
          self.pk = None
          self.save()
          for m2mField in templateInstance._meta.many_to_many:
            setattr(self, m2mField.name, getattr(templateInstance, m2mField.name).all())

    class Meta:
    abstract = True

这是模型定义:

class WeaponTemplate(ItemModel):
   def __unicode__(self):
      return str(self.id)
   type = models.CharField(max_length=100, choices = TYPE_CHOICES)
   category = models.CharField(max_length=100, choices = CATEGORY_CHOICES)
   group = models.CharField(max_length=100, choices = GROUP_CHOICES)
   name = models.CharField(max_length=25)
   level = models.IntegerField(default=1)
   frequency = models.IntegerField(default = 100)
   rarity = models.CharField(max_length=8, choices = RARITY_CHOICES)
   multiplier = models.IntegerField()
   buyCost = models.IntegerField()
   sellValue = models.IntegerField(blank=True, null=True)

class Weapon(WeaponTemplate):
   def __unicode__(self):
      return self.name 

现在我的问题是“fromTemplate”函数还在模板模型中添加了一个新实例。所以当我这样做时:

randomWeaponTemplate = random.choice(WeaponTemplate.objects.all())
newWeapon = Weapon()
newWeapon.fromTemplate(randomWeaponTemplate)
newWEapon.save()

我在 WeaonTemplate 表中看到一个新条目。我应该如何修改我的代码以使两个模型独立存储,以便在从武器模板创建新武器时,不会向 WeaponTemplate 表添加任何内容?

【问题讨论】:

  • 为什么不从fromTemplate 方法中删除self.save()?或者替换为templateInstance.save()
  • 对不起,fromTemplate 方法中的 self.save() 孤独,缺少几行代码。我希望这两个模型独立存储数据,templateInstance.save() 如何让我更接近我的目标?

标签: python django database-design django-models


【解决方案1】:

我认为你不应该在武器和武器模板之间使用继承,django 将继承视为 OneToOneRelationship。如果你想让你的代码更干,你可以尝试这样:

from django.db import models
from django.db.models.manager import Manager


class WeaponBase(models.Model):
    def __unicode__(self):
        return str(self.id)

    name = models.CharField(max_length=25)
    level = models.IntegerField(default=1)
    frequency = models.IntegerField(default = 100)
    multiplier = models.IntegerField()
    buyCost = models.IntegerField()
    sellValue = models.IntegerField(blank=True, null=True)

    class Meta:
        abstract = True

class RandomManager(Manager):
    def get_query_set(self):
        return super(RandomManager, self).get_query_set().order_by('?')[0]

class WeaponTemplate(WeaponBase):
    objects = Manager()
    random = RandomManager()

class Weapon(WeaponBase):
    @classmethod
    def fromTemplate(cls, weaponTemplate):
        w = Weapon()
        for field in w._meta.fields:
            setattr(w, str(field.name), getattr(weaponTemplate, field.name))
        return w

【讨论】:

  • 我喜欢它,但是你如何确保新实例包含它收到的模板中的所有字段,就像我对 "if issubclass(type(self), type(templateInstance)) 所做的那样:"
  • 拜托,你能解释一下为什么你需要它。如果我清楚地看到整个画面,也许我可以更好地帮助你。如我所见,您进行了此测试以检查是否可以从模板创建某些内容。但在我的模型中,你总是可以做到这一点。也许我误解了什么?
猜你喜欢
  • 1970-01-01
  • 2023-03-23
  • 2023-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-09
  • 1970-01-01
  • 2019-08-01
相关资源
最近更新 更多