简体   繁体   中英

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?

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='john@example.com')
>>> repoter1.save()
    
>>> repoter2 = Reporter(first_name='Paul', last_name='Jones', email='paul@example.com')
>>> 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: john@example.com

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>          

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM