Sfoglia il codice sorgente

Add is_public field to Product model (#2935)

master
Roel Bruggink 6 anni fa
parent
commit
a5096da38a

+ 7
- 0
.gitignore Vedi File

6
 /build/
6
 /build/
7
 /node_modules/
7
 /node_modules/
8
 
8
 
9
+# venv
10
+/bin/
11
+/lib/
12
+/share
13
+/pyvenv.cfg
14
+/pip-selfcheck.json
15
+
9
 # Vagrant
16
 # Vagrant
10
 .vagrant
17
 .vagrant
11
 
18
 

+ 5
- 0
src/oscar/apps/catalogue/abstract_models.py Vedi File

263
         _("Product structure"), max_length=10, choices=STRUCTURE_CHOICES,
263
         _("Product structure"), max_length=10, choices=STRUCTURE_CHOICES,
264
         default=STANDALONE)
264
         default=STANDALONE)
265
 
265
 
266
+    is_public = models.BooleanField(
267
+        _('Is public'),
268
+        default=True,
269
+        help_text=_("Show this product in search results and catalogue listings."))
270
+
266
     upc = NullCharField(
271
     upc = NullCharField(
267
         _("UPC"), max_length=64, blank=True, null=True, unique=True,
272
         _("UPC"), max_length=64, blank=True, null=True, unique=True,
268
         help_text=_("Universal Product Code (UPC) is an identifier for "
273
         help_text=_("Universal Product Code (UPC) is an identifier for "

+ 9
- 1
src/oscar/apps/catalogue/managers.py Vedi File

99
 
99
 
100
     def browsable(self):
100
     def browsable(self):
101
         """
101
         """
102
-        Excludes non-canonical products.
102
+        Excludes non-canonical products and non-public products
103
+        """
104
+        return self.filter(parent=None, is_public=True)
105
+
106
+    def browsable_dashboard(self):
107
+        """
108
+        Products that should be browsable in the dashboard.
109
+
110
+        Excludes non-canonical products, but includes non-public products.
103
         """
111
         """
104
         return self.filter(parent=None)
112
         return self.filter(parent=None)
105
 
113
 

+ 18
- 0
src/oscar/apps/catalogue/migrations/0015_product_is_public.py Vedi File

1
+# Generated by Django 2.1.5 on 2019-02-11 11:55
2
+
3
+from django.db import migrations, models
4
+
5
+
6
+class Migration(migrations.Migration):
7
+
8
+    dependencies = [
9
+        ('catalogue', '0014_auto_20181115_1953'),
10
+    ]
11
+
12
+    operations = [
13
+        migrations.AddField(
14
+            model_name='product',
15
+            name='is_public',
16
+            field=models.BooleanField(default=True, help_text='Show this product in search results and catalogue listings.', verbose_name='Is public'),
17
+        ),
18
+    ]

+ 8
- 1
src/oscar/apps/catalogue/views.py Vedi File

1
 from django.contrib import messages
1
 from django.contrib import messages
2
 from django.core.paginator import InvalidPage
2
 from django.core.paginator import InvalidPage
3
-from django.http import HttpResponsePermanentRedirect
3
+from django.http import Http404, HttpResponsePermanentRedirect
4
 from django.shortcuts import get_object_or_404, redirect
4
 from django.shortcuts import get_object_or_404, redirect
5
 from django.utils.http import urlquote
5
 from django.utils.http import urlquote
6
 from django.utils.translation import gettext_lazy as _
6
 from django.utils.translation import gettext_lazy as _
41
         if redirect is not None:
41
         if redirect is not None:
42
             return redirect
42
             return redirect
43
 
43
 
44
+        # Do allow staff members so they can test layout etc.
45
+        if not self.is_viewable(product, request):
46
+            raise Http404()
47
+
44
         response = super().get(request, **kwargs)
48
         response = super().get(request, **kwargs)
45
         self.send_signal(request, response, product)
49
         self.send_signal(request, response, product)
46
         return response
50
         return response
47
 
51
 
52
+    def is_viewable(self, product, request):
53
+        return product.is_public or request.user.is_staff
54
+
48
     def get_object(self, queryset=None):
55
     def get_object(self, queryset=None):
49
         # Check if self.object is already set to prevent unnecessary DB calls
56
         # Check if self.object is already set to prevent unnecessary DB calls
50
         if hasattr(self, 'object'):
57
         if hasattr(self, 'object'):

+ 1
- 1
src/oscar/apps/dashboard/catalogue/forms.py Vedi File

187
     class Meta:
187
     class Meta:
188
         model = Product
188
         model = Product
189
         fields = [
189
         fields = [
190
-            'title', 'upc', 'description', 'is_discountable', 'structure']
190
+            'title', 'upc', 'description', 'is_public', 'is_discountable', 'structure']
191
         widgets = {
191
         widgets = {
192
             'structure': forms.HiddenInput()
192
             'structure': forms.HiddenInput()
193
         }
193
         }

+ 1
- 1
src/oscar/apps/dashboard/catalogue/views.py Vedi File

124
         """
124
         """
125
         Build the queryset for this list
125
         Build the queryset for this list
126
         """
126
         """
127
-        queryset = Product.objects.browsable().base_queryset()
127
+        queryset = Product.objects.browsable_dashboard().base_queryset()
128
         queryset = self.filter_queryset(queryset)
128
         queryset = self.filter_queryset(queryset)
129
         queryset = self.apply_search(queryset)
129
         queryset = self.apply_search(queryset)
130
         return queryset
130
         return queryset

+ 28
- 0
tests/_site/apps/catalogue/migrations/0014_auto_20181115_1953.py Vedi File

1
+# Generated by Django 2.0.7 on 2018-11-15 19:53
2
+
3
+from django.db import migrations, models
4
+
5
+
6
+class Migration(migrations.Migration):
7
+
8
+    dependencies = [
9
+        ('catalogue', '0013_auto_20170821_1548'),
10
+    ]
11
+
12
+    operations = [
13
+        migrations.AlterField(
14
+            model_name='product',
15
+            name='date_created',
16
+            field=models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='Date created'),
17
+        ),
18
+        migrations.AlterField(
19
+            model_name='productimage',
20
+            name='display_order',
21
+            field=models.PositiveIntegerField(db_index=True, default=0, help_text='An image with a display order of zero will be the primary image for a product', verbose_name='Display order'),
22
+        ),
23
+        migrations.AlterField(
24
+            model_name='productrecommendation',
25
+            name='ranking',
26
+            field=models.PositiveSmallIntegerField(db_index=True, default=0, help_text='Determines order of the products. A product with a higher value will appear before one with a lower ranking.', verbose_name='Ranking'),
27
+        ),
28
+    ]

+ 18
- 0
tests/_site/apps/catalogue/migrations/0015_product_is_public.py Vedi File

1
+# Generated by Django 2.1.5 on 2019-02-11 11:55
2
+
3
+from django.db import migrations, models
4
+
5
+
6
+class Migration(migrations.Migration):
7
+
8
+    dependencies = [
9
+        ('catalogue', '0014_auto_20181115_1953'),
10
+    ]
11
+
12
+    operations = [
13
+        migrations.AddField(
14
+            model_name='product',
15
+            name='is_public',
16
+            field=models.BooleanField(default=True, help_text='Show this product in search results and catalogue listings.', verbose_name='Is public'),
17
+        ),
18
+    ]

+ 30
- 0
tests/functional/catalogue/test_catalogue.py Vedi File

46
         response = self.app.get(child_url)
46
         response = self.app.get(child_url)
47
         self.assertEqual(http_client.MOVED_PERMANENTLY, response.status_code)
47
         self.assertEqual(http_client.MOVED_PERMANENTLY, response.status_code)
48
 
48
 
49
+    def test_is_public_on(self):
50
+        product = create_product(upc="kleine-bats", is_public=True)
51
+
52
+        kwargs = {'product_slug': product.slug, 'pk': product.id}
53
+        url = reverse('catalogue:detail', kwargs=kwargs)
54
+        response = self.app.get(url)
55
+
56
+        self.assertTrue(response.status_code, 200)
57
+
58
+    def test_is_public_off(self):
59
+        product = create_product(upc="kleine-bats", is_public=False)
60
+
61
+        kwargs = {'product_slug': product.slug, 'pk': product.id}
62
+        url = reverse('catalogue:detail', kwargs=kwargs)
63
+        response = self.app.get(url, expect_errors=True)
64
+
65
+        self.assertTrue(response.status_code, 404)
66
+
49
 
67
 
50
 class TestProductListView(WebTestCase):
68
 class TestProductListView(WebTestCase):
51
 
69
 
73
 
91
 
74
         self.assertContains(page, "Page 1 of 2")
92
         self.assertContains(page, "Page 1 of 2")
75
 
93
 
94
+    def test_is_public_on(self):
95
+        product = create_product(upc="grote-bats", is_public=True)
96
+        page = self.app.get(reverse('catalogue:index'))
97
+        products_on_page = list(page.context['products'].all())
98
+        self.assertEqual(products_on_page, [product])
99
+
100
+    def test_is_public_off(self):
101
+        create_product(upc="kleine-bats", is_public=False)
102
+        page = self.app.get(reverse('catalogue:index'))
103
+        products_on_page = list(page.context['products'].all())
104
+        self.assertEqual(products_on_page, [])
105
+
76
 
106
 
77
 class TestProductCategoryView(WebTestCase):
107
 class TestProductCategoryView(WebTestCase):
78
 
108
 

+ 9
- 0
tests/functional/dashboard/test_catalogue.py Vedi File

84
         self.assertIn(product2, products_on_page)
84
         self.assertIn(product2, products_on_page)
85
         self.assertNotIn(product3, products_on_page)
85
         self.assertNotIn(product3, products_on_page)
86
 
86
 
87
+    def test_is_public(self):
88
+        # Can I still find non-public products in dashboard?
89
+        product = create_product(is_public=False, upc="kleine-bats")
90
+        page = self.get("%s?upc=%s" % (
91
+            reverse('dashboard:catalogue-product-list'), product.upc
92
+        ))
93
+        products_on_page = [row.record for row in page.context['products'].page.object_list]
94
+        self.assertEqual(products_on_page, [product])
95
+
87
 
96
 
88
 class TestAStaffUser(WebTestCase):
97
 class TestAStaffUser(WebTestCase):
89
     is_staff = True
98
     is_staff = True

Loading…
Annulla
Salva