2

A foreign key on a model is not appearing in the Django admin site. This is irrespective of whether the field is explicitly specified in a ModelAdmin instance (fields = ('title', 'field-that-does-not-show-up')) or not.

I realize there are many variables that could be causing this behavior.

class AdvertiserAdmin(admin.ModelAdmin):
    search_fields = ['company_name', 'website']
    list_display = ['company_name', 'website', 'user']


class AdBaseAdmin(admin.ModelAdmin):
    list_display = ['title', 'url', 'advertiser', 'since', 'updated', 'enabled']
    list_filter = ['updated', 'enabled', 'since', 'updated', 'zone']
    search_fields = ['title', 'url']

The problem is the advertiser foreign key is not showing up in the admin for AdBase

class Advertiser(models.Model):
    """ A Model for our Advertiser
    """
    company_name = models.CharField(max_length=255)
    website = models.URLField(verify_exists=True)
    user = models.ForeignKey(User)

    def __unicode__(self):
        return "%s" % self.company_name

    def get_website_url(self):
        return "%s" % self.website

class AdBase(models.Model):
    """
    This is our base model, from which all ads will inherit.
    The manager methods for this model will determine which ads to
    display return etc.

    """
    title = models.CharField(max_length=255)
    url = models.URLField(verify_exists=True)
    enabled = models.BooleanField(default=False)
    since = models.DateTimeField(default=datetime.now)
    expires_on=models.DateTimeField(_('Expires on'), blank=True, null=True)
    updated = models.DateTimeField(editable=False)

    # Relations
    advertiser = models.ForeignKey(Advertiser)
    category = models.ForeignKey(AdCategory)
    zone = models.ForeignKey(AdZone)

    # Our Custom Manager
    objects = AdManager()

    def __unicode__(self):
        return "%s" % self.title

    @models.permalink
    def get_absolute_url(self):
        return ('adzone_ad_view', [self.id])

    def save(self, *args, **kwargs):
        self.updated = datetime.now()
        super(AdBase, self).save(*args, **kwargs)

    def impressions(self, start=None, end=None):
        if start is not None:
            start_q=models.Q(impression_date__gte=start)
        else:
            start_q=models.Q()
        if end is not None:
            end_q=models.Q(impression_date__lte=end)
        else:
            end_q=models.Q()
        return self.adimpression_set.filter(start_q & end_q).count()

    def clicks(self, start=None, end=None):
        if start is not None:
            start_q=models.Q(click_date__gte=start)
        else:
            start_q=models.Q()
        if end is not None:
            end_q=models.Q(click_date__lte=end)
        else:
            end_q=models.Q()
        return self.adclick_set.filter(start_q & end_q).count()

class BannerAd(AdBase):
    """ A standard banner Ad """
    content = models.ImageField(upload_to="adzone/bannerads/")

The mystery deepens. I just tried to create a ModelForm object for both AdBase and BannerAd, and both generated fields for the advertiser. Some crazy admin things going on here...

powellc
  • 67
  • 1
  • 7

8 Answers8

5

I believe I've just run into exactly the same problem, but was able to debug it thanks to the help of persistent co-workers. :)

In short, if you look in the raw HTML source you'll find the field was always there - it's just that:

  • Django tries to be clever and put the form field inside a div with CSS class="form-row $FIELD_NAME",
  • The field's name was "advertiser", so the CSS class was "form-row advertiser",
  • ...Adblock Plus.

Adblock Plus will hide anything with the CSS class "advertiser", along with a hell of a lot of other CSS classes.

I consider this a bug in Django.

Josh Darnell
  • 11,304
  • 9
  • 38
  • 66
Pete
  • 66
  • 1
  • 1
  • Haha, can't believe it took me this long to okay this one. What a silly bug. Thanks guys! – powellc Nov 04 '12 at 02:24
  • You think Django should raise an exception when someone tries to create a container for an advert? I like it. – thepeer Feb 19 '13 at 17:05
  • We just had a similar issue in our application's admin list_display items. Thanks for providing a similar answer which lead us to the issue. – Ecno92 Mar 21 '23 at 12:57
4

Another very dumb cause of the same problem:

If there is only one instance of the related model, then the filter simply won't show. There is a has_output() method in RelatedFieldListFilter class that returns False in this case.

frnhr
  • 12,354
  • 9
  • 63
  • 90
4

maybe it is an encode error. I had the same problem, but when i added # -- coding: UTF-8 -- in the models.py, all fine.

Mark Hall
  • 53,938
  • 9
  • 94
  • 111
dshy336
  • 41
  • 2
1

It's a strange problem for sure. On the AdBase model if you change

advertiser = models.ForeignKey(Advertiser)

to

adver = models.ForeignKey(Advertiser)

then I believe it'll show up.

darren
  • 18,845
  • 17
  • 60
  • 79
0

We just ran into this problem.

It seems that if you call you field advertiser the in the admin the gets given an 'advertiser' class.

Then is then hidden by standard ad blocking plugins. If you view source your field will be there.

japr
  • 1
0

Powellc, do you have the models registered with their respective ModelAdmin class?

admin.site.register(Advertiser, AdvertiserAdmin) after the ModelAdmin definitions.

Max
  • 6,901
  • 7
  • 46
  • 61
  • Oh, yes. Sorry I was trying not to be verbose, but I suppose that's not a good thing with code. Yeah, the bottom registers both models with their ModelAdmins. Thanks for taking the time to look it over though! – powellc Apr 28 '11 at 15:13
0

You are talking about the list_display option, right?

Is the unicode-method for your related model set?

If the field is a ForeignKey, Django will display the unicode() of the related object

Also check this thread for some hints: Can "list_display" in a Django ModelAdmin display attributes of ForeignKey fields?

Community
  • 1
  • 1
arie
  • 18,737
  • 5
  • 70
  • 76
  • Thanks, but I've got unicode methods on both models. I've also tried to blow out both ModelAdmin's (i.e. just setting them to 'pass') and nothing seems to work... – powellc Apr 28 '11 at 15:23
  • Are there any fields showing up at all? I mean, if you don't define a ModelAdmin i wouldn't expect random fields to show up ("If you don't set list_display, the admin site will display a single column that displays the __unicode__() representation of each object."). Does your ForeignKey work in the change_form or in any other form? Can you access the related model in a shell session? Maybe you should show your model definitions too. – arie Apr 28 '11 at 15:32
  • Yeah, the models show up in the admin, and I can add them with the advertiser field just fine with the shell. It's just that the 'advertiser' foreign key field is not being picked up by the admin for some very strange reason. Thanks everyone for taking a look, man I love stack. (Also, I've appended the model defs to the question above) – powellc Apr 28 '11 at 15:42
  • Oh, and I'm actually talking about the "fields=()" method – powellc Apr 28 '11 at 15:48
  • But fields() controls the fields displayed in the change_form, not in the change_list (and your original question doesn't mention fields). So i am getting slightly confused ;-) Does it make a difference if you don't override the default manager for AdBase (objects = AdManager())? – arie Apr 28 '11 at 15:56
  • Sorry for the confusion. My problem is that a foreign key field on a model is not being displayed on the change form in the Django admin site. I was just commenting that even if I add a fields= method to the ModelAdmin, the advertiser field still does not appear. – powellc Apr 28 '11 at 16:01
  • Also, I just tried taking off the manager and it didn't change anything. – powellc Apr 28 '11 at 16:01
0

Try disabling your ad blocker. No, this is not a joke. I just ran into this exact problem.

pkoch
  • 2,682
  • 1
  • 19
  • 17