[PyQt] PyQt 5.7, QSqlQueryModel.data() sub-classed override bug?

Phil Thompson phil at riverbankcomputing.com
Wed May 16 11:30:55 BST 2018

On 16 May 2018, at 11:27 am, J Barchan <jnbarchan at gmail.com> wrote:
> ​Dear Phil,
> I previously wrote that I had had to give up on overriding QSqlQueryModel.data() because​ none of the solutions we discussed (concerning return type of native Python type versus QVariant type) worked acceptably for me.  I have since discovered that, for various reasons, I have to provide a Python override of that method.
> I have revisited this issue, and have come up with a solution which seems to work in all cases but which we did not propose between the two of us.
> Reminder of problems:
> 	• Without the sip.enableautoconversion(QVariant, False) call, overridden QSqlQueryModel.data() definition, at least when called on database NULL value for role DisplayRole, would return a "default" value string like 0 or '', which is wrong (I need blank/empty).
> 	• With the sip.enableautoconversion(QVariant, False) call, and returning the QVariant as-is, solved the above case perfectly but meant that Python callers of the method would need to be changed to call QVariant.value() on the return result to behave as before now, which is not at all good for the existing code I have inherited.
> There did not seem to be an alternative which just "worked" for me.  I have now come up with the following override code:
> def data(self, item: QtCore.QModelIndex, role: QtCore.Qt.ItemDataRole = QtCore.Qt.DisplayRole):
>     was_enabled = sip.enableautoconversion(QtCore.QVariant, False)
>     v = super().data(item, role)
>     sip.enableautoconversion(QtCore.QVariant, was_enabled)
>     if not v.isValid() or v.isNull():
>         return None
>     else:
>         return v.value()
> Note how:
> 	• In the invalid or NULL cases, it explicitly returns Python native None.  That is instead of v.value(), which would have returned 0 or ''.  This solves Problem #1 above.
> 	• In the valid, non-NULL case, it returns QVariant.value(), i.e. native Python type, keeping Python callers unchanged.  This solves Problem #2 above.
> Would you kindly comment whether you agree this definition is acceptable?  Do you see any pitfalls, or need to change any code here (e.g. based on role value)?  I can only say that I have tried running with this, and am finding all the cases I can see are working correctly/as desired, but cannot be sure there is a case I have not thought of....
> I'd really appreciate your feedback on this (hoping you'll agree with me!!), thank you.

It seems fine so long as your use case doesn't require you to distinguish between null and invalid values.


More information about the PyQt mailing list