Refactor Fields is actually the only way you can do this. Surprisingly, there is simply no way to reorder fields on a data level. You can change the presented order of fields in the qgis attribute table, but that is not stored in the data.
To actually manipulate the field order in the data, you have to recreate the dataset. This is bothersome and will be slow-ish, because not only do you need to manipulate the fields, but you will also have to rearrange the attributes of every single feature to match them.
Depending on your use case, it's probably gonna be easiest to simply call the existing refactor field algorithm from your pyqgis script, an example for that is given in the official docs
In your case, you would first add the attributes as you do already, then run refactorfields.
from qgis.core import *
from PyQt4.QtCore import QVariant
layer = processing.getObject(input)
layer.dataProvider().addAttributes([QgsField('x', QVariant.Integer),QgsField('y', QVariant.Long)])
result = processing.runalg('qgis:refactorfields',
# Expand field mapping as needed
output = QgsVectorLayer(result['OUTPUT_LAYER'],
To further explain the field mapping parameters:
- type | Any QVariant type. Note that these come from Qt4, not QGIS, and a lot of Qt4 types are not supported by QGis. This has been cause of concern for a while, and hopefully will be changed in Qgis 3. Just use the "basic" types that make sense in Qgis ;) .
- length | The length of the field (characters or digits)
- expression | Anything you'd put in the field calculator expression, you can use here. This includes dynamic variables such as @row_number
- name | The name the field should have
- precision | the number of digits after the decimal separator. Note that these are subtracted from length, so a field with length 7 and precision 4 can only reach 999.9999
The third parameter of the runalg is set to
None, so the new layer is created as a temp layer (
result['OUTPUT_LAYER']), but you can change that easily.
Alternatively, you can look at the source and steal the parts that are relevant for you if you need more optimization and running refactorfields would be overkill.
EDIT: Note that this is not an issue unique to QGIS, but a common issue (ArcGIS has it as well). This is because the big GIS players are based on the data specifications done eons ago for shapefiles and other geo formats.