Browse Source

Clean up pep8 errors in oscar.apps.catalogue

master
David Winterbottom 13 years ago
parent
commit
c8a780f60b

+ 170
- 96
oscar/apps/catalogue/abstract_models.py View File

12
 from treebeard.mp_tree import MP_Node
12
 from treebeard.mp_tree import MP_Node
13
 
13
 
14
 from oscar.core.loading import get_class
14
 from oscar.core.loading import get_class
15
-BrowsableProductManager = get_class('catalogue.managers', 'BrowsableProductManager')
15
+BrowsableProductManager = get_class('catalogue.managers',
16
+                                    'BrowsableProductManager')
16
 
17
 
17
 
18
 
18
 class AbstractProductClass(models.Model):
19
 class AbstractProductClass(models.Model):
19
     """
20
     """
20
-    Defines the options and attributes for a group of products, e.g. Books, DVDs and Toys.
21
+    Defines the options and attributes for a group of products, e.g. Books,
22
+    DVDs and Toys.
21
 
23
 
22
     Not necessarily equivalent to top-level categories but usually will be.
24
     Not necessarily equivalent to top-level categories but usually will be.
23
     """
25
     """
26
 
28
 
27
     # Some product type don't require shipping (eg digital products) - we use
29
     # Some product type don't require shipping (eg digital products) - we use
28
     # this field to take some shortcuts in the checkout.
30
     # this field to take some shortcuts in the checkout.
29
-    requires_shipping = models.BooleanField(_("Requires shipping?"), default=True)
31
+    requires_shipping = models.BooleanField(_("Requires shipping?"),
32
+                                            default=True)
30
 
33
 
31
-    # Digital products generally don't require their stock levels to be tracked.
34
+    # Digital products generally don't require their stock levels to be
35
+    # tracked.
32
     track_stock = models.BooleanField(_("Track stock levels?"), default=True)
36
     track_stock = models.BooleanField(_("Track stock levels?"), default=True)
33
 
37
 
34
     # These are the options (set by the user when they add to basket) for this
38
     # These are the options (set by the user when they add to basket) for this
35
     # item class.  For instance, a product class of "SMS message" would always
39
     # item class.  For instance, a product class of "SMS message" would always
36
     # require a message to be specified before it could be bought.
40
     # require a message to be specified before it could be bought.
37
-    options = models.ManyToManyField('catalogue.Option', blank=True, verbose_name=_("Options"))
41
+    options = models.ManyToManyField('catalogue.Option', blank=True,
42
+                                     verbose_name=_("Options"))
38
 
43
 
39
     class Meta:
44
     class Meta:
40
         abstract = True
45
         abstract = True
59
     """
64
     """
60
     name = models.CharField(_('Name'), max_length=255, db_index=True)
65
     name = models.CharField(_('Name'), max_length=255, db_index=True)
61
     description = models.TextField(_('Description'), blank=True, null=True)
66
     description = models.TextField(_('Description'), blank=True, null=True)
62
-    image = models.ImageField(_('Image'), upload_to='categories', blank=True, null=True)
63
-    slug = models.SlugField(_('Slug'), max_length=1024, db_index=True, editable=False)
64
-    full_name = models.CharField(_('Full Name'), max_length=1024, db_index=True, editable=False)
67
+    image = models.ImageField(_('Image'), upload_to='categories', blank=True,
68
+                              null=True)
69
+    slug = models.SlugField(_('Slug'), max_length=1024, db_index=True,
70
+                            editable=False)
71
+    full_name = models.CharField(_('Full Name'), max_length=1024,
72
+                                 db_index=True, editable=False)
65
 
73
 
66
     _slug_separator = '/'
74
     _slug_separator = '/'
67
     _full_name_separator = ' > '
75
     _full_name_separator = ' > '
74
             parent = self.get_parent()
82
             parent = self.get_parent()
75
             slug = slugify(self.name)
83
             slug = slugify(self.name)
76
             if parent:
84
             if parent:
77
-                self.slug = '%s%s%s' % (parent.slug, self._slug_separator, slug)
85
+                self.slug = '%s%s%s' % (parent.slug,
86
+                                        self._slug_separator, slug)
78
                 self.full_name = '%s%s%s' % (parent.full_name,
87
                 self.full_name = '%s%s%s' % (parent.full_name,
79
-                                             self._full_name_separator, self.name)
88
+                                             self._full_name_separator,
89
+                                             self.name)
80
             else:
90
             else:
81
                 self.slug = slug
91
                 self.slug = slug
82
                 self.full_name = self.name
92
                 self.full_name = self.name
89
             pass
99
             pass
90
         else:
100
         else:
91
             if match.id != self.id:
101
             if match.id != self.id:
92
-                raise ValidationError(_("A category with slug '%(slug)s' already exists") % {'slug': self.slug})
102
+                raise ValidationError(
103
+                    _("A category with slug '%(slug)s' already exists") % {
104
+                        'slug': self.slug})
93
         super(AbstractCategory, self).save(*args, **kwargs)
105
         super(AbstractCategory, self).save(*args, **kwargs)
94
 
106
 
95
     def move(self, target, pos=None):
107
     def move(self, target, pos=None):
106
                 slug_parts = [parent.slug]
118
                 slug_parts = [parent.slug]
107
                 name_parts = [parent.full_name]
119
                 name_parts = [parent.full_name]
108
                 curr_depth = parent.depth
120
                 curr_depth = parent.depth
