扩展django catridge产品会导致管理员出现Grapelli KeyError

时间:2016-10-17 08:40:26

标签: django mezzanine django-grappelli cartridge

我目前正在开发django / mezzanine / cartridge商店。

我的所有产品都有一个CAD文件和一个PDF文件,为了保持DRY,我创建了一个BaseProduct模型,其定义如下:

models.py

class BaseProduct(Product):
     cadfile = fields.FileField(upload_to="product", extensions=(".dwg",), blank=True, null=True)
     pdffile = fields.FileField(upload_to="product", blank=True, null=True)

     objects = SearchableManager()
     search_fields = ("title", "description")

     class Meta:
         abstract = True

此外,我还有其他产品类型,可以按如下方式对此基本产品类型进行子类化。

class CorniceProduct(BaseProduct):
     cornice_picture =  fields.FileField(upload_to="product", null=True, blank=True)
     ceiling_projection = models.IntegerField(null=True, blank=True)
     wall_height = models.IntegerField(null=True, blank=True)

class CeilingRoseProduct(BaseProduct):
     width = models.IntegerField(null=True, blank=True)
     height = models.IntegerField(null=True, blank=True)

这适用于模型,问题来自夹层管理区域,这主要来自cartridge/shop/admin.py文件。

admin.py

option_fields = [f.name for f in ProductVariation.option_fields()]


product_fieldsets = deepcopy(DisplayableAdmin.fieldsets)
product_fieldsets[0][1]["fields"].insert(2, "available")
product_fieldsets[0][1]["fields"].extend(["content", "categories", "pdffile", "cadfile"])
product_fieldsets = list(product_fieldsets)

other_product_fields = []
if settings.SHOP_USE_RELATED_PRODUCTS:
    other_product_fields.append("related_products")
if settings.SHOP_USE_UPSELL_PRODUCTS:
    other_product_fields.append("upsell_products")
if len(other_product_fields) > 0:
    product_fieldsets.append((_("Other products"), {
    "classes": ("collapse-closed",),
    "fields": tuple(other_product_fields)}))

product_list_display = ["admin_thumb", "title", "status", "available",
                    "admin_link"]
product_list_editable = ["status", "available"]

# If variations are used, set up the product option fields for managing
# variations. If not, expose the denormalised price fields for a product
# in the change list view.
if settings.SHOP_USE_VARIATIONS:
    product_fieldsets.insert(1, (_("Create new variations"),
        {"classes": ("create-variations",), "fields": option_fields}))
else:
    extra_list_fields = ["sku", "unit_price", "sale_price", "num_in_stock"]
    product_list_display[4:4] = extra_list_fields
    product_list_editable.extend(extra_list_fields)

class CorniceProductAdmin(ProductAdmin):
    cornice_additional_fieldsets = ("cornice_picture", "ceiling_projection", "wall_height" )
    fieldsets = product_fieldsets
    fieldsets.append((_("Cornice specific"), {
        "fields": tuple(cornice_additional_fieldsets)
   }))

admin.site.register(CorniceProduct, CorniceProductAdmin)

class CeilingRoseProductAdmin(ProductAdmin):
    rose_additional_fieldsets = ("width", "height")
    fieldsets = product_fieldsets
    #del fieldsets[4]
    fieldsets.append((_("Ceiling Rose specific"), {
        "fields": tuple(rose_additional_fieldsets)
    }))
    exclude = ('cornice_picture', 'ceiling_projection', 'wall_height',)

admin.site.register(CeilingRoseProduct, CeilingRoseProductAdmin)

当我进入管理区域编辑ceilingroseproduct时,我收到以下错误:

错误&回溯

Template error:
In template /home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/grappelli_safe/templates/admin/change_form.html, error at line 14
   Key 'cornice_picture' not found in 'CeilingRoseProductForm'. Choices are: _meta_title, available, cadfile, categories, content, description, expiry_date, gen_description, height, in_sitemap, keywords, option1, option2, pdffile, publish_date, related_products, slug, status, title, upsell_products, width.   4 : {% load i18n admin_urls admin_static admin_modify %}
   5 : 
   6 : <!-- JAVASCRIPTS -->
   7 : {% block javascripts %}
   8 :     {{ block.super }}
   9 :     {% url "admin:jsi18n" as jsi18nurl %}
   10 :     <script src="{{ jsi18nurl|default:"../../../jsi18n/" }}"></script>
   11 :     {{ media }}
   12 :     {% if inline_admin_formsets %}
   13 :     <script src="{% static "grappelli/js/admin/Inline.js" %}"></script>
   14 :     <script  src="{% static "grappel li/js/admin/CollapsedInlineFieldsets.js" %}"></script>
   15 :     {% endif %}
   16 : {% endblock %}
   17 : 
   18 : <!-- COLTYPE/BODYCLASS -->
   19 : {% block coltype %}colM{% endblock %}
   20 : {% block bodyclass %}{{ opts.app_label }}-{{ opts.object_name.lower }} change-form{% endblock %}
   21 : 
   22 : <!-- BREADCRUMBS -->
   23 : {% block breadcrumbs %}{% if not is_popup %}
   24 : <div class="breadcrumbs">


