Thursday, April 21, 2011

Define an attribute in a model, like an object of the other model in Django

Is posible to define an attribute in a data model like an object of other data model in Django? This is the scenary:

models.py

class Inmueble(models.Model):
    calle = models.CharField(max_length=20, verbose_name="Calle")
    numero = models.CharField(max_length=6, verbose_name="Numero")
    piso = models.IntegerField(verbose_name="Piso", blank=True, null=True)
    galeria_id = models.OneToOneField(Galeria, verbose_name="Galería del Inmueble")


class Galeria(Gallery):
    nombre = models.CharField(max_length=30, verbose_name="Nombre")

The point is: I need to create a new Galeria object automatically every time an Inmueble object is created. Thanks in advance!

                                 Analía.
From stackoverflow
  • Maybe AutoOneToOneField is the answer.

  • There are two ways to handle this:

    1. Override the save() method for the Inmueble model.
    2. Create a signal handler on Galeria that receives signals emitted by Inmueble

    Both methods would work and are acceptable, however I recommend using a signal for a couple reasons:

    • It's a bit more de-coupled. If later you change or remove Galeria, your code doesn't break
    • The signal handler for postsave includes a boolean value to indicate whether the model is being created or not. You could technically implement the same functionality in model save() by checking if the model has a .id set or not, but IMO the signal is a cleaner solution.

    Here's an idea of the code for both of these...

    Using a Signal (recommended)

    from django.db.models.signals import post_save
    from wherever.models import Inmueble
    
    class Galeria(Gallery):
        # ...
    
    def inmueble_postsave(sender, instance, created, **kwargs):
        if created:
            instance.galeria_id = Galeria.objects.create()
            instance.save()
    
    post_save.connect(inmueble_postsave, sender=Inmueble, dispatch_uid='galeria.inmueble_postsave')
    

    Overriding Model save() Method

    from wherever.models import Galeria
    
    class Inmueble(models.Model):
    
        # ...
    
        def save(self, force_insert=False, force_update=False):
            # No Id = newly created model
            if not self.id:
                self.galeria_id = Galeria.objects.create()
                super(Inmueble, self).save()
    
  • Thank you very much for resolve my concerns. Finally, I did:

    from django.db.models.signals import post_save
    
    class Galeria(Gallery):
    
      inmueble_id = models.ForeignKey(Inmueble)
    
      def inmueble_postsave(sender, instance, created, **kwargs):
        if created:
            instance = Galeria.objects.create(inmueble_id=instance,     title=instance.calle+' '+instance.numero, title_slug=instance.calle+' '+instance.numero)     
            instance.save()
    
      post_save.connect(inmueble_postsave, sender=Inmueble,  dispatch_uid='galeria.inmueble_postsave')
    

    Analía Lorenzatto.

0 comments:

Post a Comment