109
-            self.__class__.update_subtree_properties(list(subtree), slug_parts,
110
-                                                name_parts, curr_depth=curr_depth)
121
+            self.__class__.update_subtree_properties(
122
+                list(subtree), slug_parts, name_parts, curr_depth=curr_depth)
111
 
123
 
112
     @classmethod
124
     @classmethod
113
-    def update_subtree_properties(cls, nodes, slug_parts, name_parts, curr_depth):
125
+    def update_subtree_properties(cls, nodes, slug_parts, name_parts,
126
+                                  curr_depth):
114
         """
127
         """
115
         Update slugs and full_names of children in a subtree.
128
         Update slugs and full_names of children in a subtree.
116
         Assumes nodes were originally in DFS order.
129
         Assumes nodes were originally in DFS order.
135
             name_parts = name_parts[:-1]
148
             name_parts = name_parts[:-1]
136
             curr_depth -= 1
149
             curr_depth -= 1
137
 
150
 
138
-        cls.update_subtree_properties(nodes, slug_parts, name_parts, curr_depth)
151
+        cls.update_subtree_properties(
152
+            nodes, slug_parts, name_parts, curr_depth)
139
 
153
 
140
     def get_ancestors(self, include_self=True):
154
     def get_ancestors(self, include_self=True):
141
         ancestors = list(super(AbstractCategory, self).get_ancestors())
155
         ancestors = list(super(AbstractCategory, self).get_ancestors())
146
     @models.permalink
160
     @models.permalink
147
     def get_absolute_url(self):
161
     def get_absolute_url(self):
148
         return ('catalogue:category', (), {
162
         return ('catalogue:category', (), {
149
-                'category_slug': self.slug })
163
+                'category_slug': self.slug})
150
 
164
 
151
     class Meta:
165
     class Meta:
152
         abstract = True
166
         abstract = True
166
     Joining model between products and categories.
180
     Joining model between products and categories.
167
     """
181
     """
168
     product = models.ForeignKey('catalogue.Product', verbose_name=_("Product"))
182
     product = models.ForeignKey('catalogue.Product', verbose_name=_("Product"))
169
-    category = models.ForeignKey('catalogue.Category', verbose_name=_("Category"))
170
-    is_canonical = models.BooleanField(_('Is Cannonical'), default=False, db_index=True)
183
+    category = models.ForeignKey('catalogue.Category',
184
+                                 verbose_name=_("Category"))
185
+    is_canonical = models.BooleanField(_('Is Cannonical'), default=False,
186
+                                       db_index=True)
171
 
187
 
172
     class Meta:
188
     class Meta:
173
         abstract = True
189
         abstract = True
181
 
197
 
182
 class AbstractContributorRole(models.Model):
198
 class AbstractContributorRole(models.Model):
183
     """
199
     """
184
-    A role that may be performed by a contributor to a product, eg Author, Actor, Director.
200
+    A role that may be performed by a contributor to a product, eg Author,
201
+    Actor, Director.
185
     """
202
     """
186
     name = models.CharField(_('Name'), max_length=50)
203
     name = models.CharField(_('Name'), max_length=50)
187
     name_plural = models.CharField(_('Name Plural'), max_length=50)
204
     name_plural = models.CharField(_('Name Plural'), max_length=50)
203
 
220
 
204
 class AbstractContributor(models.Model):
221
 class AbstractContributor(models.Model):
205
     """
222
     """
206
-    Represents a person or business that has contributed to a product in some way. eg an author.
223
+    Represents a person or business that has contributed to a product in some
224
+    way. eg an author.
207
     """
225
     """
208
     name = models.CharField(_("Name"), max_length=255)
226
     name = models.CharField(_("Name"), max_length=255)
209
     slug = models.SlugField(_("Slug"), max_length=255, unique=False)
227
     slug = models.SlugField(_("Slug"), max_length=255, unique=False)
216
         verbose_name = _('Contributor')
234
         verbose_name = _('Contributor')
217
         verbose_name_plural = _('Contributors')
235
         verbose_name_plural = _('Contributors')
218
 
236
 
219
-
220
     def save(self, *args, **kwargs):
237
     def save(self, *args, **kwargs):
221
         if not self.slug:
238
         if not self.slug:
222
             self.slug = slugify(self.name)
239
             self.slug = slugify(self.name)
225
 
242
 
226
 class AbstractProductContributor(models.Model):
243
 class AbstractProductContributor(models.Model):
227
     product = models.ForeignKey('catalogue.Product', verbose_name=_("Product"))
244
     product = models.ForeignKey('catalogue.Product', verbose_name=_("Product"))
228
-    contributor = models.ForeignKey('catalogue.Contributor', verbose_name=_("Contributor"))
229
-    role = models.ForeignKey('catalogue.ContributorRole', blank=True, null=True, verbose_name=_("Contributor Role"))
245
+    contributor = models.ForeignKey('catalogue.Contributor',
246
+                                    verbose_name=_("Contributor"))
247
+    role = models.ForeignKey('catalogue.ContributorRole', blank=True,
248
+                             null=True, verbose_name=_("Contributor Role"))
230
 
249
 
231
     def __unicode__(self):
250
     def __unicode__(self):
232
         return '%s <- %s - %s' % (self.product, self.role, self.contributor)
251
         return '%s <- %s - %s' % (self.product, self.role, self.contributor)
241
     """
260
     """
242
     The base product object
261
     The base product object
243
     """
262
     """
