Search code examples
pythonpostgresqlrestodoo

Why do I always get null from fethcing data type BLOB in postgesql


I would like to get image from postgresql in odoo with rest-api python3, but I can't get it because
response data always show null.
enter image description here

This is My model:

from odoo import models, fields

class HrAttendanceBreak(models.Model):
    _name = "hr.attendance.break"
    _rec_name = 'rec_name'


    rec_name = fields.Char(string="Record Name", compute='_get_rec_name', store=True)
    attendance_id = fields.Many2one('hr.attendance',ondelete='cascade', store=True,copy=False,string='Attendance Reference')
    employee_id = fields.Many2one('hr.employee', string="Employee")

    jam_istirahat = fields.Datetime(string="Jam Istirahat")
    x_long_break = fields.Char(string="X, Longitude Break")
    y_lat_break= fields.Char(string="Y, Latitude Break")
    concat_break = fields.Char(string="Latlong Break")
    break_photo = fields.Binary(string='Break Photo', attachment=False)

    jam_lanjutKerja = fields.Datetime(string="Lanjut Kerja")
    x_long_resume = fields.Char(string="X, Longitude Resume")
    y_lat_resume= fields.Char(string="Y, Latitude Resume")
    concat_resume = fields.Char(string="Latlong Resume")
    resume_photo = fields.Binary(string='Resume Photo', attachment=False)


Im using fields.Binary() for store break_photo and resume_photo into database.
enter image description here


This is how I fetching data:

@http.route('/api/hr.attendance.break', type='http', auth="none", methods=['GET'], csrf=False)
    def hr_attendance_breake_list(self, **payload):
        model = 'hr.attendance.break'
        ioc_name = model
        model = request.env[self._model].sudo().search(
            [('model', '=', model)], limit=1)

        custFields = [
            'id', 'employee_id', 'jam_istirahat', 'jam_lanjutKerja', 
            'x_long_break', 'y_lat_break', 'break_photo', 
            'x_long_resume', 'y_lat_resume', 'resume_photo'
            ]
        
        if model:
            domain, fields, offset, limit, order = extract_arguments(payload)
            fields = custFields
            data = request.env[model.model].sudo().search_read(
                domain=domain, fields=fields, offset=offset, limit=limit, order=order)
            if data:
                return valid_response(data)
            else:
                return valid_response(data)
        return invalid_response('invalid object model', 'The model %s is not availablee in the registry.' % ioc_name)

Anyone can help me please?


Solution

  • in Odoo there is an existing controller to retrieve images called content_image with the following routes definition

    [
        '/web/image',
        '/web/image/<string:xmlid>',
        '/web/image/<string:xmlid>/<string:filename>',
        '/web/image/<string:xmlid>/<int:width>x<int:height>',
        '/web/image/<string:xmlid>/<int:width>x<int:height>/<string:filename>',
        '/web/image/<string:model>/<int:id>/<string:field>',
        '/web/image/<string:model>/<int:id>/<string:field>/<string:filename>',
        '/web/image/<string:model>/<int:id>/<string:field>/<int:width>x<int:height>',
        '/web/image/<string:model>/<int:id>/<string:field>/<int:width>x<int:height>/<string:filename>',
        '/web/image/<int:id>',
        '/web/image/<int:id>/<string:filename>',
        '/web/image/<int:id>/<int:width>x<int:height>',
        '/web/image/<int:id>/<int:width>x<int:height>/<string:filename>',
        '/web/image/<int:id>-<string:unique>',
        '/web/image/<int:id>-<string:unique>/<string:filename>',
        '/web/image/<int:id>-<string:unique>/<int:width>x<int:height>',
        '/web/image/<int:id>-<string:unique>/<int:width>x<int:height>/<string:filename>'
    ]    
    

    so you could use one like the following:

    '/web/image/hr.attendance.break/5/break_photo'
    '/web/image/hr.attendance.break/5/resume_photo'
    

    so in your controller you would generate such url for the response & the browser should load it, as following:

    @http.route('/api/hr.attendance.break', type='http', auth="none", methods=['GET'], csrf=False)
        def hr_attendance_breake_list(self, **payload):
            model = 'hr.attendance.break'
            ioc_name = model
            model = request.env[self._model].sudo().search(
                [('model', '=', model)], limit=1)
    
            custFields = [
                'id', 'employee_id', 'jam_istirahat', 'jam_lanjutKerja', 
                'x_long_break', 'y_lat_break', 'break_photo', 
                'x_long_resume', 'y_lat_resume', 'resume_photo'
                ]
            
            if model:
                domain, fields, offset, limit, order = extract_arguments(payload)
                fields = custFields
                data = request.env[model.model].sudo().search_read(
                    domain=domain, fields=fields, offset=offset, limit=limit, order=order)
                if data:
                    for item in data:
                        item['break_photo'] = '/web/image/hr.attendance.break/{}/break_photo'.format(item['id'])
                        item['resume_photo'] = '/web/image/hr.attendance.break/{}/resume_photo'.format(item['id'])
                    return valid_response(data)
                else:
                    return valid_response(data)
            return invalid_response('invalid object model', 'The model %s is not availablee in the registry.' % ioc_name)
    
    

    your final json should be as following:

    {
      "id": 65,
      "resume_photo": "/web/image/hr.attendance.break/65/resume_photo",
      "break_photo": "/web/image/hr.attendance.break/65/break_photo",
      "employee_id":[
          6,
          "Muhamed Irsan",
      ],
    }
    

    you could test this in your web browser, please note if the client is a mobile app or custom app, it has to fetch the image using the url. this should be done automatically. you have to deal with your custom client.