简体   繁体   中英

Create model instance from another model's instance in Django without link to original instance source

I'm making a game. The player's inventory holds weapons. The weapons are instances of the Weapon model. When a new weapon is created a weapon template is selected at random from the Template model instances. Than all fields are copied to create the weapon instance. To do so I use this function:

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

Here is the models definition:

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 

Now my problem is that the "fromTemplate" function also adds a new instance in the template model. So when I do this:

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

I see a new entry in the WeaonTemplate table. How should I modify my code to make the two models independently stored so that when a new weapon is created from a weaponTemplate, no addition is made to the WeaponTemplate table?

I think you should not use inheritance between weapon and weapontemplate, django treats inheritance as OneToOneRelationship. If you want to make your code more DRY you may try to make things that way:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM