6

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

1
  • @e4c5 I want to know if there is something in the documentation that allows me to define an order for _meta.get_fields() Commented Jan 11, 2017 at 16:50

4 Answers 4

6
+50

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:

  1. Each parent fields fetched in a recursive way.
  2. Remote fields.
  3. Local fields.
  4. Local many-to-many fields.
  5. 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.

Sign up to request clarification or add additional context in comments.

2 Comments

From my testing, they do come in the same order, but not a specific order. But this order changes if you restart the server
You were correct, my mistake was something else, I put the results in another dict which unordered them
1

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.

This is actually how a ModelForm is able to display all a models fields in the order they were defined.

Comments

0

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)

Comments

-4

Just add 'ordering' to the Class Meta:

class Model(models.Model):
    slug = models.SlugField()
    name = models.CharField(max_length=30)
    other_field = models.TextField(blank=True, null=True)


    class Meta:
        ordering = ('name',)

https://docs.djangoproject.com/en/1.10/ref/models/options/#ordering

2 Comments

happens to the best of us ;)
actually I just realized this is not the answer, this defines default ordering of objects in queries, not order of fields get from _meta.get_fields()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.