Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: Creating an Inline Formset Similar to the Admin Interface

I'm a Django newbie, and I have a question about reusing the inline formset of the admin interface in the production code. Consider the following model:

class Attribute(models.Model):
    name       = models.CharField(max_length=50)

class Person(models.Model):
    lastName   = models.CharField(max_length=50)
    firstName  = models.CharField(max_length=50)
    email      = models.CharField(max_length=50)
    attributes = models.ManyToManyField(Attribute, through='AttributeValue')

class AttributeValue(models.Model):
    person     = models.ForeignKey(Person, on_delete=models.CASCADE)
    attribute  = models.ForeignKey(Attribute, on_delete=models.PROTECT)
    isConsumer = models.BooleanField()
    value      = models.CharField(max_length=50)

The admin interface for this comes out beautifully. I used the following admin.py:

class AttributeValueInline(admin.TabularInline):
    model = AttributeValue
    extra = 3

class PersonAdmin(admin.ModelAdmin):
    list_display = ('lastName', 'firstName','email')
    fieldsets = [
       ('Name',        {'fields': ['firstName', 'lastName']}),
       ('Contact Info',{'fields': ['email','phoneNumber']})
    ]
    inlines = [AttributeValueInline]

admin.site.register(Person, PersonAdmin)
admin.site.register(Attribute)

This is almost exactly what I want. It looks like this: enter image description here

When I tried to implement the same in the non-admin website, I had to write quite a bit of code to do the inline formsets, form processing, in addition to the actual business logic. In addition to this, I faced the problem mentioned here.

I can't expose the admin interface to the end-user because we need to have a customized web design, and page flow. But, can I reuse parts of the admin interface code instead of re-implementing the same functionality?

Any other suggestions to reduce the code would be most welcome.

like image 881
Hemanth Avatar asked Dec 05 '13 16:12

Hemanth


People also ask

What is Django inline formset?

Django formset allows you to edit a collection of the same forms on the same page. It basically allows you to bulk edit a collection of objects at the same time.

What is the Django admin interface?

One of the most powerful parts of Django is the automatic admin interface. It reads metadata from your models to provide a quick, model-centric interface where trusted users can manage content on your site. The admin's recommended use is limited to an organization's internal management tool.

Is Django admin used in production?

Django's Admin is amazing. A built-in and fully functional interface that quickly gets in and allows data entry is priceless. Developers can focus on building additional functionality instead of creating dummy interfaces to interact with the database.

Is Django admin useful?

The Django admin application can use your models to automatically build a site area that you can use to create, view, update, and delete records. This can save you a lot of time during development, making it very easy to test your models and get a feel for whether you have the right data.


1 Answers

Here is the answer how to implement inline formsets like in Django admin http://kevindias.com/writing/django-class-based-views-multiple-inline-formsets/ However only CreateWiew is described. If you want to implement also UpdateView you need to do duplicate your code for it with a little tweaks

def get(self, request, *args, **kwargs):
    """
    Handles GET requests and instantiates blank versions of the form
    and its inline formsets.
    """
    self.object = self.get_object()
    form_class = self.get_form_class()
    form = self.get_form(form_class)
    sample_form = SampleFormSet(instance=self.object)
    return self.render_to_response(
        self.get_context_data(form=form,
                              sample_form=sample_form))

def post(self, request, *args, **kwargs):
    """
    Handles POST requests, instantiating a form instance and its inline
    formsets with the passed POST variables and then checking them for
    validity.
    """
    self.object = self.get_object()
    form_class = self.get_form_class()
    form = self.get_form(form_class)
    sample_form = SampleFormSet(self.request.POST, instance=self.object)
    if (form.is_valid() and sample_form.is_valid()):
        return self.form_valid(form, sample_form)
    else:
        return self.form_invalid(form, sample_form)

def form_valid(self, form, sample_form):
    """
    Called if all forms are valid. Creates a Recipe instance along with
    associated Ingredients and Instructions and then redirects to a
    success page.
    """
    self.object = form.save()
    sample_form.save()
    return HttpResponseRedirect(self.get_success_url())

and don`t forget to add DELETE formset field to your template

          {% for form in sample_form %}
          {{ form.id }}
          <div class="inline {{ sample_form.prefix }}">
              {{ form.description.errors }}
              {{ form.description.label_tag }}
              ...
              {{ form.DELETE }}
          </div>
          {% endfor %}
like image 150
RealGecko Avatar answered Sep 26 '22 14:09

RealGecko