How can I reach second level natural keys on django query?

268 Views Asked by At

I have this models on django with natural_keys functions declared.

class Comments(models.Model):
    profile = models.ForeignKey('Profiles', models.DO_NOTHING)
    book = models.ForeignKey(Books, models.DO_NOTHING)
    date = models.DateTimeField()
    text = models.TextField()

    class Meta:
        managed = False
        db_table = 'comments'

class Profiles(models.Model):
    alias = models.CharField(max_length=40)
    mail = models.CharField(max_length=255)
    mainimg = models.ForeignKey(Multimedia, models.DO_NOTHING)
    birthdate = models.DateTimeField(blank=True, null=True)
    country = models.CharField(max_length=30, blank=True, null=True)
    password = models.CharField(max_length=255)
    terms = models.IntegerField(blank=True, null=True)
    device_token = models.CharField(max_length=500)

    def natural_key(self):
        return (self.pk, self.alias, self.country, self.mainimg)

    class Meta:
        managed = False
        db_table = 'profiles'

class Multimedia(models.Model):
    url = models.CharField(max_length=255)
    title = models.CharField(max_length=100)
    alt = models.CharField(max_length=150, blank=True, null=True)
    description = models.CharField(max_length=150, blank=True, null=True)
    mytype = models.CharField(max_length=20, blank=True, null=True)
    extension = models.CharField(max_length=6, blank=True, null=True)

    def natural_key(self):
        return (self.pk, self.url)

    class Meta:
        managed = False
        db_table = 'multimedia'

When I do a get comments query, I want a full response with the comment details, some book details, and profile details (including the picture). Everything goes fine except when I want the profile mainimg being serialized with natural keys.

The error response is

is not JSON serializable

when executing this:

def getcomments(request):
    #Book get all comments - returns all comments on a book.
    profilelogged = validtoken(request.META['HTTP_MYAUTH'])
    if not profilelogged:
        return HttpResponse('Unauthorized', status=401)
    else:
        index = request.GET.get('id', 0)
        bookselected = Books.objects.filter(pk=index).first()
        comments = list(Comments.objects.filter(book=bookselected).order_by('-date').all())
        books_json = serializers.serialize('json', comments, use_natural_foreign_keys=True)
        return HttpResponse(books_json, content_type='application/json')

Anyway I can get multimedia url on comment query on same response object serialized?

Thanks.

2

There are 2 best solutions below

0
Harshit verma On

You are trying to convert ForeignKey object into JSON object which gives error as ForeignKey contains serialized data, So you have to use safe parameter to convert your data into JSON.

return HttpResponse(books_json, content_type='application/json', safe=False)

if it doesn't work! Try this:

return HttpResponse(books_json, safe=False)

Otherwise you can always user JsonResponse as it is safer to user for propagation of JSON objects.

P.S: Why your Profile ForeignKey in first Model is in quotes? Is it on purpose?

0
Ian Ortega On

Thanks everyone.

I have reached what i want adding to the Profiles model natural_key function the Multimedia fields I want to use, insted of the full Multimedia model I do not need.

class Profiles(models.Model):
    alias = models.CharField(max_length=40)
    mail = models.CharField(max_length=255)
    mainimg = models.ForeignKey(Multimedia, models.DO_NOTHING)
    birthdate = models.DateTimeField(blank=True, null=True)
    country = models.CharField(max_length=30, blank=True, null=True)
    password = models.CharField(max_length=255)
    terms = models.IntegerField(blank=True, null=True)
    device_token = models.CharField(max_length=500)

    def natural_key(self):
        return (self.pk, self.alias, self.country, self.mainimg.pk, self.mainimg.url)

    class Meta:
        managed = False
        db_table = 'profiles'

And now, the reponse is what I wanted.