244
-    # If an item has no parent, then it is the "canonical" or abstract version of a product
245
-    # which essentially represents a set of products.  If a product has a parent
246
-    # then it is a specific version of a catalogue.
263
+    # If an item has no parent, then it is the "canonical" or abstract version
264
+    # of a product which essentially represents a set of products.  If a
265
+    # product has a parent then it is a specific version of a catalogue.
247
     #
266
     #
248
-    # For example, a canonical product would have a title like "Green fleece" while its
249
-    # children would be "Green fleece - size L".
267
+    # For example, a canonical product would have a title like "Green fleece"
268
+    # while its children would be "Green fleece - size L".
250
 
269
 
251
     # Universal product code
270
     # Universal product code
252
-    upc = models.CharField(_("UPC"), max_length=64, blank=True, null=True, unique=True,
253
-        help_text=_("""Universal Product Code (UPC) is an identifier for a product which is
254
-                     not specific to a particular supplier.  Eg an ISBN for a book."""))
271
+    upc = models.CharField(_("UPC"), max_length=64, blank=True, null=True,
272
+                           unique=True,
273
+        help_text=_("Universal Product Code (UPC) is an identifier for "
274
+                    "a product which is not specific to a particular "
275
+                    " supplier. Eg an ISBN for a book."))
255
 
276
 
256
     # No canonical product should have a stock record as they cannot be bought.
277
     # No canonical product should have a stock record as they cannot be bought.
257
-    parent = models.ForeignKey('self', null=True, blank=True, related_name='variants', verbose_name=_("Parent"),
258
-        help_text=_("""Only choose a parent product if this is a 'variant' of a canonical catalogue.  For example
259
-                     if this is a size 4 of a particular t-shirt.  Leave blank if this is a CANONICAL PRODUCT (ie
260
-                     there is only one version of this product)."""))
278
+    parent = models.ForeignKey('self', null=True, blank=True,
279
+                               related_name='variants',
280
+                               verbose_name=_("Parent"),
281
+        help_text=_("Only choose a parent product if this is a 'variant' of "
282
+                    "a canonical catalogue.  For example if this is a size "
283
+                    "4 of a particular t-shirt.  Leave blank if this is a "
284
+                    "CANONICAL PRODUCT (ie there is only one version of this "
285
+                    "product)."))
261
 
286
 
262
     # Title is mandatory for canonical products but optional for child products
287
     # Title is mandatory for canonical products but optional for child products
263
     title = models.CharField(_('Title'), max_length=255, blank=True, null=True)
288
     title = models.CharField(_('Title'), max_length=255, blank=True, null=True)
264
     slug = models.SlugField(_('Slug'), max_length=255, unique=False)
289
     slug = models.SlugField(_('Slug'), max_length=255, unique=False)
265
     description = models.TextField(_('Description'), blank=True, null=True)
290
     description = models.TextField(_('Description'), blank=True, null=True)
266
 
291
 
267
-    # Use this field to indicate if the product is inactive or awaiting approval
268
-    status = models.CharField(_('Status'), max_length=128, blank=True, null=True, db_index=True)
269
-    product_class = models.ForeignKey('catalogue.ProductClass', verbose_name=_('Product Class'), null=True,
292
+    # Use this field to indicate if the product is inactive or awaiting
293
+    # approval
294
+    status = models.CharField(_('Status'), max_length=128, blank=True,
295
+                              null=True, db_index=True)
296
+    product_class = models.ForeignKey(
297
+        'catalogue.ProductClass', verbose_name=_('Product Class'), null=True,
270
         help_text=_("""Choose what type of product this is"""))
298
         help_text=_("""Choose what type of product this is"""))
271
-    attributes = models.ManyToManyField('catalogue.ProductAttribute', through='ProductAttributeValue',
272
-        verbose_name=_("Attributes"), help_text=_("A product attribute is something that this product MUST have, "
273
-        "such as a size, as specified by its class"))
274
-    product_options = models.ManyToManyField('catalogue.Option', blank=True, verbose_name=_("Product Options"),
275
-        help_text=_("""Options are values that can be associated with a item when it is added to
276
-                     a customer's basket.  This could be something like a personalised message to be
277
-                     printed on a T-shirt."""))
278
-
279
-    related_products = models.ManyToManyField('catalogue.Product', related_name='relations', blank=True,
280
-        verbose_name=_("Related Products"), help_text=_("""Related items are things like different formats
281
-            of the same book.  Grouping them together allows better linking betwen products on the site."""))
299
+    attributes = models.ManyToManyField(
300
+        'catalogue.ProductAttribute',
301
+        through='ProductAttributeValue',
302
+        verbose_name=_("Attributes"),
303
+        help_text=_("A product attribute is something that this product MUST "
304
+                    "have, such as a size, as specified by its class"))
305
+    product_options = models.ManyToManyField(
306
+        'catalogue.Option', blank=True, verbose_name=_("Product Options"),
307
+        help_text=_("Options are values that can be associated with a item "
308
+                    "when it is added to a customer's basket.  This could be "
309
+                    "something like a personalised message to be printed on "
310
+                    "a T-shirt."))
311
+
312
+    related_products = models.ManyToManyField(
313
+        'catalogue.Product', related_name='relations', blank=True,
314
+        verbose_name=_("Related Products"),
315
+        help_text=_("Related items are things like different formats of the "
316
+                    "same book.  Grouping them together allows better linking "
317
+                    "betwen products on the site."))
282
 
318
 