Traceback:

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/forms/forms.py" in __getitem__
  144.             field = self.fields[name]

During handling of the above exception ('cornice_picture'), another exception occurred:

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/core/handlers/exception.py" in inner
  39.             response = get_response(request)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/core/handlers/base.py" in _legacy_get_response
  249.             response = self._get_response(request)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/core/handlers/base.py" in _get_response
  217.                 response = self.process_exception_by_middleware(e, request)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/core/handlers/base.py" in _get_response
  215.                 response = response.render()

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/response.py" in render
  109.             self.content = self.rendered_content

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/response.py" in rendered_content
  86.         content = template.render(context, self._request)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/backends/django.py" in render
  66.             return self.template.render(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/base.py" in render
  208.                     return self._render(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/base.py" in _render
  199.         return self.nodelist.render(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/base.py" in render
  994.                 bit = node.render_annotated(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/base.py" in render_annotated
  961.             return self.render(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/loader_tags.py" in render
  174.         return compiled_parent._render(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/base.py" in _render
  199.         return self.nodelist.render(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/base.py" in render
  994.                 bit = node.render_annotated(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/base.py" in render_annotated
  961.             return self.render(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/loader_tags.py" in render
  174.         return compiled_parent._render(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/base.py" in _render
  199.         return self.nodelist.render(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/base.py" in render
  994.                 bit = node.render_annotated(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/base.py" in render_annotated
  961.             return self.render(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/loader_tags.py" in render
  70.                 result = block.nodelist.render(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/base.py" in render
  994.                 bit = node.render_annotated(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/base.py" in render_annotated
  961.             return self.render(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/loader_tags.py" in render
  70.                 result = block.nodelist.render(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/base.py" in render
  994.                 bit = node.render_annotated(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/base.py" in render_annotated
  961.             return self.render(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/defaulttags.py" in render
  209.                     nodelist.append(node.render_annotated(context))

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/base.py" in render_annotated
  961.             return self.render(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/loader_tags.py" in render
  210.                 return template.render(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/base.py" in render
  210.                 return self._render(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/base.py" in _render
  199.         return self.nodelist.render(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/base.py" in render
  994.                 bit = node.render_annotated(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/base.py" in render_annotated
  961.             return self.render(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/defaulttags.py" in render
  209.                     nodelist.append(node.render_annotated(context))

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/base.py" in render_annotated
  961.             return self.render(context)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/template/defaulttags.py" in render
  165.                 values = list(values)

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/contrib/admin/helpers.py" in __iter__
  115.                 yield AdminField(self.form, field, is_first=(i == 0))

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/contrib/admin/helpers.py" in __init__
  127.         self.field = form[field]  # A django.forms.BoundField instance

File "/home/vagrant/virtualenvs/mezzanine/lib/python3.4/site-packages/django/forms/forms.py" in __getitem__
  150.                     ', '.join(sorted(f for f in self.fields)),

Exception Type: KeyError at /admin/my_shop/ceilingroseproduct/add/
Exception Value: "Key 'cornice_picture' not found in 'CeilingRoseProductForm'. Choices are: _meta_title, available, cadfile, categories, content, description, expiry_date, gen_description, height, in_sitemap, keywords, option1, option2, pdffile, publish_date, related_products, slug, status, title, upsell_products, width."

可以通过umcommenting del fieldsets [4]行来修复它,但是这看起来非常h​​acky并且需要对每种产品类型进行这种覆盖,我并不是真的想做。

1 个答案:

答案 0 :(得分:1)

在Cartridge中查看此PR,这将成为您正在尝试做的事情的正式方式:

https://github.com/stephenmcd/cartridge/pull/293