def get_upsert_sql(
        self,
        rows,
        unique_fields,
        update_fields,
        auto_field_name=None,
        only_insert=False,
        return_rows=True
    ):
        """
        Generates the postgres specific sql necessary to perform an upsert (ON CONFLICT)

        INSERT INTO table_name (field1, field2)
        VALUES (1, 'two')
        ON CONFLICT (unique_field) DO UPDATE SET field2 = EXCLUDED.field2;
        """
        ModelClass = self.tables[0].model

        # Use all fields except pk unless the uniqueness constraint is the pk field. Null pk field rows will be
        # excluded in the upsert method before calling this method
        all_fields = [field for field in ModelClass._meta.fields if field.column != auto_field_name]
        if auto_field_name in unique_fields and not only_insert:
            all_fields = [field for field in ModelClass._meta.fields]

        all_field_names = [field.column for field in all_fields]
        all_field_names_sql = ', '.join(all_field_names)

        # Convert field names to db column names
        unique_fields = [
            ModelClass._meta.get_field(unique_field)
            for unique_field in unique_fields
        ]
        update_fields = [
            ModelClass._meta.get_field(update_field)
            for update_field in update_fields
        ]

        unique_field_names_sql = ', '.join([
            field.column for field in unique_fields
        ])
        update_fields_sql = ', '.join([
            '{0} = EXCLUDED.{0}'.format(field.column)
            for field in update_fields
        ])

        row_values = []
        sql_args = []

        for row in rows:
            placeholders = []
            for field in all_fields:
                # Convert field value to db value
                # Use attname here to support fields with custom db_column names
                sql_args.append(field.get_db_prep_save(getattr(row, field.attname), self.connection))
                placeholders.append('%s')
            row_values.append('({0})'.format(', '.join(placeholders)))
        row_values_sql = ', '.join(row_values)

        if update_fields:
            self.sql = 'INSERT INTO {0} ({1}) VALUES {2} ON CONFLICT ({3}) DO UPDATE SET {4} {5}'.format(
                self.tables[0].get_identifier(),
                all_field_names_sql,
                row_values_sql,
                unique_field_names_sql,
                update_fields_sql,
                'RETURNING *' if return_rows else ''
            )
        else:
            self.sql = 'INSERT INTO {0} ({1}) VALUES {2} ON CONFLICT ({3}) {4} {5}'.format(
                self.tables[0].get_identifier(),
                all_field_names_sql,
                row_values_sql,
                unique_field_names_sql,
                'DO UPDATE SET {0}=EXCLUDED.{0}'.format(unique_fields[0].column),
                'RETURNING *' if return_rows else ''
            )

        return self.sql, sql_args