3

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 ?

8
  • 1
    Exactly what error do you receive? Commented Jun 18, 2021 at 19:07
  • 1
    Note that your save method does not save the object, you need to call the super().save() to eventually save the item to the database. Commented Jun 18, 2021 at 19:09
  • What happens is that the path is always equal to ".png" only. There is no uuid or path coming from user. Commented Jun 18, 2021 at 19:09
  • 1
    How do you create ProfileImages and ThumbnailStaticImages? With some view, with form? Can you share details about this? Commented Jun 18, 2021 at 19:13
  • 1
    @SuperEye You seem to be expecting uuid to have a value in the ProfileImage.save method? uuid is set in the Image.save method which is called at the end of the ProfileImage.save method when you call super Commented Jun 18, 2021 at 20:00

2 Answers 2

2

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>          
Sign up to request clarification or add additional context in comments.

Comments

2

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

1 Comment

This makes sense if you know want a profile image, however what if you want to display attributes of either the ProfileImage or the Thumbnail image on the same view by only selecting the parent class "Image". How do i select those child attributes ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.