Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to display a custom field only in change view (admin)

I'm totally new in Python and Django :) and i need some help.

What i want to do:

I have a model Page and i need to add a custom field "message" when someone try to update one object.

Why? Because i'm building a revision system. This field, it's just an explanation about the change. So this field is not linked to the Page (but to another model PageRevision)

After some research i managed to add this field to my form in the admin.py file, like this:

class PageAdminForm(forms.ModelForm):
    # custom field not backed by database
    message = forms.CharField(required=False)

    class Meta:
        model = Page

it's working, my field is now displayed...But i don't want this field everywhere. Just when someone try to update a Page object. i have found this answer different-fields-for-add-and-change-pages-in-admin but it's not working for me because it's a custom field (i think).

The rest of my code in admin.py:

class PageAdmin(admin.ModelAdmin):
    form = PageAdminForm
    fields = ["title", "weight", "description", "message"]
    list_display = ["title", "weight", "description"]
    list_filter = ["updated_at"]

    def get_form(self, request, obj=None, **kwargs):
        if obj is None:
            # not working ?
            kwargs['exclude'] = ['message']
        # else:
        #     kwargs['exclude'] = ['message']
        return super(PageAdmin, self).get_form(request, obj, **kwargs)

    def save_model(self, request, obj, form, change):
        if not obj.id:
            obj.author = request.user
        obj.modified_by = request.user
        wiki_page = obj.save()

        # save page in revision table
        revision = PageRevision(change=change, obj=wiki_page,
                            request=request)
        # retrieve value in the custom field
        revision.message = form.cleaned_data['message']
        revision.save()

def get_form doesn't exclude my custom message field because i think it doesn't know is existence. If i put another field like title, it's works. So how to exclude the custom field from add view ?

Thanks :)

like image 779
Epok Avatar asked Mar 21 '23 10:03

Epok


1 Answers

You're right, it won't work this way, because 'message' is not a field found on the Page model and the ModelAdmin class will ignore the exclusion. You can achieve this in many ways, but I think the best way to do it is this:

class PageAdmin(admin.ModelAmin):
    change_form = PageAdminForm

    ...

    def get_form(self, request, obj=None, **kwargs):
       if obj is not None:
          kwargs['form'] = self.change_form

       return super(UserAdmin, self).get_form(request, obj, **defaults)

Basicaly here django will use an auto-generated ModelForm when adding a Page and your custom form when editing the Page. Django itself uses a similar technique to display different forms when adding and changing a User:

https://github.com/django/django/blob/stable/1.6.x/django/contrib/auth/admin.py (the interesting part is in line 68)

like image 188
ppetrid Avatar answered Apr 27 '23 00:04

ppetrid