About Hien D. Nguyen

Hien Nguyen is an experienced Software QA Engineer. He has a great passion for software testing, especially complex test automation problems. If his hard work was somewhat helpful for you, buy him a coffee!

Deploy Django in Sub-Directory behind uWSGI and NGINX on CentOS 7

It took me awhile to deploy Django in sub-directory. Actually, I move it from sub-domain to sub-directory. I hope this post will save you some hours searching the Internet.

Prerequisite or situation

You are running Django in sub-domain, another domain and you want to move it to a sub-directory. You’re properly having issue with urlpatterns which may lead to code revise. However you still want to keep your code same.

You may also want to check out how to Setup Django behind uWSGI and NGINX on CentOS 7. FYI I am currently using Linode and DigitalOcean to host my sites.

Deploy Django in sub-directory

If you are running Django, along with WordPress, on a VPS like me, you only need to update NginX & uWSGI configuration files.

uWSGI ini

NginX configuration file

Wrap it up

Here you go demo: https://www.vndeveloper.com/django-demo/

That’s it. There are only few things from configuration files. You may also want to check out Setup Django behind uWSGI and NGINX on CentOS 7 to understand how to configure at server side.

[1] https://uwsgi-docs.readthedocs.io/en/latest/Changelog-2.0.11.html#fixpathinfo-routing-action

Web Server (VPS) Optimization Checklist for WordPress

I have been using VPS as web server since 2005 to host my sites. Before that, I switched among shared web hosting for many reasons. One of them is cost efficiency because I have more than one websites (using WordPress). I also want to try some thing else like Django, Flask which I cannot do with share web hosting.

If you are about to start a WordPress blog for the first time, you may want to start with shared web hosting. Below are list of shared web hosting suggested by WordPress.org

Spin up a VPS web server

I am currently using both Linode and DigitalOcean for my sites. They are all good and I want to experience with both so I keep using both till now. You can pickup one of them or one at your own choice. There are long list of VPS provider so please do some researches.

I wrote a tutorial on how to setup LEMP stack on CentOS 7. So please go ahead to check it out for basic web server setup.

VPS optimization for WordPress

Below is checklist or to-do list that we need to work on our VPS

  • Configure Nginx with HTTP 2 support
  • PHP extensions, Zend Opcache
  • Nginx GZIP Compression configuration
  • Install and configure Nginx module Brotli Compression
  • Install and configure Nginx module  Google PageSpeed
  • Use W3-Total-Cache: this is actually not server side directly related. However you cannot or hard to use W3-Total-Cache without full control web server.
  • Install and configure Memcached so you won’t get MySQL crash sometime or “Error establishing a database connection”. This one can also speed up your WordPress site since required data is already in memory & smaller PHP script needs to be executed meaning faster web site.
  • If your site already has some content with images, you may want to optimize them using optipng, jpegoptim, pngquant, etc.

web server test result

Final thought

Fast web site needs not only strong web server but also well configured. You really don’t want to pay for a super strong VPS and still see loading time of your site more than 3 seconds. All VPSs’ I used so far is $5/month (1vCPU, 1GB of RAM, 25GB SSD).

Keeping an active desktop session

Credit: this post heavily uses/reuses the content from Arnon Axelrod’s post. For some reasons, I couldn’t leave him a comment because of reCAPTCHA issue. So I decided to create this post and cover part he didn’t. I strongly recommend you to visit his post for full story.

Some test automation tools require an active desktop session to operate normally. I have been struggling with other approaches: autologin, relogin, unlock locked screen, etc. All of them led to same dead end. I already have a post for “How To Unlock Desktop Screen After Remote Access Disconnected” however it requires running cmd command as administrator which is not so convenience.

What locks the desktop?
1. System locked (Windows Key + L) – So far, I don’t see any better solution than using VNC.
2. Remote Desktop session disconnected – See solution below

In my opinion, Arnon Axelrod’s approach or solution is so elegent for this very common test automation problem. What we need to do is keeping an active desktop session by getting cmd command triggered automatically upon RDC disconnected.

In brief, the solution is composed of few pieces
1. A Task Scheduler’s task that is triggered upon disconnecting form Remote Desktop
2. The query session command
3. The TSCon command
4. A windows script that combines the 2 commands

