I have been watching this thread since its beginnings because I am stuck with the same problem. Look at this scenario:
Two database tables

CUSTOMERS
customer_id INTEGER AUTOINCREMENT NOT NULL
name VARCHAR
city INTEGER NOT NULL DEFAULT 0

CITIES
city_id INTEGER AUTOINCREMENT NOT NULL
city_name VARCHAR

A model:
Qt Code:
  1. model = new QSqlRelationalTableModel(this);
  2. model->setTable("customers");
  3. model->setRelation(2, QSqlRelation("cities", "city_id", "city_name"));
  4. model->select();
To copy to clipboard, switch view to plain text mode 

"this" beeing the form on which there is a QTableView:

Qt Code:
  1. ui.tableView->setModel(model);
To copy to clipboard, switch view to plain text mode 

A QPushButton insertButton and a custom slot:

Qt Code:
  1. void MainWindow::on_insertButton_clicked(bool checked)
  2. {
  3. QSqlRecord rec = model->record();
  4.  
  5. rec.setValue("name", "Test Customer");
  6. rec.setValue("city_name", "London");
  7.  
  8. bool insert = model->insertRecord(-1, rec);
  9. bool submit = model->submit();
  10. }
To copy to clipboard, switch view to plain text mode 

The select statement upon which the model is created is like this:
"SELECT customers.customer_id, customers.name, cities.city_name
FROM customers, cities
WHERE customers.city = cities.city_id"
This is the return of model->query().lastQuery().

The QSqlRecord rec from above have the same fields: customer_id, name, city_name, which is obvious.
BUT if you run the code like this both insertRecord() and submit() return FALSE and the last error reported by model->lastError().text() is:
"Unknown column 'city_name' in 'field list' QMYSQL3 : QMYSQLResult". Surprisingly in the tableView there is a new row which contain the values used by the setRecord() calls.
You get the same result if you use a numerical value with rec.setValue() in line 6:
Qt Code:
  1. rec.setValue("city_name", 1);
To copy to clipboard, switch view to plain text mode 

QSqlTableModel::insertRecord() calls internally QSqlTableModel::insertRows() and QSqlTableModel::setRecord(). The new row is shown in the tableView and that means that only insertRows() worked but not setRecord().

Now change this line (6) to be like this:
Qt Code:
  1. rec.setValue("city", 1);
To copy to clipboard, switch view to plain text mode 
Both insertRecord() and submit() return TRUE, the record is added in the database (I have checked with MySQL Query Browser) but the field "city" is set to 0, which is the default value for the field and model->lastError().text() is empty. The record isn't shown in the tableView because there is no corresponding record in the related table "cities" to match the WHERE clause 'customers.city = cities.city_id'.

So the first way is not good (it generates SQL errors and no record added) the second one seems also not to be working (no SQL error, record added, but with a useless value in the field upon the relation is set). Until now I couldn't narrow it more than this. Which way??