Просмотр исходного кода

Remove Product.status field and Contributor models

The Contributor models (Contributor, ContributorRole, ProductContributor
and their abstract versions) were unused and too specific to the book
domain.

Product.status was provided as a convenience, but the real world showed
that more often than not, a different field type is necessary. As adding
a field is much easier than changing the field type, it is removed.
master
Maik Hoepfel 12 лет назад
Родитель
Сommit
f56226aa2f

+ 18
- 3
docs/source/releases/v0.7.rst Просмотреть файл

@@ -80,13 +80,27 @@ Bugfixes
80 80
 Backwards incompatible changes in 0.7
81 81
 =====================================
82 82
 
83
+.. warning::
84
+
85
+    Fields and models have been removed from Oscar. If you used them, you must
86
+    ensure you create/extend the affected models appropriately.
87
+
88
+* ``AbstractProduct.status`` was an unused ``CharField`` provided for convenience
89
+  as it's a commonly required field. But a different field type was often
90
+  required, and as changing it is much harder than adding a field with the
91
+  desired type, the field has been removed.
92
+
93
+* ``Contributor``, ``ContributorRole``, the through-model ``ProductContributor``
94
+  and their abstract versions have been removed as they were unused and too
95
+  specific to the domain of book shops.
96
+
97
+* ``ProductCategory.is_canonical`` was an unused ``BooleanField`` and has been
98
+  removed.
99
+
83 100
 * ``Order.basket_id`` was a ``PositiveIntegerField`` containing the primary key of the
84 101
   associated basket. It's been refactored to be a nullable ``ForeignKey`` and
85 102
   is now called "basket".
86 103
 
87
-* ``ProductCategory.is_canonical`` was an unused ``BooleanField`` and has been
88
-  dropped.
89
-
90 104
 * `#1123`_ - The URL structure of ``ProductCreateRedirectView`` has been changed to use
91 105
   the product class' slug instead of the primary key. It's necessary to update
92 106
   URLs pointing to that view.
@@ -112,6 +126,7 @@ Migrations
112 126
     - ``0014`` - Drops unused ``ProductCategory.is_canonical`` field.
113 127
     - ``0015`` - Turns a product's UPC field into a :class:`oscar.models.fields.NullCharField`
114 128
     - ``0016`` - ``AutoSlugField`` for ``AbstractProductClass`` and ``AbstractOption``
129
+    - ``0017`` - Removes ``Product.status``, ``Contributor``, ``ContributorRole`` and ``ProductContributor``
115 130
 
116 131
 * Customer:
117 132
 

+ 0
- 66
oscar/apps/catalogue/abstract_models.py Просмотреть файл

@@ -188,67 +188,6 @@ class AbstractProductCategory(models.Model):
188 188
         return u"<productcategory for product '%s'>" % self.product
189 189
 
190 190
 
191
-class AbstractContributorRole(models.Model):
192
-    """
193
-    A role that may be performed by a contributor to a product, eg Author,
194
-    Actor, Director.
195
-    """
196
-    name = models.CharField(_('Name'), max_length=50)
197
-    name_plural = models.CharField(_('Name Plural'), max_length=50)
198
-    slug = models.SlugField()
199
-
200
-    def __unicode__(self):
201
-        return self.name
202
-
203
-    class Meta:
204
-        abstract = True
205
-        verbose_name = _('Contributor Role')
206
-        verbose_name_plural = _('Contributor Roles')
207
-
208
-    def save(self, *args, **kwargs):
209
-        if not self.slug:
210
-            self.slug = slugify(self.name)
211
-        super(AbstractContributorRole, self).save(*args, **kwargs)
212
-
213
-
214
-class AbstractContributor(models.Model):
215
-    """
216
-    Represents a person or business that has contributed to a product in some
217
-    way. eg an author.
218
-    """
219
-    name = models.CharField(_("Name"), max_length=255)
220
-    slug = models.SlugField(_("Slug"), max_length=255, unique=False)
221
-
222
-    def __unicode__(self):
223
-        return self.name
224
-
225
-    class Meta:
226
-        abstract = True
227
-        verbose_name = _('Contributor')
228
-        verbose_name_plural = _('Contributors')
229
-
230
-    def save(self, *args, **kwargs):
231
-        if not self.slug:
232
-            self.slug = slugify(self.name)
233
-        super(AbstractContributor, self).save(*args, **kwargs)
234
-
235
-
236
-class AbstractProductContributor(models.Model):
237
-    product = models.ForeignKey('catalogue.Product', verbose_name=_("Product"))
238
-    contributor = models.ForeignKey('catalogue.Contributor',
239
-                                    verbose_name=_("Contributor"))
240
-    role = models.ForeignKey('catalogue.ContributorRole', blank=True,
241
-                             null=True, verbose_name=_("Contributor Role"))
242
-
243
-    def __unicode__(self):
244
-        return '%s <- %s - %s' % (self.product, self.role, self.contributor)
245
-
246
-    class Meta:
247
-        abstract = True
248
-        verbose_name = _('Product Contributor')
249
-        verbose_name_plural = _('Product Contributors')
250
-
251
-
252 191
 class AbstractProduct(models.Model):