for /f “skip=1 tokens=2” %s in (‘query user %USERNAME%’) do (tscon.exe %s /dest:console)

WordPress textbox autocomplete using Ajax/jQuery

This tutorial is absolutely for beginner which contains demo source code, wordy explanation. At the end, you will be able to write up a WordPress Plugin that can load data from custom database table and serve it as data source. If you learn faster by reading source code, please feel free to jump in to my github repository.

In this article, I am going to cover below topics

  1. WordPress custom database table
  2. Enqueue or load required scripts (js)
  3. Textbox autocomplete


Getting started

Before we deep dive into detail, here is couple of things that we need to do

  1. Create a folder in “\wp-content\plugins\” called “ajax-autocomplete”
  2. Create “ajax-autocomplete.php” inside above folder, this file should have below header. Check out this official document for more options

    * Plugin Name: Ajax Autocomplete
    * Plugin URI: https://www.vndeveloper.com/
    * Description: DEMO WordPress Ajax jQuery textbox autocomplete, data source from custom table.
    * Version: 0.1
    * Author: Hien D. Nguyen
    * Author URI: https://www.vndeveloper.com/
    * License: GPL2+

  3. I recommend below file folder structure. If you already have your style, keep using it.

WordPress custom database table

We will create a custom table name “testing_table” and insert some test data upon Plugin activation

