'Django get Model fields in order
Is there a way to get them in code order, or set an order for the fields of a Django Model? When I call MyModel._meta.get_fields() they come unordered (altough is the same 'unordered' order as long as you don't reset the server it seems).
If possible, without having to change the base lib of overwrite any methods
I've read about ordering in Forms https://docs.djangoproject.com/en/1.9/ref/forms/api/#django.forms.Form.order_fields, but not in the Model itself
The meta property 'ordering' only defines default ordering of objects when making a query
Solution 1:[1]
Actually get_fields() returns fields in a fixed order.
Take a look into django example:
>>> from django.contrib.auth.models import User
>>> User._meta.get_fields()
(<ManyToOneRel: admin.logentry>,
<django.db.models.fields.AutoField: id>,
<django.db.models.fields.CharField: password>,
<django.db.models.fields.DateTimeField: last_login>,
<django.db.models.fields.BooleanField: is_superuser>,
<django.db.models.fields.CharField: username>,
<django.db.models.fields.CharField: first_name>,
<django.db.models.fields.CharField: last_name>,
<django.db.models.fields.EmailField: email>,
<django.db.models.fields.BooleanField: is_staff>,
<django.db.models.fields.BooleanField: is_active>,
<django.db.models.fields.DateTimeField: date_joined>,
<django.db.models.fields.related.ManyToManyField: groups>,
<django.db.models.fields.related.ManyToManyField: user_permissions>)
I've repeated this code and got the same results. If you will go deeper and look into the sources, you will find that the order is the following:
- Each
parentfields fetched in a recursive way. - Remote fields.
- Local fields.
- Local many-to-many fields.
- Private fields.
All that says that if you define some trivial field before some other trivial field in your model, you will always get it in the same order in get_fields() results.
But be careful on relying on a non-documented behaviour, so it could be changed in a future without any warning.
Solution 2:[2]
If you want to get a list of all fields defined in your model in the order that you defined them in, then you can the following class method to your model definition. (or take the body of the function and move it wherever you feel like)
import itertools
from django.db.models.fields import Field
@classmethod
def getModelFields(cls):
#Pulled this from djangos ModelForm source code
sortable_private_fields = [f for f in cls._meta.private_fields if isinstance(f, Field)]
return sorted(itertools.chain(cls._meta.concrete_fields, sortable_private_fields, cls._meta.many_to_many))
This works because django's Field class defines custom __eq__ and __lt__ methods that reference an internal creation_counter. This allows us to construct a list of all the fields on the model, and simply use sorted to get them in the order.
Solution 3:[3]
Use User._meta.fields to get Model fields in order.
for e in User._meta.fields:
t = e.get_internal_type()
print(t, e.name)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | vasi1y |
| Solution 2 | |
| Solution 3 | Rajiv Sharma |
