Jeroj82
Jeroj82

Reputation: 401

Django models ForeinKey to abstact class

I'm making simply rpg browser game and I want to do this:

#Basic class
class AbstractClass(models.Model):
    health = models.IntegerField(default=10)
    mana = models.IntegerField(default=10)

And I have few profession class like

class WarriorClass(AbstractClass):
    strength = models.IntegerField(default=20)
    intelligence = models.IntegerField(default=10)

class MageClass(AbstractClass):
    strength = models.IntegerField(default=10)
    intelligence = models.IntegerField(default=20)

And in UserProfile model

class UserProfile(models.Model):
    user = models.OneToOneField(
        User, on_delete=models.CASCADE, related_name='profile'
    )
    profession = #??? 

And I don't know what should I do in profession field. I want to something like ForeingKey (but during creating new instance I want to specify to which class (mage or warrior) should be this ForeignKey.

How can I do this? Or maybe you guys have bettere idea to do mini system like this?

Best

Upvotes: 0

Views: 49

Answers (2)

rzych
rzych

Reputation: 116

You can use GenericForeignKey, from the docs

from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType

class TaggedItem(models.Model):
    tag = models.SlugField()
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

    def __str__(self):
        return self.tag

And then:

>>> from django.contrib.auth.models import User
>>> guido = User.objects.get(username='Guido')
>>> t = TaggedItem(content_object=guido, tag='bdfl')
>>> t.save()
>>> t.content_object
<User: Guido>

But this solution maybe problematic in the future. What about simpler solution

  1. Make profession as choice field
  2. Put your mana, strength, etc in UserProfile model
  3. Dependently on choice set proper value

You can overwrite the save method and if user choice Warrior set strength on 20, etc.

Upvotes: 1

GiaMele
GiaMele

Reputation: 1

Check this answer in similar case.

Based on this you can define:

class UserProfile(models.Model):
user = models.OneToOneField(
    User, on_delete=models.CASCADE, related_name='profile'
)
profession = models.ForeignKey(WarriorClass)

Upvotes: 0

Related Questions