register_activation_hook(basename(dirname(__FILE__)) . ‘/’ . basename( __FILE__ ), ‘activate’);
function activate() {
global $wpdb;
$charset_collate = $wpdb->get_charset_collate();
require_once(ABSPATH . ‘wp-admin/includes/upgrade.php’);

$table = $wpdb->prefix . ‘testing_table’;
$query = “CREATE TABLE IF NOT EXISTS {$table} (
name VARCHAR(128),

$wpdb->insert($table, array(‘name’=>’LogiTech’));
$wpdb->insert($table, array(‘name’=>’Apple’));
$wpdb->insert($table, array(‘name’=>’Dell’));
$wpdb->insert($table, array(‘name’=>’Google’));

Enqueue or load required scripts (js)

You might know that AutoComplete needs jQuery. You also might think that you need to download jQuery libraries and place it in your plugin, then enqueue it.

For demo purpose, we don’t have any specific requirement for jQuery version. Therefore, we are going to use “built-in” jQuery that shipped along with WordPress. You can also check out all built-in scripts or libraries such as backbone, jquery-effects-transfer…at here.

add_action(‘wp_enqueue_scripts’, ‘mysite_js’);
function mysite_js() {
$wp_scripts = wp_scripts();
wp_enqueue_script(‘mysitejs’, plugins_url(‘/assets/js/frontend.js’, __FILE__), array(‘jquery’, ‘jquery-ui-core’, ‘jquery-ui-autocomplete’));
wp_localize_script(‘mysitejs’, ‘ajax_object’, array(‘ajax_url’ => admin_url( ‘admin-ajax.php’)));

// Autocomplete style
wp_enqueue_style(‘plugin_name-admin-ui-css’,’http://ajax.googleapis.com/ajax/libs/jqueryui/’ . $wp_scripts->registered[‘jquery-ui-core’]->ver . ‘/themes/flick/jquery-ui.css’);

// If your plugin needs its own style
wp_register_style(‘mysitecss’, plugins_url(‘/assets/css/frontend.css’, __FILE__));
wp_enqueue_style(‘mysitecss’ );

Keep in mind that we’ll need to send ajax request to query data from custom database table (testing_table). That’s why we need to call wp_localize_script so that our script (JavaScript) can understand variable “ajax_url”. Basically, to send an ajax request, we send a POST request to “wp-admin/admin-ajax.php”. I personally find this article perfectly explains Ajax as well as how it handles data submission.

We also load “themes/flick/jquery-ui.css” for styling our textbox autocomplete. You can check out other styles at here.

Textbox autocomplete

First thing first, we need a textbox. In this tutorial, we’ll use shortcode called “test-form” so later on we can place it in any page or post or even widget.

add_shortcode(‘test-form’, ‘test_form’);
function test_form($args, $content=”){
include(plugin_dir_path(__FILE__) . ‘includes/forms/test-form.php’);
return ob_get_clean();

In our “test-form.php”, just create a form with a textbox with “name” attribute as “testing”. In our JavaScript, we can make use of this attribute to locate this target textbox.

<form >
<input type=”text” name=”testing”>

In our loaded script (“/assets/js/frontend.js”), it looks this

jQuery(document).ready(function($) {
source: function(request, response){
type: “POST”,
url: ajax_object.ajax_url,
data: {
action: ‘myautocomplete’,
keyword: $(‘input[name=testing]’).val(),
success:function(data) {
response(JSON.parse( data ));
error: function(errorThrown){

For further options, please check out this article. Whenever user types in, an ajax request will be sent to (url: ajax_object.ajax_url) which is “wp-admin/admin-ajax.php”, then callback action “myautocomplete” will handle this request and send a response.

add_action(‘wp_ajax_nopriv_myautocomplete’, ‘ajax_autocomplete’);
add_action(‘wp_ajax_myautocomplete’, ‘ajax_autocomplete’);
function ajax_autocomplete() {
global $wpdb;
$table = $wpdb->prefix . ‘testing_table’;
$results = $wpdb->get_results(“SELECT name FROM ” . $table . ” WHERE name LIKE ‘%” . $_POST[‘keyword’] . “%'”);
$items = array();
if ( !empty( $results) ) {
foreach ( $results as $result ) {
$items[] = $result->name;
echo json_encode($items);

Final thought

That’s it. We finished creating a WordPress Plugin that has a “testing-form” short-code. This short-code contains a form with single textbox. When user types in “l”, this textbox will load data from custom table and suggest possible value.

Technical side, we covered

  1. Creating custom table upon WordPress Plugin activation, also add some testing data
  2. Load built-in jQuery and custom scripts, styles
  3. Using Ajax/jQuery for textbox autocomplete

Please share if you find this tutorial helpful and don’t forget to leave a comment.

How To Unlock Desktop Screen After Remote Access Disconnected

Remote Desktop to VM to check out, investigate issues, deploy things are very common, especially when you are in CI/CD, Agile, DevOps environment. The demand to unlock desktop screen remotely is crucial for automation tests to run. A friend of mine says he struggled with this for 2 weeks. Therefore I am going to put simple and short answer right below.

How To Unlock Desktop Screen Remotely

Please note that you need to run these commands with administrative rights on remote machine.

Below command should work for Windows 7, Windows 8, Windows 8.1, Windows 10

tscon [RDC Session ID] /dest:console
Ex. tscon 1 /dest:console

Session ID can be retrieve by issuing below command

query session

Or simply use below single command

for /f "skip=1 tokens=2" %%s in ('query user %USERNAME%') do (
    tscon.exe %%s /dest:console


Below command should work on Windows Server

tscon %sessionname% /dest:console

If you have PowerShell installed on your remote machine, try this one

tscon ((quser $env:_TFSLab | select -Skip 1) -split '\s+')[2] /dest:console

Wrapping Up

That’s it. It’s simple when you know it and it can take you weeks if you don’t (like my friend’s case). Please share if you have any inputs or comment if these work for you.


Django with MariaDB Troubleshoot

If you are struggling with below error while deploying Django on VPS, this post may help and save you hours for MariaDB Troubleshoot.

  • Did you install mysqlclient or MySQL-python?
  • OSError: mysql_config not found
  • ModuleNotFoundError: No module named ‘ConfigParser’

This is my 2nd times try out Django with MariaDB. The 1st one went smoothly. Couple of searches and I find that I only need to add a simple line into “activate” file of Python VirtualEnv

2nd time didn’t go right, when running “python manage.py migrate“, I got “Did you install mysqlclient or MySQL-python?“. Continue trying to run “pip install mysqlclient“, I got “OSError: mysql_config not found“, and sometimes “ModuleNotFoundError: No module named ‘ConfigParser‘”

MariaDB Troubleshoot

I tried and installed many things and not quite sure which one resolved the issue. I do believe below helped me out

“yum install mariadb-devel”

After running above command, I was able to “pip install mysqlclient” and “python manage.py migrate”