london_utku
london_utku

Reputation: 1312

How to access parent class fields from child class in Django Python

I have following inheritance between Image and ProfileImage & ThumbnailStaticImage classes in Django :

class Image(models.Model):
    uuid = models.CharField(max_length=12, default="")

    extension  = models.CharField(max_length=6, default=None)
    filename   = models.CharField(max_length=20, default=None)
    path       = models.CharField(max_length=64, default=None)

    class Meta:
        abstract = True

    def save(self, *args, **kwargs):
        if self.uuid is None:
            self.uuid = "T" + get_random_string(11).lower()
        super(Image, self).save(*args, **kwargs)

    def delete(self, *args, **kwargs):
        delete_message_send(self.path)
        super(Image, self).delete(*args, **kwargs)

class ProfileImage(Image):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

    def save(self, *args, **kwargs):
        if self.extension is None:
            self.extension = ".png"
        if self.filename is None:
            self.filename = self.uuid + self.extension
        if self.path is None:
            self.path = self.user.path + "/" + self.filename
        super(ProfileImage, self).save(*args, **kwargs)

class ThumbnailStaticImage(Image):
    video = models.ForeignKey(Video, on_delete=models.CASCADE, default=None)

    def save(self, *args, **kwargs):
        if self.extension is None:
            self.extension = ".png"
        if self.filename is None:
            self.filename = self.uuid + self.extension
        if self.path is None:
            self.path = settings.STORAGE.THUMBNAILDIRECTORY + "/" + self.filename
        super(ThumbnailStaticImage, self).save(*args, **kwargs)

When I try to access the extension variable that should be inherited from Image class to ProfileImage class, it does not get that information from parent class.

class CustomProfileImageSignedURL(APIView):
    @method_decorator(login_required(login_url='/login/'))
    def post(self, request):
        profileimage = ProfileImage.objects.
                       create(user=request.user)
        signed_url = get_signed_url_for_upload(
                     path=profileimage.path, 
                     content_type='image/png')
        logging.debug(signed_url);

        return Response({
                   "custom_profile_image_signed_url":signed_url, 
                   "image_uuid":profileimage.uuid})

What is the purpose of inheritance if the child class does not get the fields that parent class has directly?

How can I access the parent class fields from child class' overriding save method ?

Upvotes: 3

Views: 5174

Answers (2)

monkut
monkut

Reputation: 43870

When using django model inheritance where the parent model is not set to abstract=True you can access the parent using {lowercase parent model name}_ptr attribute attached to the child model.

class Image(models.Model):
    uuid = models.CharField(max_length=12, default="")

    extension  = models.CharField(max_length=6, default=None)
    filename   = models.CharField(max_length=20, default=None)
    path       = models.CharField(max_length=64, default=None)



class ProfileImage(Image):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

In the case above the parent Image model can be accessed from the from image_ptr.

p = ProfileImage.objects.all().first()
p.image_ptr.filename

Upvotes: 2

boyenec
boyenec

Reputation: 1637

Let assume you have parent model name Reporter and Child model name Article. Now you want to access Reporter from Article model. here is an example:

class Reporter(models.Model): #this is our parent model
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    email = models.EmailField()
      

class Article(models.Model): #this is our child model 
    headline = models.CharField(max_length=100)
    pub_date = models.DateField()
    reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)

Let create objects of our two models and we can access our parent(Reporter class) from our child model

here we are creating two objects of our parent model
>>> repoter1 = Reporter(first_name='John', last_name='Smith', email='[email protected]')
>>> repoter1.save()
    
>>> repoter2 = Reporter(first_name='Paul', last_name='Jones', email='[email protected]')
>>> repoter2.save()

#here we are creating an child of object

>>> from datetime import date 
>>> a = Article(id=None, headline="This is a test", pub_date=date(2005, 7, 27), reporter=repoter1) #this is a child object of repoter1 
>>> a.save()

#now we can access our parent from child object

>>> print("repoter id: ",a.reporter1.id)   
>>>repoter id: 1
>>> print("repoter email: ",a.reporter1.email)   
>>>repoter email: [email protected]

There are lot of way you can access parent class fields from child class. The easiest way to use inlineformset_factory.

in your froms.py:

forms .models import your model

class ParentFrom(froms.From):
          # add fields from your parent model 
    
ImageFormSet = inlineformset_factory(your parent model name,Your Child model name,fields=('image',# add fields from your child model),extra=1,can_delete=False,)

in your views.py

if ParentFrom.is_valid():
            ParentFrom = ParentFrom.save(commit=False)
            ImageFormSet = ImageFormSet(request.POST, request.FILES,)

            if  ImageFormSet.is_valid():
                ParentFrom.save()
                ImageFormSet.save()
                return HttpResponseRedirect(#your redirect url)

#html

<form method="POST"  enctype="multipart/form-data"> 
       
        {% csrf_token %}
        #{{ImageFormSet.errors}} #if you want to show ImageFormSet error
        {{ImageFormSet}}
        {{form}}
</form>          

Upvotes: 2

Related Questions