Search code examples
pythondjangofunctionmodel

Django, Assign specific fuction tomodel field and then call it


I have a model built like this

class ApiPartner(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=30, verbose_name=_('Name'))
    api_key = models.CharField(max_length=50, verbose_name=_('API key'), null=True)
    secret_key = models.CharField(max_length=50, verbose_name=_('Secret key'), null=True)
    client_key = models.CharField(max_length=50, verbose_name=_('Client key'), null=True)
    endpoint = models.CharField(max_length=50, verbose_name=_('Endpoint'), null=True)
    logo = models.ImageField(upload_to='logos/', null=True)

evey API partner has its own method to retrieve data, for example

def get_youtube_posts(endpoint,api_key):
    results=list(requests.get(endpoint+'?key='+api_key).json())
    return results[0:50]

def get_instagram_posts(endpoint,api_key,secret_key):
    return requests.get(endpoint+'?key='+api_key+'&secret='+secret_key)

the question is: how do i assign the 'get_posts' function to the model so i can call a generic ApiPartner.get_posts() and it will retrieve the posts using the given function? I'm thinking about like a models.FunctionField but i know that doesn't exist. I think this is more a logical problem than a technical one but i can't find a way. Thank you


Solution

  • Maybe I'm understanding the question wrong; but you can just assign it as a property on the model class:

    class MyModel(models.Model):
       fields...
       
       @property
       def youtube_posts(self):
           results=list(requests.get(self.endpoint+'?key='+self.api_key).json())
           return results[0:50]
    
       @property
       def instagram_posts(self):
           return requests.get(self.endpoint+'?key='+self.api_key+'&secret='+self.secret_key)
    

    Then you can call it with the instance of your model.

    mymodel = MyModel.objects.all().first()
    youtube_posts = mymodel.youtube_posts
    # or
    instagram_posts = mymodel.instagram_posts
    

    But this will only return one or the other since your models are based on one specific endpoint. To create a more generic method on the model, use the above methods, plus this:

    @property
    def platform_posts(self)
        if "instagram" in self.endpoint:
            return self.instagram_posts
        elif "youtube" in self.endpoint:
            return self.youtube_posts
        ... You get the gist.