283
     # Recommended products
319
     # Recommended products
284
-    recommended_products = models.ManyToManyField('catalogue.Product', through='ProductRecommendation', blank=True,
320
+    recommended_products = models.ManyToManyField(
321
+        'catalogue.Product', through='ProductRecommendation', blank=True,
285
         verbose_name=_("Recommended Products"))
322
         verbose_name=_("Recommended Products"))
286
 
323
 
287
     # Product score
324
     # Product score
290
     date_created = models.DateTimeField(_("Date Created"), auto_now_add=True)
327
     date_created = models.DateTimeField(_("Date Created"), auto_now_add=True)
291
 
328
 
292
     # This field is used by Haystack to reindex search
329
     # This field is used by Haystack to reindex search
293
-    date_updated = models.DateTimeField(_("Date Updated"), auto_now=True, db_index=True)
330
+    date_updated = models.DateTimeField(_("Date Updated"), auto_now=True,
331
+                                        db_index=True)
294
 
332
 
295
-    categories = models.ManyToManyField('catalogue.Category', through='ProductCategory', verbose_name=_("Categories"))
333
+    categories = models.ManyToManyField(
334
+        'catalogue.Category', through='ProductCategory',
335
+        verbose_name=_("Categories"))
296
 
336
 
297
     is_discountable = models.BooleanField(_("Is Discountable"), default=True)
337
     is_discountable = models.BooleanField(_("Is Discountable"), default=True)
298
 
338
 
305
     def options(self):
345
     def options(self):
306
         pclass = self.get_product_class()
346
         pclass = self.get_product_class()
307
         if pclass:
347
         if pclass:
308
-            return list(chain(self.product_options.all(), self.get_product_class().options.all()))
348
+            return list(chain(self.product_options.all(),
349
+                              self.get_product_class().options.all()))
309
         return self.product_options.all()
350
         return self.product_options.all()
310
 
351
 
311
     @property
352
     @property
317
 
358
 
318
     @property
359
     @property
319
     def is_group(self):
360
     def is_group(self):
320
-        u"""Return True if this is a top level product and has more than 0 variants"""
361
+        """
362
+        Test if this is a top level product and has more than 0 variants
363
+        """
321
         # use len() instead of count() in this specific instance
364
         # use len() instead of count() in this specific instance
322
         # as variants are highly likely to be used after this
365
         # as variants are highly likely to be used after this
323
         # which reduces the amount of SQL queries required
366
         # which reduces the amount of SQL queries required
325
 
368
 
326
     @property
369
     @property
327
     def is_variant(self):
370
     def is_variant(self):
328
-        u"""Return True if a product is not a top level product"""
371
+        """Return True if a product is not a top level product"""
329
         return not self.is_top_level
372
         return not self.is_top_level
330
 
373
 
331
     @property
374
     @property
382
 
425
 
383
     def attribute_summary(self):
426
     def attribute_summary(self):
384
         u"""Return a string of all of a product's attributes"""
427
         u"""Return a string of all of a product's attributes"""
385
-        return ", ".join([attribute.__unicode__() for attribute in self.attributes.all()])
428
+        return ", ".join([
429
+            attribute.__unicode__() for attribute in self.attributes.all()])
386
 
430
 
387
     def get_title(self):
431
     def get_title(self):
388
         """
432
         """
410
         return {
454
         return {
411
             'original': MissingProductImage(),
455
             'original': MissingProductImage(),
412
             'caption': '',
456
             'caption': '',
413
-            'is_missing': True
414
-        }
457
+            'is_missing': True}
415
 
458
 
416
     # Helpers
459
     # Helpers
417
 
460
 
468
     """
511
     """
469
     'Through' model for product recommendations
512
     'Through' model for product recommendations
470
     """
513
     """
471
-    primary = models.ForeignKey('catalogue.Product', related_name='primary_recommendations',
514
+    primary = models.ForeignKey(
515
+        'catalogue.Product', related_name='primary_recommendations',
472
         verbose_name=_("Primary Product"))
516
         verbose_name=_("Primary Product"))
473
-    recommendation = models.ForeignKey('catalogue.Product', verbose_name=_("Recommended Product"))
517
+    recommendation = models.ForeignKey(
518
+        'catalogue.Product', verbose_name=_("Recommended Product"))
474
     ranking = models.PositiveSmallIntegerField(_('Ranking'), default=0)
519
     ranking = models.PositiveSmallIntegerField(_('Ranking'), default=0)
475
 
520
 
476
     class Meta:
521
     class Meta:
540
 
585
 
541
 
586
 
542
 class AbstractProductAttribute(models.Model):
587
 class AbstractProductAttribute(models.Model):
588
+    """
589
+    Defines an attribute for a product class. (For example, number_of_pages for
590
+    a 'book' class)
591
+    """
543
 
592
 
544
     TYPE_CHOICES = (
593
     TYPE_CHOICES = (
545
         ("text", _("Text")),
594
         ("text", _("Text")),
549
         ("richtext", _("Rich Text")),
598
         ("richtext", _("Rich Text")),
550
         ("date", _("Date")),
599
         ("date", _("Date")),
551
         ("option", _("Option")),
600
         ("option", _("Option")),
552
-        ("entity", _("Entity"))
553
-    )
554
-
555
-    """
556
-    Defines an attribute for a product class. (For example, number_of_pages for a 'book' class)
557
-    """
558
-    product_class = models.ForeignKey('catalogue.ProductClass', related_name='attributes', blank=True, null=True,
559
-        verbose_name=_("Product Class"))
601
+        ("entity", _("Entity")))
602
+    product_class = models.ForeignKey(
603
+        'catalogue.ProductClass', related_name='attributes', blank=True,
604
+        null=True, verbose_name=_("Product Class"))
560
     name = models.CharField(_('Name'), max_length=128)
