Rachit
Rachit

Reputation: 248

Django: How to use same abstract class twice with same fields but different names?

I have an abstract model called Address with fields such as address_line, postcode etc.

Now I want to create a model Person which has multiple types of addresses like residential_address, office_address etc. How can I achieve that in Django?

My Address model:

class Address(Model):

    address_line_one = CharField(
        blank=True,
        null=True,
        max_length=255,
    )

    address_postcode = CharField(
        blank=True,
        null=True,
        max_length=50,
        validators=POSTCODE_VALIDATORS
    )

    class Meta(GlobalMeta):
        abstract = True

My Person class:

class Person(Address, Model):
    name = CharField(
        blank = True
        max_length = True
    )
    class Meta:
    app_label = "person"
    
)

forms

class PersonForm(forms.ModelForm):
    class Meta:
        model = Person
        exclude = []
        widgets = {}

form.html

<div>
    {% form.name %}
</div>

Upvotes: 2

Views: 113

Answers (1)

Abdul Aziz Barkat
Abdul Aziz Barkat

Reputation: 21807

You should not inherit from Address in your Person class. The basic premise of inheritance is an "Is a" relationship, i.e. your code ends up saying "Person is an Address" which is wrong! What you want instead is an Aggregation in terms of Object Oriented Programming. You can do this in databases / Django models by using foreign keys.

In Django you can use the ForeignKey [Django doc] field to model such relationships:

from django.db import models


class Address(Model):

    address_line_one = CharField(
        blank=True,
        null=True,
        max_length=255,
    )

    address_postcode = CharField(
        blank=True,
        null=True,
        max_length=50,
        validators=POSTCODE_VALIDATORS
    )

    class Meta(GlobalMeta):
        # This should not be abstract
        # abstract = True


class Person(Model):
    name = CharField(
        blank = True
        max_length = 50 # This must be a number
    )
    residential_address = models.ForeignKey(
        Address,
        on_delete=models.CASCADE,
        related_name='residing_people'
    )
    office_address = models.ForeignKey(
        Address,
        on_delete=models.CASCADE,
        related_name='office_people'
    )
    
    class Meta:
        app_label = "person"

Upvotes: 1

Related Questions