Browse Source

Minor tweaks to category management

master
David Winterbottom 13 years ago
parent
commit
eeab925eb6

+ 7
- 6
oscar/apps/catalogue/abstract_models.py View File

@@ -71,7 +71,7 @@ class AbstractCategory(MP_Node):
71 71
             slug = slugify(self.name)
72 72
             if parent:
73 73
                 self.slug = '%s%s%s' % (parent.slug, self._slug_separator, slug)
74
-                self.full_name = '%s%s%s' % (parent.full_name, 
74
+                self.full_name = '%s%s%s' % (parent.full_name,
75 75
                                              self._full_name_separator, self.name)
76 76
             else:
77 77
                 self.slug = slug
@@ -92,17 +92,15 @@ class AbstractCategory(MP_Node):
92 92
                 slug_parts = [parent.slug]
93 93
                 name_parts = [parent.full_name]
94 94
                 curr_depth = parent.depth
95
-            self.__class__.update_subtree_properties(list(subtree), slug_parts, 
95
+            self.__class__.update_subtree_properties(list(subtree), slug_parts,
96 96
                                                 name_parts, curr_depth=curr_depth)
97 97
 
98 98
     @classmethod
99 99
     def update_subtree_properties(cls, nodes, slug_parts, name_parts, curr_depth):
100
-
101 100
         """
102
-            Update slugs and full_names of children in a subtree.
103
-            Assumes nodes were originally in DFS order.
101
+        Update slugs and full_names of children in a subtree.
102
+        Assumes nodes were originally in DFS order.
104 103
         """
105
-
106 104
         if nodes == []:
107 105
             return
108 106
 
@@ -142,6 +140,9 @@ class AbstractCategory(MP_Node):
142 140
         verbose_name_plural = 'Categories'
143 141
         verbose_name = 'Category'
144 142
 
143
+    def has_children(self):
144
+        return self.get_children().count() > 0
145
+
145 146
 
146 147
 class AbstractProductCategory(models.Model):
147 148
     """

+ 6
- 5
oscar/apps/catalogue/app.py View File

@@ -10,11 +10,11 @@ class BaseCatalogueApplication(Application):
10 10
     detail_view = ProductDetailView
11 11
     index_view = ProductListView
12 12
     category_view = ProductCategoryView
13
-    
13
+
14 14
     def get_urls(self):
15
-        urlpatterns = super(BaseCatalogueApplication, self).get_urls()        
15
+        urlpatterns = super(BaseCatalogueApplication, self).get_urls()
16 16
         urlpatterns += patterns('',
17
-            url(r'^$', self.index_view.as_view(), name='index'),       
17
+            url(r'^$', self.index_view.as_view(), name='index'),
18 18
             url(r'^(?P<product_slug>[\w-]*)-(?P<pk>\d+)/$', self.detail_view.as_view(), name='detail'),
19 19
             url(r'^(?P<category_slug>[\w-]+(/[\w-]+)*)/$', self.category_view.as_view(), name='category')
20 20
         )
@@ -22,8 +22,8 @@ class BaseCatalogueApplication(Application):
22 22
 
23 23
 
24 24
 class ReviewsApplication(Application):
25
-    reviews_app = reviews_app    
26
-    
25
+    reviews_app = reviews_app
26
+
27 27
     def get_urls(self):
28 28
         urlpatterns = super(ReviewsApplication, self).get_urls()
29 29
         urlpatterns += patterns('',
@@ -37,4 +37,5 @@ class CatalogueApplication(BaseCatalogueApplication, ReviewsApplication):
37 37
     Composite class combining Products with Reviews
38 38
     """
39 39
 
40
+
40 41
 application = CatalogueApplication()

oscar/apps/catalogue/migrations/0004_auto__add_unique_category_slug.py → oscar/apps/catalogue/migrations/0005_auto__add_unique_category_slug.py View File


+ 3
- 4
oscar/apps/dashboard/catalogue/forms.py View File

@@ -29,8 +29,7 @@ class CategoryForm(MoveNodeForm):
29 29
         return cleaned_data
30 30
 
31 31
     def is_slug_conflicting(self, name, ref_node_pk, position):
32
-        
33
-        #determine parent
32
+        # determine parent
34 33
         if ref_node_pk:
35 34
             ref_category = Category.objects.get(pk=ref_node_pk)
36 35
             if position == 'first-child':
@@ -40,11 +39,11 @@ class CategoryForm(MoveNodeForm):
40 39
         else:
41 40
             parent = None
42 41
 
43
-        #build full slug
42
+        # build full slug
44 43
         slug_prefix = (parent.slug + Category._slug_separator) if parent else ''
45 44
         slug = '%s%s' % (slug_prefix, slugify(name))
46 45
 
47
-        #check if slug is conflicting
46
+        # check if slug is conflicting
48 47
         try:
49 48
             category = Category.objects.get(slug=slug)
50 49
         except Category.DoesNotExist:

+ 12
- 2
oscar/apps/dashboard/catalogue/views.py View File

@@ -270,20 +270,30 @@ class CategoryListMixin(object):
270 270
 
271 271
 
272 272
 class CategoryCreateView(CategoryListMixin, generic.CreateView):
273
-    template_name = 'dashboard/catalogue/category_create.html'
273
+    template_name = 'dashboard/catalogue/category_form.html'
274 274
     model = Category
275 275
     form_class = CategoryForm
276 276
 
277
+    def get_context_data(self, **kwargs):
278
+        ctx = super(CategoryCreateView, self).get_context_data(**kwargs)
279
+        ctx['title'] = "Add a new category"
280
+        return ctx
281
+
277 282
     def get_success_url(self):
278 283
         messages.info(self.request, "Category created successfully")
279 284
         return super(CategoryCreateView, self).get_success_url()
280 285
 
281 286
 
282 287
 class CategoryUpdateView(CategoryListMixin, generic.UpdateView):
283
-    template_name = 'dashboard/catalogue/category_create.html'
288
+    template_name = 'dashboard/catalogue/category_form.html'
284 289
     model = Category
285 290
     form_class = CategoryForm
286 291
 
292
+    def get_context_data(self, **kwargs):
293
+        ctx = super(CategoryUpdateView, self).get_context_data(**kwargs)
294
+        ctx['title'] = "Update category '%s'" % self.object.name
295
+        return ctx
296
+
287 297
     def get_success_url(self):
288 298
         messages.info(self.request, "Category updated successfully")
289 299
         return super(CategoryUpdateView, self).get_success_url()

oscar/templates/dashboard/catalogue/category_create.html → oscar/templates/dashboard/catalogue/category_form.html View File

@@ -3,7 +3,7 @@
3 3
 {% block body_class %}catalogue{% endblock %}
4 4
 
5 5
 {% block title %}
6
-Category management | {{ block.super }}
6
+{{ title }} | Category management | {{ block.super }}
7 7
 {% endblock %}
8 8
 
9 9
 {% block breadcrumbs %}
@@ -16,25 +16,20 @@ Category management | {{ block.super }}
16 16
         <a href="{% url dashboard:catalogue-category-list %}">Categories</a>
17 17
         <span class="divider">/</span>
18 18
     </li>
19
-    <li class="active"><a href=".">{% if object %}Update category{% else %}Add a category{% endif %}</a></li>
19
+	<li class="active"><a href=".">{{ title }}</a></li>
20 20
 </ul>
21 21
 {% endblock %}
22 22
 
23 23
 {% block header %}
24 24
 <div class="page-header action">
25
-    <h1>{% if object %}Update category{% else %}Add a category{% endif %}</h1>
25
+	<h1>{{ title }}</h1>
26 26
 </div>
27 27
 {% endblock header %}
28 28
 
29 29
 {% block dashboard_content %}
30
-
31
-<form action="." method="post">{% csrf_token %}
32
-    {{ form.as_p }}
33
-    <input type="submit" value="Save" />
34
-</form>
35
-
36
-<div class="sub-header">
37
-    <h2>{{ queryset_description }}</h2>
38
-</div>
39
-
30
+	<form action="." method="post" enctype="multipart/form-data">{% csrf_token %}
31
+		{{ form.as_p }}
32
+		<button type="submit" class="btn btn-primary btn-large">Save</button> or
33
+		<a href="{% url dashboard:catalogue-category-list %}">cancel</a>
34
+	</form>
40 35
 {% endblock dashboard_content %}

+ 23
- 18
oscar/templates/dashboard/catalogue/category_list.html View File

@@ -12,7 +12,7 @@ Category management | {{ block.super }}
12 12
         <a href="{% url dashboard:index %}">Dashboard</a>
13 13
         <span class="divider">/</span>
14 14
     </li>
15
-    <li class="active"><a href=".">Categories</a></li>
15
+    <li class="active"><a href=".">Category management</a></li>
16 16
 </ul>
17 17
 {% endblock %}
18 18
 
@@ -25,38 +25,43 @@ Category management | {{ block.super }}
25 25
 {% block dashboard_content %}
26 26
 
27 27
 <div class="well well-info">
28
-    <h3 class="app-ico ico_expand icon"><a href="{% url dashboard:catalogue-category-create %}">Create a new category</a></h3>
29
-</div>
30
-
31
-<div class="well well-info">
32
-    <a href="{% url dashboard:catalogue-category-list %}">Home</a> >
28
+	<p>You are editing:
29
+    <a href="{% url dashboard:catalogue-category-list %}">Home</a>
33 30
     {% if ancestors %}
31
+	    &gt;
34 32
         {% for ancestor in ancestors %}
35 33
             <a href="{% url dashboard:catalogue-category-detail-list pk=ancestor.pk %}">{{ ancestor.name }}</a>{% if not forloop.last %} > {% endif %}
36 34
         {% endfor %}
37 35
     {% endif %}
36
+	</p>
38 37
 </div>
39 38
 
40 39
 <table class="table table-striped table-bordered">
40
+	<thead>
41
+		<tr>
42
+			<th>Name</th>
43
+			<th>Description</th>
44
+			<th>Number of child categories</th>
45
+			<th></th>
46
+		</tr>
47
+	</thead>
48
+	<tbody>
41 49
     {% for category in child_categories %}
42 50
         <tr>
51
+            <td>{{ category.name }}</td>
52
+			<td>{{ category.description|default:""|truncatewords:6 }}</td>
53
+			<td>{{ category.get_children_count }}</td>
43 54
             <td>
44
-            {% if category.get_children_count > 0 %}
45
-                <a href="{% url dashboard:catalogue-category-detail-list pk=category.pk %}">{{ category.name }}</a>
46
-            {% else %}
47
-                {{ category.name }}
48
-            {% endif %}
49
-            </td>
50
-            <td>
51
-                <a class="btn btn-primary" href="{% url dashboard:catalogue-category-update category.id %}">Edit</a>
52
-                <a class="btn btn-success" href="{% url dashboard:catalogue-category-delete category.id %}">Delete</a>
55
+                <a class="btn btn-primary" href="{% url dashboard:catalogue-category-update category.id %}">Edit category</a>
56
+				<a class="btn btn-primary {% if not category.has_children %}disabled{% endif %}" href="{% url dashboard:catalogue-category-detail-list pk=category.pk %}">Edit children</a>
57
+				<a class="btn btn-info" href="{{ category.get_absolute_url }}">View on site</a>
58
+                <a class="btn btn-danger" href="{% url dashboard:catalogue-category-delete category.id %}">Delete</a>
53 59
             </td>
54 60
         </tr>
55 61
     {% endfor %}
62
+	</tbody>
56 63
 </table>
57 64
 
58
-<div class="sub-header">
59
-    <h2>{{ queryset_description }}</h2>
60
-</div>
65
+<a class="btn btn-large btn-primary" href="{% url dashboard:catalogue-category-create %}">Create a new category</a>
61 66
 
62 67
 {% endblock dashboard_content %}

+ 10
- 0
tests/unit/catalogue_tests.py View File

@@ -115,6 +115,16 @@ class TestCategoryFactory(TestCase):
115 115
         self.assertEqual(child.full_name, 'E > F')
116 116
 
117 117
 
118
+class TestCategory(TestCase):
119
+
120
+    def test_supports_has_children_method(self):
121
+        """Supports has_children method"""
122
+        root = Category.add_root(name="Products")
123
+        self.assertFalse(root.has_children())
124
+        root.add_child(name="Books")
125
+        self.assertTrue(root.has_children())
126
+
127
+
118 128
 class ProductTests(TestCase):
119 129
 
120 130
     def setUp(self):

Loading…
Cancel
Save