Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgraded selectRelated to work like in the current Django version. #52

Merged
merged 8 commits into from Mar 7, 2018
25 changes: 20 additions & 5 deletions src/db/QDjangoMetaModel.cpp
Expand Up @@ -725,7 +725,7 @@ void QDjangoMetaModel::setForeignKey(QObject *model, const char *name, QObject *
/*!
Loads the given properties into a \a model instance.
*/
void QDjangoMetaModel::load(QObject *model, const QVariantList &properties, int &pos) const
void QDjangoMetaModel::load(QObject *model, const QVariantList &properties, int &pos, const QStringList &relatedFields) const
{
// process local fields
foreach (const QDjangoMetaField &field, d->localFields)
Expand All @@ -736,11 +736,26 @@ void QDjangoMetaModel::load(QObject *model, const QVariantList &properties, int
return;
foreach (const QByteArray &fkName, d->foreignFields.keys())
{
QObject *object = model->property(fkName + "_ptr").value<QObject*>();
if (object)
QString fkS(fkName);
if ( relatedFields.contains(fkS) )
{
const QDjangoMetaModel foreignMeta = QDjango::metaModel(d->foreignFields[fkName]);
foreignMeta.load(object, properties, pos);
QStringList nsl = relatedFields.filter(QRegExp("^" + fkS + "__")).replaceInStrings(QRegExp("^" + fkS + "__"),"");
QObject *object = model->property(fkName + "_ptr").value<QObject*>();
if (object)
{
const QDjangoMetaModel foreignMeta = QDjango::metaModel(d->foreignFields[fkName]);
foreignMeta.load(object, properties, pos, nsl);
}
}

if (relatedFields.isEmpty())
{
QObject *object = model->property(fkName + "_ptr").value<QObject*>();
if (object)
{
const QDjangoMetaModel foreignMeta = QDjango::metaModel(d->foreignFields[fkName]);
foreignMeta.load(object, properties, pos);
}
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/db/QDjangoMetaModel.h
Expand Up @@ -21,6 +21,7 @@
#include <QMap>
#include <QSharedDataPointer>
#include <QVariant>
#include <QStringList>

#include "QDjango_p.h"

Expand Down Expand Up @@ -75,7 +76,7 @@ class QDJANGO_DB_EXPORT QDjangoMetaModel
QStringList createTableSql() const;
bool dropTable() const;

void load(QObject *model, const QVariantList &props, int &pos) const;
void load(QObject *model, const QVariantList &props, int &pos, const QStringList &relatedFields = QStringList()) const;
bool remove(QObject *model) const;
bool save(QObject *model) const;

Expand Down
20 changes: 15 additions & 5 deletions src/db/QDjangoQuerySet.cpp
Expand Up @@ -99,7 +99,7 @@ QString QDjangoCompiler::databaseColumn(const QString &name)
return modelRef + QLatin1Char('.') + driver->escapeIdentifier(field.column(), QSqlDriver::FieldName);
}

QStringList QDjangoCompiler::fieldNames(bool recurse, QDjangoMetaModel *metaModel, const QString &modelPath, bool nullable)
QStringList QDjangoCompiler::fieldNames(bool recurse, const QStringList *fields, QDjangoMetaModel *metaModel, const QString &modelPath, bool nullable)
{
QStringList columns;
if (!metaModel)
Expand All @@ -117,7 +117,17 @@ QStringList QDjangoCompiler::fieldNames(bool recurse, QDjangoMetaModel *metaMode
foreach (const QByteArray &fkName, metaModel->foreignFields().keys()) {
QDjangoMetaModel metaForeign = QDjango::metaModel(metaModel->foreignFields()[fkName]);
bool nullableForeign = metaModel->localField(fkName + QByteArray("_id")).isNullable();
columns += fieldNames(recurse, &metaForeign, pathPrefix + QString::fromLatin1(fkName), nullableForeign);
QString fkS(fkName);
if ( (fields != 0) && (fields->contains(fkS) ) )
{
QStringList nsl = fields->filter(QRegExp("^" + fkS + "__")).replaceInStrings(QRegExp("^" + fkS + "__"),"");
columns += fieldNames(recurse, &nsl, &metaForeign, pathPrefix + QString::fromLatin1(fkName), nullableForeign);
}

if (fields == 0)
{
columns += fieldNames(recurse, 0, &metaForeign, pathPrefix + QString::fromLatin1(fkName), nullableForeign);
}
}
return columns;
}
Expand Down Expand Up @@ -335,7 +345,7 @@ bool QDjangoQuerySetPrivate::sqlLoad(QObject *model, int index)

const QDjangoMetaModel metaModel = QDjango::metaModel(m_modelName);
int pos = 0;
metaModel.load(model, properties.at(index), pos);
metaModel.load(model, properties.at(index), pos, this->relatedFields);
return true;
}

Expand Down Expand Up @@ -400,7 +410,7 @@ QDjangoQuery QDjangoQuerySetPrivate::insertQuery(const QVariantMap &fields) cons
foreach (const QString &name, fields.keys()) {
const QDjangoMetaField field = metaModel.localField(name.toLatin1());
fieldColumns << db.driver()->escapeIdentifier(field.column(), QSqlDriver::FieldName);
fieldHolders << QLatin1String("?");
fieldHolders << QString::fromLatin1(":%1").arg(name);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we touching insertQuery?

I think this change is what is causing the test build to fail

}

QDjangoQuery query(db);
Expand All @@ -423,7 +433,7 @@ QDjangoQuery QDjangoQuerySetPrivate::selectQuery() const
QDjangoWhere resolvedWhere(whereClause);
compiler.resolve(resolvedWhere);

const QStringList columns = compiler.fieldNames(selectRelated);
const QStringList columns = compiler.fieldNames(selectRelated, &this->relatedFields);
const QString where = resolvedWhere.sql(db);
const QString limit = compiler.orderLimitSql(orderBy, lowMark, highMark);
QString sql = QLatin1String("SELECT ") + columns.join(QLatin1String(", ")) + QLatin1String(" FROM ") + compiler.fromSql();
Expand Down
11 changes: 9 additions & 2 deletions src/db/QDjangoQuerySet.h
Expand Up @@ -296,7 +296,7 @@ template <class T>
QDjangoQuerySet limit(int pos, int length = -1) const;
QDjangoQuerySet none() const;
QDjangoQuerySet orderBy(const QStringList &keys) const;
QDjangoQuerySet selectRelated() const;
QDjangoQuerySet selectRelated(const QStringList &relatedFields = QStringList()) const;

int count() const;
QDjangoWhere where() const;
Expand Down Expand Up @@ -425,6 +425,7 @@ QDjangoQuerySet<T> QDjangoQuerySet<T>::all() const
other.d->highMark = d->highMark;
other.d->orderBy = d->orderBy;
other.d->selectRelated = d->selectRelated;
other.d->relatedFields = d->relatedFields;
other.d->whereClause = d->whereClause;
return other;
}
Expand Down Expand Up @@ -577,12 +578,18 @@ bool QDjangoQuerySet<T>::remove()
/** Returns a QDjangoQuerySet that will automatically "follow" foreign-key
* relationships, selecting that additional related-object data when it
* executes its query.
*
* \param relatedFields If provided it will follow only the listed foreign
* keys. This is handy for very complex DB structures and allows the user
* to limit the amount of retrieved data. If omitted, the basic functionality
* is preserved and the function will traverse all foreign key relationships.
*/
template <class T>
QDjangoQuerySet<T> QDjangoQuerySet<T>::selectRelated() const
QDjangoQuerySet<T> QDjangoQuerySet<T>::selectRelated(const QStringList &relatedFields) const
{
QDjangoQuerySet<T> other = all();
other.d->selectRelated = true;
other.d->relatedFields = relatedFields;
return other;
}

Expand Down
3 changes: 2 additions & 1 deletion src/db/QDjangoQuerySet_p.h
Expand Up @@ -61,7 +61,7 @@ class QDJANGO_DB_EXPORT QDjangoCompiler
public:
QDjangoCompiler(const char *modelName, const QSqlDatabase &db);
QString fromSql();
QStringList fieldNames(bool recurse, QDjangoMetaModel *metaModel = 0, const QString &modelPath = QString(), bool nullable = false);
QStringList fieldNames(bool recurse, const QStringList *fields = 0, QDjangoMetaModel *metaModel = 0, const QString &modelPath = QString(), bool nullable = false);
QString orderLimitSql(const QStringList &orderBy, int lowMark, int highMark);
void resolve(QDjangoWhere &where);

Expand Down Expand Up @@ -110,6 +110,7 @@ class QDJANGO_DB_EXPORT QDjangoQuerySetPrivate
QStringList orderBy;
QList<QVariantList> properties;
bool selectRelated;
QStringList relatedFields;

private:
Q_DISABLE_COPY(QDjangoQuerySetPrivate)
Expand Down