5

Given the following models:

class Store(models.Model):
    name = models.CharField(max_length=150)

class ItemGroup(models.Model):
    group = models.CharField(max_length=100)
    code = models.CharField(max_length=20)

class ItemType(models.Model):
    store = models.ForeignKey(Store, on_delete=models.CASCADE, related_name="item_types")
    item_group = models.ForeignKey(ItemGroup)
    type = models.CharField(max_length=100)

Inline's handle adding multiple item_types to a Store nicely when viewing a single Store.

The content admin team would like to be able to edit stores and their types in bulk. Is there a simple way to implement Store.item_types in list_editable which also allows adding new records, similar to horizontal_filter? If not, is there a straightforward guide that shows how to implement a custom list_editable template? I've been Googling but haven't been able to come up with anything.

Also, if there is a simpler or better way to set up these models that would make this easier to implement, feel free to comment.

Nate Pinchot
  • 3,288
  • 24
  • 35

1 Answers1

1

How about making ItemType a ManyToManyField for Store?

To me it seems logical that if you're changing the ItemTypes available in a Store, you're changing a property of the Store (not the ItemType).

e.g.:

from django.db import models

class ItemGroup(models.Model):
    group = models.CharField(max_length=100)
    code = models.CharField(max_length=20)

class ItemType(models.Model):
    item_group = models.ForeignKey(ItemGroup)
    type = models.CharField(max_length=100)

class Store(models.Model):
    name = models.CharField(max_length=150)
    item_type = models.ManyToManyField(ItemType, related_name="store")

# admin
from django.contrib import admin

class StoreAdmin(admin.ModelAdmin):
    list_display=('name', 'item_type',)
    list_editable=('item_type',)

for model in [(Store, StoreAdmin), (ItemGroup,), (ItemType,)]:
    admin.site.register(*model)

I get an error here:

File "C:\Python27\lib\site-packages\django\contrib\admin\validation.py", line 43, in validate
% (cls.__name__, idx, field))
django.core.exceptions.ImproperlyConfigured: 'StoreAdmin.list_display[1]', 'item_type' is a ManyToManyField which is not supported.

Which I solved by commenting out lines 41-43 in django.contrib.admin.validation:

#if isinstance(f, models.ManyToManyField):
#    raise ImproperlyConfigured("'%s.list_display[%d]', '%s' is a ManyToManyField which is not supported."
#        % (cls.__name__, idx, field))

Probably not the ideal solution, but it seemed to work for me.

logworthy
  • 1,218
  • 2
  • 11
  • 23
  • First, my apologies that I had a typo'd plural on the `ItemType` model (fixed now). Wouldn't your implementation only allow 1 `ItemType` per `Store`? Stores definitely need to have multiple `ItemType`s. – Nate Pinchot Sep 07 '12 at 15:39
  • No, each store will be able to have any number of ItemTypes. Also can't say changing the django source is a good idea! – slackjake Sep 08 '12 at 09:04
  • 2
    slackjake - It sounds like multiple ItemType per Store is exactly something Nate wants. When I was testing, I expected that commenting out those lines would lead to some sort of error somewhere else in the code - and that I'd probably need to subclass ManyToManyField to get around it. Was quite surprised that it just worked straight away. – logworthy Sep 08 '12 at 22:55
  • @logworthy *"To me it seems logical that if you're changing the ItemTypes available in a Store, you're changing a property of the Store (not the ItemType)."* - I couldn't agree more. Coming from .NET ORMs and Rails it seemed completely backwards to me to implement a relationship between child and parent models by defining the relationship on the child instead of the parent. You are correct that multiple `ItemType`s per `Store` is exactly what I want. I'll give this a try on Monday when I'm back in the office. I'm also curious to see how this will affect the database schema. Thanks. – Nate Pinchot Sep 09 '12 at 04:14
  • @logworthy I tried out your suggested solution but didn't really get anywhere. I commented out the lines you referenced to bypass the exception, but I don't get any type of ability to edit that field. All that's displayed is a bunch of text similar to `` in that column. – Nate Pinchot Sep 12 '12 at 23:36
  • Not sure why that would be. Using the exact code I have up there, I can see a multiple-select widget, that allows me to select different item types for different stores and add new ones too. Any idea what you might be doing differently? (FYI: I was using Django 1.3.0 - have now upgraded to 1.4.1 and it still seems to work) [This is what the Admin Stores change list looks like to me...](https://docs.google.com/open?id=0BzGC0eRpo-OdOFZtWFlEeXVORGs) – logworthy Sep 15 '12 at 12:08
  • @logworthy Interesting. Let me give it a try with a blank project. Perhaps something else is going on. Thanks for the follow up. I'm marking yours as the accepted answer since it obviously works and I'm just missing something. – Nate Pinchot Sep 17 '12 at 14:56