Create a new model which have all fields of currently existing model
django, django-models, python
Solution
If your `BookmarkPlayer` needs the same data but in a different table, an abstract base model is the best way to go:
class BasePlayer(models.Model):
name = models.CharField(max_length=100, null=True, blank=True)
date_created = models.DateTimeField(auto_now_add=True)
last_updated = models.DateTimeField(auto_now=True)
hash = models.CharField(max_length=128, null=True, blank=True)
bookmark_url = models.CharField(max_length=300, null=True, blank=True)
class Meta:
abstract = True
class Player(BasePlayer):
""" player model """
pass
class BookmarkPlayer(BasePlayer):
""" bookmark player model """
pass
This way, both `Player` and `BookmarkPlayer` inherit their fields from the `BasePlayer` model, but because `BasePlayer` is abstract, the models are completely decoupled.
Multi-table inheritance on the other hand would still save the fields in a single table, but add an extra table for the `BookmarkPlayer` with an implicit `OneToOneField` to the `Player` table.
Problem
I am having a model `Player` with my django app . ``` class Player(models.Model): """ player model """ name = models.CharField(max_length=100, null=True, blank=True) date_created = models.DateTimeField(auto_now_add=True) last_updated = models.DateTimeField(auto_now=True) hash = models.CharField(max_length=128, null=True, blank=True) bookmark_url = models.CharField(max_length=300, null=True, blank=True) ``` As per my requirement i need to create a new model `BookmarkPlayer`which will have all fields of `Player` model. Right now i have two things into my mind to do this . - I can extend Player class for BookmarkPlayer model. ``` class BookmarkPlayer(Player): """ just a bookmark player""" class Meta: app_label = "core" ``` - I can define all fields of Player model into BookmarkPlayer model. ``` class BookmarkPlayer(models.Model): """ bookmark player model """ name = models.CharField(max_length=100, null=True, blank=True) date_created = models.DateTimeField(auto_now_add=True) last_updated = models.DateTimeField(auto_now=True) hash = models.CharField(max_length=128, null=True, blank=True) bookmark_url = models.CharField(max_length=300, null=True, blank=True) ``` I just want to know which way is better to do this .Please share with my if there is another good way. Updated Question Knbb's idea to create a base class is interesting but i am facing issue with one of my model which is already existed into database. My actual models : ``` class Address(models.Model): address = models.TextField(null=True, blank=True) class Site(models.Model): domain = models.CharField(max_length=200) class Player(models.Model): # ... other fields shipping_address = models.ForeignKey(Address, related_name='shipping') billing_address = models.ForeignKey(Address, related_name='billing') created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now_add=True) site = models.ManyToManyField(Site, null=True, blank=True) class Meta: abstract = True ``` Models after changes : ``` class Address(models.Model): address = models.TextField(null=True, blank=True) class Site(models.Model): domain = models.CharField(max_length=200) class BasePlayer(models.Model): # .. other fields shipping_address = models.ForeignKey(Address, related_name='shipping') billing_address = models.ForeignKey(Address, related_name='billing') created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now_add=True) site = models.ManyToManyField(Site, null=True, blank=True) class Meta: abstract = True class Player(BasePlayer): class Meta: app_label = 'core' class BookmarkPlayer(BasePlayer): class Meta: app_label = 'core' ``` After these changes when i am running my django server i am getting errors given below. ``` django.core.management.base.CommandError: One or more models did not validate: core.test1: Accessor for field 'shipping_address' clashes with related field 'Address.shipping'. Add a related_name argument to the definition for 'shipping_address'. core.test1: Reverse query name for field 'shipping_address' clashes with related field 'Address.shipping'. Add a related_name argument to the definition for 'shipping_address'. core.test1: Accessor for field 'billing_address' clashes with related field 'Address.billing'. Add a related_name argument to the definition for 'billing_address'. core.test1: Reverse query name for field 'billing_address' clashes with related field 'Address.billing'. Add a related_name argument to the definition for 'billing_address'. core.test2: Accessor for field 'shipping_address' clashes with related field 'Address.shipping'. Add a related_name argument to the definition for 'shipping_address'. core.test2: Reverse query name for field 'shipping_address' clashes with related field 'Address.shipping'. Add a related_name argument to the definition for 'shipping_address'. core.test2: Accessor for field 'billing_address' clashes with related field 'Address.billing'. Add a related_name argument to the definition for 'billing_address'. core.test2: Reverse query name for field 'billing_address' clashes with related field 'Address.billing'. Add a related_name argument to the definition for 'billing_address' ``` Answer : Finally i got answer if we are using the related_name attribute on a ForeignKey or ManyToManyField into a Abstract model. This would normally cause a problem in abstract base classes, since the fields on this class are included into each of the child classes, with exactly the same values for the attributes (including related_name) each time . To work around this problem, when you are using related_name in an abstract base class (only), part of the name should contain '%(app_label)s' and '%(class)s'. https://docs.djangoproject.com/en/dev/topics/db/models/#abstract-base-classes Now my BasePlayer model is ``` class BasePlayer(models.Model): # .. other fields shipping_address = models.ForeignKey(Address, related_name='%(app_label)s_%(class)s_shipping') billing_address = models.ForeignKey(Address, related_name='%(app_label)s_%(class)s_billing') created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now_add=True) site = models.ManyToManyField(Site, null=True, blank=True) class Meta: abstract = True ```