605
     name = models.CharField(_('Name'), max_length=128)
561
-    code = models.SlugField(_('Code'), max_length=128, validators=[RegexValidator(regex=r'^[a-zA-Z_][0-9a-zA-Z_]*$',
606
+    code = models.SlugField(
607
+        _('Code'), max_length=128,
608
+        validators=[RegexValidator(regex=r'^[a-zA-Z_][0-9a-zA-Z_]*$',
562
         message=_("Code must match ^[a-zA-Z_][0-9a-zA-Z_]*$"))])
609
         message=_("Code must match ^[a-zA-Z_][0-9a-zA-Z_]*$"))])
563
-    type = models.CharField(choices=TYPE_CHOICES, default=TYPE_CHOICES[0][0], max_length=20, verbose_name=_("Type"))
564
-    option_group = models.ForeignKey('catalogue.AttributeOptionGroup', blank=True, null=True,
565
-        verbose_name=_("Option Group"), help_text=_('Select an option group if using type "Option"'))
566
-    entity_type = models.ForeignKey('catalogue.AttributeEntityType', blank=True, null=True,
567
-        verbose_name=_("Entity Type"), help_text=_('Select an entity type if using type "Entity"'))
610
+    type = models.CharField(
611
+        choices=TYPE_CHOICES, default=TYPE_CHOICES[0][0],
612
+        max_length=20, verbose_name=_("Type"))
613
+    option_group = models.ForeignKey(
614
+        'catalogue.AttributeOptionGroup', blank=True, null=True,
615
+        verbose_name=_("Option Group"),
616
+        help_text=_('Select an option group if using type "Option"'))
617
+    entity_type = models.ForeignKey(
618
+        'catalogue.AttributeEntityType', blank=True, null=True,
619
+        verbose_name=_("Entity Type"),
620
+        help_text=_('Select an entity type if using type "Entity"'))
568
     required = models.BooleanField(_('Required'), default=False)
621
     required = models.BooleanField(_('Required'), default=False)
569
 
622
 
570
     class Meta:
623
     class Meta:
599
 
652
 
600
     def _validate_entity(self, value):
653
     def _validate_entity(self, value):
601
         if not isinstance(value, get_model('catalogue', 'AttributeEntity')):
654
         if not isinstance(value, get_model('catalogue', 'AttributeEntity')):
602
-            raise ValidationError(_("Must be an AttributeEntity model object instance"))
655
+            raise ValidationError(
656
+                _("Must be an AttributeEntity model object instance"))
603
         if not value.pk:
657
         if not value.pk:
604
             raise ValidationError(_("Model has not been saved yet"))
658
             raise ValidationError(_("Model has not been saved yet"))
605
         if value.type != self.entity_type:
659
         if value.type != self.entity_type:
606
-            raise ValidationError(_("Entity must be of type %s" % self.entity_type.name))
660
+            raise ValidationError(
661
+                _("Entity must be of type %s" % self.entity_type.name))
607
 
662
 
608
     def _validate_option(self, value):
663
     def _validate_option(self, value):
609
         if not isinstance(value, get_model('catalogue', 'AttributeOption')):
664
         if not isinstance(value, get_model('catalogue', 'AttributeOption')):
610
-            raise ValidationError(_("Must be an AttributeOption model object instance"))
665
+            raise ValidationError(
666
+                _("Must be an AttributeOption model object instance"))
611
         if not value.pk:
667
         if not value.pk:
612
             raise ValidationError(_("AttributeOption has not been saved yet"))
668
             raise ValidationError(_("AttributeOption has not been saved yet"))
613
-        valid_values = self.option_group.options.values_list('option', flat=True)
669
+        valid_values = self.option_group.options.values_list('option',
670
+                                                             flat=True)
614
         if value.option not in valid_values:
671
         if value.option not in valid_values:
