Home > Software engineering >  How to autopopulate a field in models.py
How to autopopulate a field in models.py

Time:05-17

I have a class named Property with a field property_type, i wana autofill this field when i create one of the other models who have onetoone relationship with Property I want the when i create a Apartment in django admin for exp the property_type in Property should autofill with the "Apartment", when i create Villa in django admin it should autofill with "villa"

class Property(models.Model):
    created_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name="agent_of_property")
    district_id = models.ForeignKey(District, on_delete=models.CASCADE)
    slug = models.SlugField(max_length=255, unique=True)
    property_type = models.CharField(choices=PROPERTY_TYPE, max_length=20)
    title = models.TextField(verbose_name="Titulli", help_text="Vendos titullin e njoftimit", max_length=500)
    description = models.TextField(verbose_name="Pershkrimi", help_text="Vendos pershkrimin",max_length=1000)
    address_line = models.CharField(verbose_name="Adresa", help_text="E nevojeshme",max_length=255)
    price = models.IntegerField()
    area = models.IntegerField()
    views = models.IntegerField(default=0)
    documents = models.CharField(verbose_name="Dokumentacioni", help_text="Dokumentat", max_length=255)
    status = models.BooleanField(default=True)
    activity = models.CharField(max_length=20, choices=ACTION_OPTION)
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True, editable=False)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta: 
        verbose_name = "Prona"
        verbose_name_plural = "Pronat"

    def get_absolute_url(self):
        return reverse("pronat:property_detail", args=[self.slug])

    def __str__(self):
        return self.title


class Apartment(Property):
    property_id = models.OneToOneField(Property, on_delete=models.CASCADE, parent_link=True, primary_key=True)
    floor = models.IntegerField(default=0)
    room_num = models.IntegerField(default=0)
    bath_num = models.IntegerField(default=0)
    balcony_num = models.IntegerField(default=0)

    class Meta: 
        verbose_name = "Apartament"
        verbose_name_plural = "Apartamentet"

    def save(self, *args, **kwargs):
        self.property_type = "Apartment"



class Villa(Property):
    property_id = models.OneToOneField(Property, on_delete=models.CASCADE, parent_link=True, primary_key=True)
    living_room = models.IntegerField(default=1)
    floors = models.IntegerField(default=1)
    room_num = models.IntegerField(default=1)
    bath_num = models.IntegerField(default=1)
    balcony_num = models.IntegerField(default=0)

    class Meta: 
        verbose_name = "Vila"
        verbose_name_plural = "Vilat"```

CodePudding user response:

I don't understand what your are doing. If you are inheriting from Property models in Apartment just remove OneToOneField and your save method would be

def save(self, *args, **kwargs):
    self.property_type = 'Apartment'
    super().save(*args, **kwargs)

But if you really want to use OneToOneField, replace Property inherit with models.Model and your save method should look like this.

def save(self, *args, **kwargs):
    self.property_id.property_type = 'Apartment'
    self.property_id.save()
    super().save(*args, **kwargs)

For 2nd case you can also use django signal

from django.db.models.signal import post_save
# ...
def populate_property_type(sender, created, instance, **kwargs):
    if sender.__name__ == 'Apartment':
        instance.property_id.property_type = 'Apartment'
        instance.property_id.save()
    # condition for Villa

post_save.connect(populate_property_type, sender=Apartment)
post_save.connect(populate_property_type, sender=Villa)

CodePudding user response:

I would suggest that you should add field in Appartment table with the name appartment_type and remove property_type from Property. But If you don't want to do that then Two ways are possible for your case.

1.When you are adding values from Django admin, you should also add the property_type from Admin.In that case you don't need to override save method. Register your Property and Appartment Table in one view. Make the admin Tables of Property and Appartment for admin view. Then register it like this way i-e

admin.site.register(PropertyAdmin, AppartmentAdmin)

and add values into both tables.

2: Simply override the save method and add this

def save(self, *args, **kwargs):
    self.property_id.property_type = 'Apartment' # you should add other field in Appartment table just avoid hard coded 'Apartment'
    self.property_id.save()
    super().save(*args, **kwargs)
  • Related