Django hide field when creating new object

Question:

I want to hide field name when user is creating new object, but it must be visible if user wants to edit this object.
I tried exclude method but it makes field invisible when i try to edit this field. for example i want to hide status field.

class Toys(BaseModel):
    name = models.CharField(max_length=255)
    tags = models.ManyToManyField(Tag, related_name='Item_tags')
    price = models.CharField(max_length=255)
    status = models.BooleanField(default=False)
Asked By: I.Jokhadze

||

Answers:

In the model admin that you register in your admin.py file you can overload the get_form(self, request, obj=None, **kwargs) method. As you can see it takes the obj argument, it is None only on add (not None on change).
From there you could mess around with the form to exclude the form field “name” from it only if the obj is None.

In Django 1.10 that method is in django.contrib.admin.options.ModelAdmin.get_form.

EDIT 1 (this is by far not the best solution)
I can’t give you a full solution here, but you can start with something like:

# admin.py

from django.contrib import admin

from models import Toys


class ToysModelAdmin(admin.ModelAdmin):

    def get_form(self, request, obj=None, **kwargs):
        # all the code you have in the original
        # django.contrib.admin.options.ModelAdmin.get_form
        # up to the last try except

        if obj is not None:
            defaults['fields'] = ('tags', 'price', 'status', )

        try:
            return modelform_factory(self.model, **defaults)
        except FieldError as e:
            raise FieldError(
                '%s. Check fields/fieldsets/exclude attributes of class %s.'
                % (e, self.__class__.__name__)
            )

admin.site.register(Toys, ToysModelAdmin)

EDIT 2 (this is a better example)

# admin.py

from collections import OrderedDict

from django.contrib import admin

from models import Toys


class ToysModelAdmin(admin.ModelAdmin):

    # this is not perfect as you'll need to keep track of your
    # model changes also here, but you won't accidentally add
    # a field that is not supposed to be editable
    _add_fields = ('tags', 'price', 'status', )

    def get_form(self, request, obj=None, **kwargs):
        model_form = super(ToysModelAdmin, self).get_form(
            request, obj, **kwargs
        )

        if obj is None:
            model_form._meta.fields = self._add_fields
            model_form.base_fields = OrderedDict(**[
                (field, model_form.base_fields[field])
                for field in self._add_fields
            ])

        return model_form
Answered By: McAbra

I had same problem.
I wanted to exclude some columns only in create form.

You can override get_exclude() method

from django.contrib import admin
from . import models

@admin.register(models.Toys)
class ToysAdmin(admin.ModelAdmin):
    def get_exclude(self, request, obj=None):
        exclude = list(super().get_exclude(request, obj) or [])
        if obj==None:
            # columns to exclude when it's create form
            exclude += ["status","column_to_hide_on_create"]
        return tuple(set(exclude))
Answered By: 김태엽
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.