253 192
     """
254 193
     The base product object
@@ -282,11 +221,6 @@ class AbstractProduct(models.Model):
282 221
     slug = models.SlugField(_('Slug'), max_length=255, unique=False)
283 222
     description = models.TextField(_('Description'), blank=True, null=True)
284 223
 
285
-    #: Status field which is not used by core Oscar. Added because it's
286
-    # commonly needed to e.g. indicate if the product is inactive or awaiting
287
-    #: approval.
288
-    status = models.CharField(_('Status'), max_length=128, blank=True,
289
-                              null=True, db_index=True)
290 224
     product_class = models.ForeignKey(
291 225
         'catalogue.ProductClass', verbose_name=_('Product Class'), null=True,
292 226
         related_name="products",

+ 0
- 12
oscar/apps/catalogue/admin.py Просмотреть файл

@@ -7,8 +7,6 @@ AttributeEntityType = get_model('catalogue', 'AttributeEntityType')
7 7
 AttributeOption = get_model('catalogue', 'AttributeOption')
8 8
 AttributeOptionGroup = get_model('catalogue', 'AttributeOptionGroup')
9 9
 Category = get_model('catalogue', 'Category')
10
-ContributorRole = get_model('catalogue', 'ContributorRole')
11
-Contributor = get_model('catalogue', 'Contributor')
12 10
 Option = get_model('catalogue', 'Option')
13 11
 Product = get_model('catalogue', 'Product')
14 12
 ProductAttribute = get_model('catalogue', 'ProductAttribute')
@@ -44,14 +42,6 @@ class ProductClassAdmin(admin.ModelAdmin):
44 42
     inlines = [ProductAttributeInline]
45 43
 
46 44
 
47
-class ContributorAdmin(admin.ModelAdmin):
48
-    prepopulated_fields = {"slug": ("name",)}
49
-
50
-
51
-class ContributorRoleAdmin(admin.ModelAdmin):
52
-    prepopulated_fields = {"slug": ("name",)}
53
-
54
-
55 45
 class ProductAdmin(admin.ModelAdmin):
56 46
     list_display = ('get_title', 'upc', 'get_product_class', 'is_top_level',
57 47
                     'is_variant', 'attribute_summary',
@@ -92,8 +82,6 @@ class CategoryAdmin(TreeAdmin):
92 82
 
93 83
 admin.site.register(ProductClass, ProductClassAdmin)
94 84
 admin.site.register(Product, ProductAdmin)
95
-admin.site.register(ContributorRole, ContributorRoleAdmin)
96
-admin.site.register(Contributor, ContributorAdmin)
97 85
 admin.site.register(ProductAttribute, ProductAttributeAdmin)
98 86
 admin.site.register(ProductAttributeValue, ProductAttributeValueAdmin)
99 87
 admin.site.register(AttributeOptionGroup, AttributeOptionGroupAdmin)

+ 181
- 0
oscar/apps/catalogue/migrations/0017_auto__del_contributor__del_productcontributor__del_contributorrole__de.py Просмотреть файл

@@ -0,0 +1,181 @@
1
+# -*- coding: utf-8 -*-
2
+from south.utils import datetime_utils as datetime
3
+from south.db import db
4
+from south.v2 import SchemaMigration
5
+from django.db import models
6
+
7
+
8
+class Migration(SchemaMigration):
9
+
10
+    def forwards(self, orm):
11
+        # Deleting model 'Contributor'
12
+        db.delete_table(u'catalogue_contributor')
13
+
14
+        # Deleting model 'ProductContributor'
15
+        db.delete_table(u'catalogue_productcontributor')
16
+
17
+        # Deleting model 'ContributorRole'
18
+        db.delete_table(u'catalogue_contributorrole')
19
+
20
+        # Deleting field 'Product.status'
21
+        db.delete_column(u'catalogue_product', 'status')
22
+
23
+
24
+    def backwards(self, orm):
25
+        # Adding model 'Contributor'
26
+        db.create_table(u'catalogue_contributor', (
27
+            ('slug', self.gf('django.db.models.fields.SlugField')(max_length=255)),
28
+            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
29
+            ('name', self.gf('django.db.models.fields.CharField')(max_length=255)),
30
+        ))
31
+        db.send_create_signal(u'catalogue', ['Contributor'])
32
+
33
+        # Adding model 'ProductContributor'
34
+        db.create_table(u'catalogue_productcontributor', (
35
+            ('contributor', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['catalogue.Contributor'])),
36
+            ('product', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['catalogue.Product'])),
37
+            ('role', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['catalogue.ContributorRole'], null=True, blank=True)),
38
+            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
39
+        ))
40
+        db.send_create_signal(u'catalogue', ['ProductContributor'])
41
+
42
+        # Adding model 'ContributorRole'
43
+        db.create_table(u'catalogue_contributorrole', (
44
+            ('name_plural', self.gf('django.db.models.fields.CharField')(max_length=50)),
45
+            ('slug', self.gf('django.db.models.fields.SlugField')(max_length=50)),
46
+            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
47
+            ('name', self.gf('django.db.models.fields.CharField')(max_length=50)),
48
+        ))
49
+        db.send_create_signal(u'catalogue', ['ContributorRole'])
50
+
51
+        # Adding field 'Product.status'
52
+        db.add_column(u'catalogue_product', 'status',
53
+                      self.gf('django.db.models.fields.CharField')(blank=True, max_length=128, null=True, db_index=True),
54
+                      keep_default=False)
55
+
56
+
57
+    models = {
58
+        u'catalogue.attributeentity': {
59
+            'Meta': {'object_name': 'AttributeEntity'},
60
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
61
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
62
+            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'blank': 'True'}),
63
+            'type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'entities'", 'to': u"orm['catalogue.AttributeEntityType']"})
64
+        },
65
+        u'catalogue.attributeentitytype': {
66
+            'Meta': {'object_name': 'AttributeEntityType'},
67
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
68
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
69
+            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255', 'blank': 'True'})
70
+        },
71
+        u'catalogue.attributeoption': {
72
+            'Meta': {'object_name': 'AttributeOption'},
73
+            'group': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'options'", 'to': u"orm['catalogue.AttributeOptionGroup']"}),
74
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
75
+            'option': ('django.db.models.fields.CharField', [], {'max_length': '255'})
76
+        },
77
+        u'catalogue.attributeoptiongroup': {
78
+            'Meta': {'object_name': 'AttributeOptionGroup'},
79
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
80
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '128'})
81
+        },
82
+        u'catalogue.category': {
83
+            'Meta': {'ordering': "['full_name']", 'object_name': 'Category'},
84
+            'depth': ('django.db.models.fields.PositiveIntegerField', [], {}),
85
+            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
86
+            'full_name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
87
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
88
+            'image': ('django.db.models.fields.files.ImageField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
89
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
90
+            'numchild': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
91
+            'path': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255'}),
92
+            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'})
93
+        },
94
+        u'catalogue.option': {
95
+            'Meta': {'object_name': 'Option'},
96
+            'code': ('oscar.models.fields.autoslugfield.AutoSlugField', [], {'allow_duplicates': 'False', 'max_length': '128', 'separator': "u'-'", 'blank': 'True', 'unique': 'True', 'populate_from': "'name'", 'overwrite': 'False'}),
97
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
98
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
99
+            'type': ('django.db.models.fields.CharField', [], {'default': "'Required'", 'max_length': '128'})
100
+        },
101
+        u'catalogue.product': {
102
+            'Meta': {'ordering': "['-date_created']", 'object_name': 'Product'},
103
+            'attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.ProductAttribute']", 'through': u"orm['catalogue.ProductAttributeValue']", 'symmetrical': 'False'}),
104
+            'categories': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Category']", 'through': u"orm['catalogue.ProductCategory']", 'symmetrical': 'False'}),
105
+            'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
106
+            'date_updated': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
107
+            'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
108
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
109
+            'is_discountable': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
110
+            'parent': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'variants'", 'null': 'True', 'to': u"orm['catalogue.Product']"}),
111
+            'product_class': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'products'", 'null': 'True', 'to': u"orm['catalogue.ProductClass']"}),
112
+            'product_options': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Option']", 'symmetrical': 'False', 'blank': 'True'}),
113
+            'rating': ('django.db.models.fields.FloatField', [], {'null': 'True'}),
114
+            'recommended_products': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Product']", 'symmetrical': 'False', 'through': u"orm['catalogue.ProductRecommendation']", 'blank': 'True'}),
115
+            'related_products': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'relations'", 'blank': 'True', 'to': u"orm['catalogue.Product']"}),
116
+            'score': ('django.db.models.fields.FloatField', [], {'default': '0.0', 'db_index': 'True'}),
117
+            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '255'}),
118
+            'title': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
119
+            'upc': ('oscar.models.fields.NullCharField', [], {'max_length': '64', 'unique': 'True', 'null': 'True', 'blank': 'True'})
120
+        },
121
+        u'catalogue.productattribute': {
122
+            'Meta': {'ordering': "['code']", 'object_name': 'ProductAttribute'},
123
+            'code': ('django.db.models.fields.SlugField', [], {'max_length': '128'}),
124
+            'entity_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeEntityType']", 'null': 'True', 'blank': 'True'}),
125
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
126
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
127
+            'option_group': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeOptionGroup']", 'null': 'True', 'blank': 'True'}),
128
+            'product_class': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'attributes'", 'null': 'True', 'to': u"orm['catalogue.ProductClass']"}),
129
+            'required': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
130
+            'type': ('django.db.models.fields.CharField', [], {'default': "'text'", 'max_length': '20'})
131
+        },
132
+        u'catalogue.productattributevalue': {
133
+            'Meta': {'object_name': 'ProductAttributeValue'},
134
+            'attribute': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.ProductAttribute']"}),
135
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
136
+            'product': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'attribute_values'", 'to': u"orm['catalogue.Product']"}),
137
+            'value_boolean': ('django.db.models.fields.NullBooleanField', [], {'null': 'True', 'blank': 'True'}),
138
+            'value_date': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
139
+            'value_entity': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeEntity']", 'null': 'True', 'blank': 'True'}),
140
+            'value_file': ('django.db.models.fields.files.FileField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
141
+            'value_float': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
142
+            'value_image': ('django.db.models.fields.files.ImageField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
143
+            'value_integer': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
144
+            'value_option': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.AttributeOption']", 'null': 'True', 'blank': 'True'}),
145
+            'value_richtext': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
146
+            'value_text': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'})
147
+        },
148
+        u'catalogue.productcategory': {
149
+            'Meta': {'ordering': "['product', 'category']", 'object_name': 'ProductCategory'},
150
+            'category': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Category']"}),
151
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
152
+            'product': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Product']"})
153
+        },
154
+        u'catalogue.productclass': {
155
+            'Meta': {'ordering': "['name']", 'object_name': 'ProductClass'},
156
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
157
+            'name': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
158
+            'options': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['catalogue.Option']", 'symmetrical': 'False', 'blank': 'True'}),
159
+            'requires_shipping': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
160
+            'slug': ('oscar.models.fields.autoslugfield.AutoSlugField', [], {'allow_duplicates': 'False', 'max_length': '128', 'separator': "u'-'", 'blank': 'True', 'unique': 'True', 'populate_from': "'name'", 'overwrite': 'False'}),
161
+            'track_stock': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
162
+        },
163
+        u'catalogue.productimage': {
164
+            'Meta': {'ordering': "['display_order']", 'unique_together': "(('product', 'display_order'),)", 'object_name': 'ProductImage'},
165
+            'caption': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True', 'blank': 'True'}),
166
+            'date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
167
+            'display_order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
168
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
169
+            'original': ('django.db.models.fields.files.ImageField', [], {'max_length': '255'}),
170
+            'product': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'images'", 'to': u"orm['catalogue.Product']"})
171
+        },
172
+        u'catalogue.productrecommendation': {
173
+            'Meta': {'object_name': 'ProductRecommendation'},
174
+            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
175
+            'primary': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'primary_recommendations'", 'to': u"orm['catalogue.Product']"}),
176
+            'ranking': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '0'}),
177
+            'recommendation': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['catalogue.Product']"})
178
+        }
179
+    }
180
+
181
+    complete_apps = ['catalogue']

+ 0
- 12
oscar/apps/catalogue/models.py Просмотреть файл

@@ -20,18 +20,6 @@ class Product(AbstractProduct):
20 20
     pass
21 21
 
22 22
 
23
-class ContributorRole(AbstractContributorRole):
24
-    pass
25
-
26
-
27
-class Contributor(AbstractContributor):
28
-    pass
29
-
30
-
31
-class ProductContributor(AbstractProductContributor):
32
-    pass
33
-
34
-
35 23
 class ProductAttribute(AbstractProductAttribute):
36 24
     pass
37 25
 

+ 2
- 2
oscar/apps/dashboard/catalogue/forms.py Просмотреть файл

@@ -272,7 +272,7 @@ class ProductForm(forms.ModelForm):
272 272
 
273 273
     class Meta:
274 274
         model = Product
275
-        exclude = ('slug', 'status', 'score', 'product_class',
275
+        exclude = ('slug', 'score', 'product_class',
276 276
                    'recommended_products', 'product_options',
277 277
                    'attributes', 'categories')
278 278
         widgets = {
@@ -379,7 +379,7 @@ class ProductForm(forms.ModelForm):
379 379
 
380 380
 
381 381
 class StockAlertSearchForm(forms.Form):
382
-    status = forms.CharField(label=_('Status'))
382
+    tatus = forms.CharField(label=_('Status'))
383 383
 
384 384
 
385 385
 class ProductCategoryForm(forms.ModelForm):

Загрузка…
Отмена
Сохранить