4

i am using django-admin, and i have a model as following. it shows as a dropdown list in the admin. how can i order it by alphabet? instead of default user ID?

user= models.ForeignKey(User)
karthikr
  • 97,368
  • 26
  • 197
  • 188
Grey
  • 1,365
  • 4
  • 23
  • 34

6 Answers6

4

The problem you describe is, according to Django core devs, a feature, not a bug. In the beginning, Django ordered the User field alphabetically, but this resulted in a performance issue for really big sites (namely Pownce at the time) with hundreds of thousands of users. But instead of asking the few huge Django websites to implement a workaround, the ordering was simply removed, and now every site that has models with a ForeignKey to User has a usability problem.

I posted an ugly workaround on the Django issue tracker about a year ago. Daniel Roseman posted a similar (and IMHO better) solution in another Stackoverflow question.

Community
  • 1
  • 1
Benjamin Wohlwend
  • 30,958
  • 11
  • 90
  • 100
2

Why not at the level model?

class Meta:
    ordering = ['field',]

Or at the level admin?

class Admin:
    ordering       = ('field',)
Jason Plank
  • 2,336
  • 5
  • 31
  • 40
inigomedina
  • 1,791
  • 14
  • 21
  • simply because it is django.contrib, so you should not change it this way. you can but this is not a good idea to modify library for the single project. – Jerzyk Mar 22 '11 at 12:10
  • Sorry? I'm not talking about modifying any library. I was thinking on the proxy-models as stated in the documentation: "The standard User model has no ordering defined on it (intentionally; sorting is expensive and we don't want to do it all the time when we fetch users). You might want to regularly order by the username attribute when you use the proxy..." – inigomedina Mar 23 '11 at 15:26
  • But then - you will have different model in different namespace. So your foreign key will be to a different model. – Jerzyk Mar 23 '11 at 15:52
  • Yep, to the proxy-model. Clear enough, nop? No relation to your first comment, anyway, – inigomedina Mar 23 '11 at 16:01
0

Create a custom form for your model and assign it to your ModelAdmin subclass -- you can override the ordering for the ModelChoiceField in the form's __init__. For example:

# models.py
from django.db import models
from django.contrib.auth.models import User

class MyModel(models.Model):
    user = models.ForeignKey(User)
    # Other model fields ...

# forms.py
from django import forms
from django.contrib.auth.models import User
from myapp.models import MyModel

class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel

    def __init__(self, *args, **kwargs):
        super(MyModelForm, self).__init__(*args, **kwargs)
        self.fields['user'].queryset = User.objects.order_by('first_name', 'last_name')

# admin.py
from django.contrib import admin
from myapp.models import MyModel
from myapp.forms import MyModelForm

class MyModelAdmin(admin.ModelAdmin):
    form = MyModelForm
    # Other admin attributes ...

admin.site.register(MyModel, MyModelForm)
elo80ka
  • 14,837
  • 3
  • 36
  • 43
  • do u know why i always got "type object 'CollaboratorForm' has no attribute 'fields'" thanks – Grey Aug 17 '10 at 21:12
0

If you have not only 5 but a decent amount of users, it might make sense to change the Admin to use raw_id_fields for the user selection. That way, the users will be displayed in their own list view, allowing for filtering and sorting.

class MyAdmin(ModelAdmin):
    raw_id_fields = ['user']
Risadinha
  • 16,058
  • 2
  • 88
  • 91
0

Actually, Django provides much better way of doing this. It's even in their documentation http://docs.djangoproject.com/en/1.2/topics/db/models/#proxy-models

Jasmo
  • 808
  • 2
  • 9
  • 17
0

You can easily sort in your admin.py relevant Admin class.

Let's say your Admin class is the following:

@admin.register(UserStuff)
class UserStuffAdmin(admin.ModelAdmin):
    list_display = ['user', 'other', 'fields']
    ordering = ['user']

The line ordering = ['user'] will order by the user field. Alphabetically or numerically, depending on the field. Uses the field's normal ordering method. You can also do ordering = ['-user'] which will sort in descending order.

Source: https://docs.djangoproject.com/en/3.0/ref/contrib/admin/#django.contrib.admin.ModelAdmin.ordering

Blairg23
  • 11,334
  • 6
  • 72
  • 72