Repository: saleor/saleor

Issue:
Sub-categories are shown as top-level categories on Dashboard edit form
(Please take the time and describe the problem you're having before you propose a solution.)
When I go to edit/create a product, and assign it a category, I see all categories (top and second level) in a single-level dropdown.

### What I'm trying to achieve
I'd like to see the categories displayed according to the established hierarchy.
...

### Steps to reproduce the problem

1. Create a category.
2. Add 2 sub-categories.
3. Go to the create product screen.

Here, you will see the category dropdown, and that sub-categories are treated the same as top-level.

### What I expected to happen

A multi-level dropdown. For example, 
https://www.w3schools.com/bootstrap/tryit.asp?filename=trybs_ref_js_dropdown_multilevel_css&stacked=h
...

### What happened instead/how it failed

...

(Please include a stack trace if this problem results in a crash.)



Discussion:
I think that simpler solution would be to include names of ancestor categories e.g.:
- Category
- Category > Child A
- Category > Child B > Child C
etc.
Yes, that would be a simpler solution, and would certainly suffice.
However, I think it'd be a bit unwieldily for a high level of
sub-categories. It's probably reasonable to restrict the depth to three
though.

On Tue, Mar 13, 2018 at 9:58 AM, Marcin Gębala <notifications@github.com>
wrote:

> I think that simpler solution would be to include names of ancestor
> categories e.g.:
>
>    - Category
>    - Category > Child A
>    - Category > Child B > Child C
>    etc.
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/mirumee/saleor/issues/1887#issuecomment-372674118>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/ABtQnrKM1irF9o2CA-TomgGaKFNT-EULks5td9BzgaJpZM4SjQ9X>
> .
>



-- 
Joshua Fialkoff
<https://www.facebook.com/prof.fialkoff/>
<https://www.instagram.com/joshuafialkoff/>
<https://www.youtube.com/channel/UC7ysxr3B4DhS_3xSEPxuebQ>
support me on patreon (and get free stuff)
<https://www.patreon.com/joshuafialkoff>
www.joshuafialkoff.com

Hiya!

You can use `TreeNodeChoiceField` or `TreeNodeMultipleChoiceField` from django-mptt for that (already in saleor's dependencies, nothing to install). It works really well with the dashboard. See https://django-mptt.readthedocs.io/en/latest/forms.html#fields.
`TreeNodeChoiceField` seems totally fine for now. Maybe it's not the best looking option, but I would think of visual improvements once we rewrite this view in React.

Resolving patch:
diff --git a/saleor/dashboard/product/forms.py b/saleor/dashboard/product/forms.py
--- a/saleor/dashboard/product/forms.py
+++ b/saleor/dashboard/product/forms.py
@@ -7,13 +7,15 @@
 from django.utils.encoding import smart_text
 from django.utils.text import slugify
 from django.utils.translation import pgettext_lazy
+from mptt.forms import TreeNodeChoiceField
 
-from . import ProductBulkAction
 from ...product.models import (
-    AttributeChoiceValue, Collection, Product, ProductAttribute, ProductImage,
-    ProductType, ProductVariant, Stock, StockLocation, VariantImage)
+    AttributeChoiceValue, Category, Collection, Product, ProductAttribute,
+    ProductImage, ProductType, ProductVariant, Stock, StockLocation,
+    VariantImage)
 from ..widgets import RichTextEditorWidget
 from .widgets import ImagePreviewWidget
+from . import ProductBulkAction
 
 
 class RichTextField(forms.CharField):
@@ -134,7 +136,6 @@ def clean(self):
 
 
 class ProductForm(forms.ModelForm):
-
     class Meta:
         model = Product
         exclude = ['attributes', 'product_type', 'updated_at']
@@ -152,6 +153,7 @@ class Meta:
             'collections': pgettext_lazy(
                 'Add to collection select', 'Collections')}
 
+    category = TreeNodeChoiceField(queryset=Category.objects.all())
     collections = forms.ModelMultipleChoiceField(
         required=False, queryset=Collection.objects.all())
     description = RichTextField()


Test patch: