Thanks for the answer, Jerremy!
Problem is that looking for the joining field is always made in baseModel and only first level joins are there. Luckily,
QDjangoCompiler::databaseColumn() method already has almost all what is needed. So, I took this method, simplified it, and made a new method to find correct model field from the relationship name:
const QDjangoMetaField QDjangoCompiler::foreignField(const QString &name)
{
QDjangoMetaModel model = baseModel;
QStringList bits = name.split(QLatin1String("__"));
while (bits.size() > 1) {
const QByteArray fk = bits.first().toLatin1();
QDjangoMetaModel foreignModel;
if (!model.foreignFields().contains(fk)) {
// this might be a reverse relation, so look for the model
// and if it exists continue
foreignModel = QDjango::metaModel(fk);
if (!foreignModel.isValid())
break;
} else {
foreignModel = QDjango::metaModel(model.foreignFields()[fk]);
}
model = foreignModel;
bits.takeFirst();
}
return model.localField(bits.join(QLatin1String("__")).toLatin1());
}
Then I changed line (2) in fromSql() to call this new method:
.arg(driver->escapeIdentifier(modelRefs[name].second.table(), QSqlDriver::TableName))
.arg(modelRefs[name].first)
.arg(modelRefs[name].first)
.arg(driver->escapeIdentifier(modelRefs[name].second.localField("pk").column(), QSqlDriver::FieldName))
.arg(reverseModelRefs.contains(name) ? databaseColumn(reverseModelRefs[name]) :
databaseColumn(name + QLatin1String("_id")));
}
return from;
}
Maybe this solution can be further refined, but with that change it seems to me that it is working correctly.
When I get same time, I will also add a test case, as you asked.
Regards,
Vitomir