615
             raise ValidationError(_("%(enum)s is not a valid choice "
672
             raise ValidationError(_("%(enum)s is not a valid choice "
616
                                         "for %(attr)s") % \
673
                                         "for %(attr)s") % \
642
         except get_model('catalogue', 'ProductAttributeValue').DoesNotExist:
699
         except get_model('catalogue', 'ProductAttributeValue').DoesNotExist:
643
             if value == None or value == '':
700
             if value == None or value == '':
644
                 return
701
                 return
645
-            value_obj = get_model('catalogue', 'ProductAttributeValue').objects.create(product=product, attribute=self)
702
+            model = get_model('catalogue', 'ProductAttributeValue')
703
+            value_obj = model.objects.create(product=product, attribute=self)
646
         if value == None or value == '':
704
         if value == None or value == '':
647
             value_obj.delete()
705
             value_obj.delete()
648
             return
706
             return
658
         Check whether the passed value is valid for this attribute
716
         Check whether the passed value is valid for this attribute
659
         """
717
         """
660
         if self.type == 'option':
718
         if self.type == 'option':
661
-            valid_values = self.option_group.options.values_list('option', flat=True)
719
+            valid_values = self.option_group.options.values_list('option',
720
+                                                                 flat=True)
662
             return value in valid_values
721
             return value in valid_values
663
         return True
722
         return True
664
 
723
 
671
 
730
 
672
     For example: number_of_pages = 295
731
     For example: number_of_pages = 295
673
     """
732
     """
674
-    attribute = models.ForeignKey('catalogue.ProductAttribute', verbose_name=_("Attribute"))
675
-    product = models.ForeignKey('catalogue.Product', related_name='attribute_values', verbose_name=_("Product"))
676
-    value_text = models.CharField(_('Text'), max_length=255, blank=True, null=True)
733
+    attribute = models.ForeignKey('catalogue.ProductAttribute',
734
+                                  verbose_name=_("Attribute"))
735
+    product = models.ForeignKey(
736
+        'catalogue.Product', related_name='attribute_values',
737
+        verbose_name=_("Product"))
738
+    value_text = models.CharField(
739
+        _('Text'), max_length=255, blank=True, null=True)
677
     value_integer = models.IntegerField(_('Integer'), blank=True, null=True)
740
     value_integer = models.IntegerField(_('Integer'), blank=True, null=True)
678
     value_boolean = models.BooleanField(_('Boolean'), blank=True)
741
     value_boolean = models.BooleanField(_('Boolean'), blank=True)
679
     value_float = models.FloatField(_('Float'), blank=True, null=True)
742
     value_float = models.FloatField(_('Float'), blank=True, null=True)
680
     value_richtext = models.TextField(_('Richtext'), blank=True, null=True)
743
     value_richtext = models.TextField(_('Richtext'), blank=True, null=True)
681
     value_date = models.DateField(_('Date'), blank=True, null=True)
744
     value_date = models.DateField(_('Date'), blank=True, null=True)
682
-    value_option = models.ForeignKey('catalogue.AttributeOption', blank=True, null=True,
745
+    value_option = models.ForeignKey(
746
+        'catalogue.AttributeOption', blank=True, null=True,
683
         verbose_name=_("Value Option"))
747
         verbose_name=_("Value Option"))
684
-    value_entity = models.ForeignKey('catalogue.AttributeEntity', blank=True, null=True,
748
+    value_entity = models.ForeignKey(
749
+        'catalogue.AttributeEntity', blank=True, null=True,
685
         verbose_name=_("Value Entity"))
750
         verbose_name=_("Value Entity"))
686
 
751
 
687
     def _get_value(self):
752
     def _get_value(self):
690
     def _set_value(self, new_value):
755
     def _set_value(self, new_value):
691
         if self.attribute.type == 'option' and isinstance(new_value, str):
756
         if self.attribute.type == 'option' and isinstance(new_value, str):
692
             # Need to look up instance of AttributeOption
757
             # Need to look up instance of AttributeOption
693
-            new_value = self.attribute.option_group.options.get(option=new_value)
758
+            new_value = self.attribute.option_group.options.get(
759
+                option=new_value)
694
         setattr(self, 'value_%s' % self.attribute.type, new_value)
760
         setattr(self, 'value_%s' % self.attribute.type, new_value)
695
 
761
 
696
     value = property(_get_value, _set_value)
762
     value = property(_get_value, _set_value)
726
     Provides an option within an option group for an attribute type
792
     Provides an option within an option group for an attribute type
727
     Examples: In a Language group, English, Greek, French
793
     Examples: In a Language group, English, Greek, French
728
     """
794
     """
729
-    group = models.ForeignKey('catalogue.AttributeOptionGroup', related_name='options', verbose_name=_("Group"))
795
+    group = models.ForeignKey(
796
+        'catalogue.AttributeOptionGroup', related_name='options',
797
+        verbose_name=_("Group"))
730
     option = models.CharField(_('Option'), max_length=255)
798
     option = models.CharField(_('Option'), max_length=255)
731
 
799
 
732
     def __unicode__(self):
800
     def __unicode__(self):
743
     Provides an attribute type to enable relationships with other models
811
     Provides an attribute type to enable relationships with other models
744
     """
812
     """
745
     name = models.CharField(_("Name"), max_length=255)
813
     name = models.CharField(_("Name"), max_length=255)
746
-    slug = models.SlugField(_("Slug"), max_length=255, unique=False, blank=True)
747
-    type = models.ForeignKey('catalogue.AttributeEntityType', related_name='entities', verbose_name=_("Type"))
814
+    slug = models.SlugField(
815
+        _("Slug"), max_length=255, unique=False, blank=True)
816
+    type = models.ForeignKey(
817
+        'catalogue.AttributeEntityType', related_name='entities',
818
+        verbose_name=_("Type"))
748
 
819
 
749
     def __unicode__(self):
820
     def __unicode__(self):
750
         return self.name
821
         return self.name
765
     Provides the name of the model involved in an entity relationship
836
     Provides the name of the model involved in an entity relationship
766
     """
837
     """
767
     name = models.CharField(_("Name"), max_length=255)
838
     name = models.CharField(_("Name"), max_length=255)
768
-    slug = models.SlugField(_("Slug"), max_length=255, unique=False, blank=True)
839
+    slug = models.SlugField(
840
+        _("Slug"), max_length=255, unique=False, blank=True)
769
 
841
 
770
     def __unicode__(self):
842
     def __unicode__(self):
771
         return self.name
843
         return self.name
786
     An option that can be selected for a particular item when the product
858
     An option that can be selected for a particular item when the product
787
     is added to the basket.
859
     is added to the basket.
788
 
860
 
789
-    For example,  a list ID for an SMS message send, or a personalised message to
790
-    print on a T-shirt.
861
+    For example,  a list ID for an SMS message send, or a personalised message
862
+    to print on a T-shirt.
791
 
863
 
792
     This is not the same as an 'attribute' as options do not have a fixed value
864
     This is not the same as an 'attribute' as options do not have a fixed value
793
     for a particular item.  Instead, option need to be specified by a customer
865
     for a particular item.  Instead, option need to be specified by a customer
832
     """
904
     """
833
     An image of a product
905
     An image of a product
834
     """
906
     """
835
-    product = models.ForeignKey('catalogue.Product', related_name='images', verbose_name=_("Product"))
836
-    original = models.ImageField(_("Original"), upload_to=settings.OSCAR_IMAGE_FOLDER)
837
-    caption = models.CharField(_("Caption"), max_length=200, blank=True, null=True)
907
+    product = models.ForeignKey(
908
+        'catalogue.Product', related_name='images', verbose_name=_("Product"))
909
+    original = models.ImageField(
910
+        _("Original"), upload_to=settings.OSCAR_IMAGE_FOLDER)
911
+    caption = models.CharField(
912
+        _("Caption"), max_length=200, blank=True, null=True)
838
 
913
 
839
     # Use display_order to determine which is the "primary" image
914
     # Use display_order to determine which is the "primary" image
840
     display_order = models.PositiveIntegerField(_("Display Order"), default=0,
915
     display_order = models.PositiveIntegerField(_("Display Order"), default=0,
873
     @property
948
     @property
874
     def thumbnail_url(self):
949
     def thumbnail_url(self):
875
         return self.resized_image_url()
950
         return self.resized_image_url()
876
-

+ 23
- 9
oscar/apps/catalogue/admin.py View File

20
 class AttributeInline(admin.TabularInline):
20
 class AttributeInline(admin.TabularInline):
21
     model = ProductAttributeValue
21
     model = ProductAttributeValue
22
 
22
 
23
+
23
 class ProductRecommendationInline(admin.TabularInline):
24
 class ProductRecommendationInline(admin.TabularInline):
24
     model = ProductRecommendation
25
     model = ProductRecommendation
25
     fk_name = 'primary'
26
     fk_name = 'primary'
26
-    
27
+
28
+
27
 class CategoryInline(admin.TabularInline):
29
 class CategoryInline(admin.TabularInline):
28
     model = ProductCategory
30
     model = ProductCategory
29
     extra = 1
31
     extra = 1
30
 
32
 
33
+
31
 class ProductClassAdmin(admin.ModelAdmin):
34
 class ProductClassAdmin(admin.ModelAdmin):
32
     prepopulated_fields = {"slug": ("name",)}
35
     prepopulated_fields = {"slug": ("name",)}
33
-    
36
+
37
+
34
 class ProductAdmin(admin.ModelAdmin):
38
 class ProductAdmin(admin.ModelAdmin):
35
-    list_display = ('get_title', 'upc', 'get_product_class', 'is_top_level', 'is_group', 'is_variant', 'attribute_summary', 'date_created')
39
+    list_display = ('get_title', 'upc', 'get_product_class', 'is_top_level',
40
+                    'is_group', 'is_variant', 'attribute_summary',
41
+                    'date_created')
36
     prepopulated_fields = {"slug": ("title",)}
42
     prepopulated_fields = {"slug": ("title",)}
37
     inlines = [AttributeInline, CategoryInline, ProductRecommendationInline]
43
     inlines = [AttributeInline, CategoryInline, ProductRecommendationInline]
38
-    
44
+
45
+
39
 class ProductAttributeAdmin(admin.ModelAdmin):
46
 class ProductAttributeAdmin(admin.ModelAdmin):
40
     prepopulated_fields = {"code": ("name", )}
47
     prepopulated_fields = {"code": ("name", )}
41
-    
48
+
49
+
42
 class OptionAdmin(admin.ModelAdmin):
50
 class OptionAdmin(admin.ModelAdmin):
43
     exclude = ['code']
51
     exclude = ['code']
44
-    
52
+
53
+
45
 class ProductAttributeValueAdmin(admin.ModelAdmin):
54
 class ProductAttributeValueAdmin(admin.ModelAdmin):
46
     list_display = ('product', 'attribute', 'value')
55
     list_display = ('product', 'attribute', 'value')
47
 
56
 
57
+
48
 class AttributeOptionInline(admin.TabularInline):
58
 class AttributeOptionInline(admin.TabularInline):
49
     model = AttributeOption
59
     model = AttributeOption
50
-    
60
+
61
+
51
 class AttributeOptionGroupAdmin(admin.ModelAdmin):
62
 class AttributeOptionGroupAdmin(admin.ModelAdmin):
52
     inlines = [AttributeOptionInline, ]
63
     inlines = [AttributeOptionInline, ]
53
-        
64
+
65
+
54
 class AttributeEntityAdmin(admin.ModelAdmin):
66
 class AttributeEntityAdmin(admin.ModelAdmin):
55
     list_display = ('name', )
67
     list_display = ('name', )
56
-                 
68
+
69
+
57
 class CategoryAdmin(TreeAdmin):
70
 class CategoryAdmin(TreeAdmin):
58
     pass
71
     pass
59
 
72
 
73
+
60
 admin.site.register(ProductClass, ProductClassAdmin)
74
 admin.site.register(ProductClass, ProductClassAdmin)
61
 admin.site.register(Product, ProductAdmin)
75
 admin.site.register(Product, ProductAdmin)
62
 admin.site.register(ProductAttribute, ProductAttributeAdmin)
76
 admin.site.register(ProductAttribute, ProductAttributeAdmin)

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

1
 from django.conf.urls import patterns, url, include
1
 from django.conf.urls import patterns, url, include
2
 
2
 
3
 from oscar.core.application import Application
3
 from oscar.core.application import Application
4
-from oscar.apps.catalogue.views import ProductDetailView, ProductListView, ProductCategoryView
4
+from oscar.apps.catalogue import views
5
 from oscar.apps.catalogue.reviews.app import application as reviews_app
5
 from oscar.apps.catalogue.reviews.app import application as reviews_app
6
 
6
 
7
 
7
 
8
 class BaseCatalogueApplication(Application):
8
 class BaseCatalogueApplication(Application):
9
     name = 'catalogue'
9
     name = 'catalogue'
10
-    detail_view = ProductDetailView
11
-    index_view = ProductListView
12
-    category_view = ProductCategoryView
10
+    detail_view = views.ProductDetailView
11
+    index_view = views.ProductListView
12
+    category_view = views.ProductCategoryView
13
 
13
 
14
     def get_urls(self):
14
     def get_urls(self):
15
         urlpatterns = super(BaseCatalogueApplication, self).get_urls()
15
         urlpatterns = super(BaseCatalogueApplication, self).get_urls()
18
             url(r'^(?P<product_slug>[\w-]*)_(?P<pk>\d+)/$',
18
             url(r'^(?P<product_slug>[\w-]*)_(?P<pk>\d+)/$',
19
                 self.detail_view.as_view(), name='detail'),
19
                 self.detail_view.as_view(), name='detail'),
20
             url(r'^(?P<category_slug>[\w-]+(/[\w-]+)*)/$',
20
             url(r'^(?P<category_slug>[\w-]+(/[\w-]+)*)/$',
21
-                self.category_view.as_view(), name='category')
22
-        )
21
+                self.category_view.as_view(), name='category'))
23
         return self.post_process_urls(urlpatterns)
22
         return self.post_process_urls(urlpatterns)
24
 
23
 
25
 
24
 

+ 1
- 1
oscar/apps/catalogue/exceptions.py View File

7
 
7
 
8
 
8
 
9
 class InvalidImageArchive(Exception):
9
 class InvalidImageArchive(Exception):
10
-    pass    
10
+    pass

+ 2
- 1
oscar/apps/catalogue/managers.py View File

3
 
3
 
4
 class BrowsableProductManager(models.Manager):
4
 class BrowsableProductManager(models.Manager):
5
     def get_query_set(self):
5
     def get_query_set(self):
6
-        return super(BrowsableProductManager, self).get_query_set().filter(parent=None)
6
+        return super(BrowsableProductManager, self).get_query_set().filter(
7
+            parent=None)

+ 2
- 3
oscar/apps/catalogue/models.py View File

30
 
30
 
31
 class ProductContributor(AbstractProductContributor):
31
 class ProductContributor(AbstractProductContributor):
32
     pass
32
     pass
33
-    
34
-    
33
+
34
+
35
 class ProductAttribute(AbstractProductAttribute):
35
 class ProductAttribute(AbstractProductAttribute):
36
     pass
36
     pass
37
 
37
 
62
 
62
 
63
 class ProductImage(AbstractProductImage):
63
 class ProductImage(AbstractProductImage):
64
     pass
64
     pass
65
-

+ 2
- 1
oscar/apps/catalogue/signals.py View File

1
 import django.dispatch
1
 import django.dispatch
2
 
2
 
3
-product_viewed = django.dispatch.Signal(providing_args=["product", "user", "request", "response"])
3
+product_viewed = django.dispatch.Signal(
4
+    providing_args=["product", "user", "request", "response"])
4
 
5
 
5
 # This needs to be moved into the search app when it is refactored
6
 # This needs to be moved into the search app when it is refactored
6
 product_search = django.dispatch.Signal(providing_args=["query", '"user'])
7
 product_search = django.dispatch.Signal(providing_args=["query", '"user'])

+ 3
- 3
oscar/apps/catalogue/utils.py View File

11
 from django.db.models import get_model
11
 from django.db.models import get_model
12
 from django.utils.translation import ugettext_lazy as _
12
 from django.utils.translation import ugettext_lazy as _
13
 
13
 
14
-from oscar.apps.catalogue.exceptions import ImageImportError, IdenticalImageError, InvalidImageArchive
14
+from oscar.apps.catalogue.exceptions import (
15
+    ImageImportError, IdenticalImageError, InvalidImageArchive)
15
 
16
 
16
 Category = get_model('catalogue', 'category')
17
 Category = get_model('catalogue', 'category')
17
 Product = get_model('catalogue', 'product')
18
 Product = get_model('catalogue', 'product')
30
         stats = {
31
         stats = {
31
             'num_processed': 0,
32
             'num_processed': 0,
32
             'num_skipped': 0,
33
             'num_skipped': 0,
33
-            'num_invalid': 0
34
-        }
34
+            'num_invalid': 0}
35
         image_dir, filenames = self._get_image_files(dirname)
35
         image_dir, filenames = self._get_image_files(dirname)
36
         if image_dir:
36
         if image_dir:
37
             for filename in filenames:
37
             for filename in filenames:

Loading…
Cancel
Save