7

I've got a weird problem in django admin list_display. Whenever I add a foreign key to a list_display the whole change list view goes blank showing only the total no of entries.

models.py:

class Organization(models.Model):
    org_id = models.AutoField(primary_key=True)
    org_name = models.CharField(max_length=288)

    def __unicode__(self):
        return self.org_name

    class Meta:
        db_table = u'organization'

class Server(models.Model):
    server_id = models.AutoField(primary_key=True)
    server_name = models.CharField(max_length=135,verbose_name="Server Name")
    org = models.ForeignKey(Organization,verbose_name="Organization")   

    def __unicode__(self):
        return self.server_name

    class Meta:
        db_table = u'server'

admin.py:

class ServerAdmin(admin.ModelAdmin):
    list_display = ('server_name','org') 
admin.site.register(Server,ServerAdmin) 

Now I'd expect this code to show me the organization name in the ChangeList View, But instead I get this:

empty changelist :(

If I remove the org in the list_display of ServerAdmin class, I get this:

change list with data :(

I didn't modify the template or override any ModelAdmin methods. I'm using Mysql(5.1.58) as my database that comes with ubuntu 11.10 repository.

I'll be really glad if I could a get a sloution for this problem guys. Thanks in advance.

Pannu
  • 2,547
  • 2
  • 23
  • 29
  • In `models.py` I see `TlxServer` and in `admin.py` just `Server`. Is that a typo? – jcollado Jan 20 '12 at 13:09
  • You don't need to define a AutoField. Django automatically creates a primary key for each table. – dan-klasson Jan 20 '12 at 13:15
  • @jcollado: That's a typo :P its suppose to be 'Server` – Pannu Jan 20 '12 at 13:33
  • @dan-klasson: I got the models from a legacy database. I ran `inspectdb` and got the models and I got `IntegerField` for primary keys, So I changed them to `AutoFiled` – Pannu Jan 20 '12 at 13:35

4 Answers4

8

I second Stefano on the fact that null=True, blank=True is to be added. But, I think you only need to add it to the org_name field of the Organization model. That should make your way through. It has to be done because you have run inspectdb to create models from your legacy DB. And probably the organization table in the DB has an empty string stored. So, adding the above would allow the Admin to have a blank field/column displayed.

Moreover, you can also try using callbacks in situations where you don't want to make changes to your model definition like the above.

Sandip Agarwal
  • 1,890
  • 5
  • 28
  • 42
  • Alright! Had a similar situation with another model like `Organization` which had a `ForeignKey` to `User`. Thanks to you and the `django-debug-toolbar` Zero'd on `INNER JOINS` causing whole problem. `inspectdb` doesn't specify `null=True,balnk=True` and I was too lazy ;) to cross check models and the database. Thanks man I owe you one for solving this mysterious looking problem. – Pannu Jan 23 '12 at 06:03
  • Anytime Pannu. All are here to learn and I too have learnt from your problem. – Sandip Agarwal Jan 23 '12 at 06:05
3

Try adding null=True, blank=True to all your model fields.

Usually django admin will silenty fail (thus show no records in the list) if the row does not validate the model constraints.

Stefano
  • 18,083
  • 13
  • 64
  • 79
2

See: https://stackoverflow.com/a/163968/1104941

Does the following work for you?

admin.py:

class ServerAdmin(admin.ModelAdmin):
    list_display = ('server_name','org__org_name') 
admin.site.register(Server,ServerAdmin) 
Community
  • 1
  • 1
sgallen
  • 2,079
  • 13
  • 10
  • I tried your solution, although strange as it may sound, it didn't seem to work. It kept popping an error `'org__org_name' is not a callable or an attribute of 'ServerAdmin' or found in the model 'Server'.` thanks anyways man. – Pannu Jan 23 '12 at 06:06
  • You can't use terms that span relationships in list_display, which could be very helpful. A workaround is to define a method in the ModelAdmin subclass that returns the value you are looking for, and add that method's name to list_display. – glarrain Nov 30 '12 at 12:46
1

I had a similar problem and solved it like this (using your example):

class ServerAdmin(admin.ModelAdmin):
    list_display = ('server_name', 'get_org') 

    def get_org(self, obj):
        return obj.org.org_name

    get_org.short_description = 'Org'

admin.site.register(Server,ServerAdmin)
Medhat Gayed
  • 2,585
  • 20
  • 12