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

Merge pull request #1022 from mbertheau/easily-add-new-formset-to-product-update-page

Easily add new formset to product update page
master
Maik Hoepfel 12 лет назад
Родитель
Сommit
f22b7f93ca
2 измененных файлов: 74 добавлений и 66 удалений
  1. 22
    10
      oscar/apps/dashboard/catalogue/forms.py
  2. 52
    56
      oscar/apps/dashboard/catalogue/views.py

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

@@ -1,6 +1,6 @@
1 1
 from django import forms
2 2
 from django.core.exceptions import ValidationError, MultipleObjectsReturned
3
-from django.forms.models import inlineformset_factory, BaseInlineFormSet
3
+from django.forms.models import inlineformset_factory
4 4
 from django.db.models import get_model
5 5
 from django.utils.translation import ugettext_lazy as _
6 6
 from treebeard.forms import MoveNodeForm, movenodeform_factory
@@ -364,7 +364,15 @@ class ProductCategoryForm(forms.ModelForm):
364 364
         model = ProductCategory
365 365
 
366 366
 
367
-class BaseProductCategoryFormSet(BaseInlineFormSet):
367
+BaseProductCategoryFormSet = inlineformset_factory(
368
+    Product, ProductCategory, form=ProductCategoryForm,
369
+    fields=('category',), extra=1, can_delete=False)
370
+
371
+
372
+class ProductCategoryFormSet(BaseProductCategoryFormSet):
373
+
374
+    def __init__(self, product_class, user, *args, **kwargs):
375
+        super(ProductCategoryFormSet, self).__init__(*args, **kwargs)
368 376
 
369 377
     def clean(self):
370 378
         if self.instance.is_top_level and self.get_num_categories() == 0:
@@ -385,12 +393,6 @@ class BaseProductCategoryFormSet(BaseInlineFormSet):
385 393
         return num_categories
386 394
 
387 395
 
388
-ProductCategoryFormSet = inlineformset_factory(
389
-    Product, ProductCategory, form=ProductCategoryForm,
390
-    formset=BaseProductCategoryFormSet, fields=('category',), extra=1,
391
-    can_delete=False)
392
-
393
-
394 396
 class ProductImageForm(forms.ModelForm):
395 397
     class Meta:
396 398
         model = ProductImage
@@ -415,10 +417,15 @@ class ProductImageForm(forms.ModelForm):
415 417
         return self.prefix.split('-').pop()
416 418
 
417 419
 
418
-ProductImageFormSet = inlineformset_factory(
420
+BaseProductImageFormSet = inlineformset_factory(
419 421
     Product, ProductImage, form=ProductImageForm, extra=2)
420 422
 
421 423
 
424
+class ProductImageFormSet(BaseProductImageFormSet):
425
+    def __init__(self, product_class, user, *args, **kwargs):
426
+        super(ProductImageFormSet, self).__init__(*args, **kwargs)
427
+
428
+
422 429
 class ProductRecommendationForm(forms.ModelForm):
423 430
     class Meta:
424 431
         model = ProductRecommendation
@@ -427,6 +434,11 @@ class ProductRecommendationForm(forms.ModelForm):
427 434
         }
428 435
 
429 436
 
430
-ProductRecommendationFormSet = inlineformset_factory(
437
+BaseProductRecommendationFormSet = inlineformset_factory(
431 438
     Product, ProductRecommendation, form=ProductRecommendationForm,
432 439
     extra=5, fk_name="primary")
440
+
441
+
442
+class ProductRecommendationFormSet(BaseProductRecommendationFormSet):
443
+    def __init__(self, product_class, user, *args, **kwargs):
444
+        super(ProductRecommendationFormSet, self).__init__(*args, **kwargs)

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

@@ -171,6 +171,13 @@ class ProductCreateUpdateView(generic.UpdateView):
171 171
     recommendations_formset = ProductRecommendationFormSet
172 172
     stockrecord_formset = StockRecordFormSet
173 173
 
174
+    def __init__(self, *args, **kwargs):
175
+        super(ProductCreateUpdateView, self).__init__(*args, **kwargs)
176
+        self.formsets = {'category_formset': self.category_formset,
177
+                         'image_formset': self.image_formset,
178
+                         'recommended_formset': self.recommendations_formset,
179
+                         'stockrecord_formset': self.stockrecord_formset}
180
+
174 181
     def get_queryset(self):
175 182
         """
176 183
         Filter products that the user doesn't have permission to update
@@ -202,17 +209,13 @@ class ProductCreateUpdateView(generic.UpdateView):
202 209
     def get_context_data(self, **kwargs):
203 210
         ctx = super(ProductCreateUpdateView, self).get_context_data(**kwargs)
204 211
         ctx['product_class'] = self.product_class
205
-        if 'stockrecord_formset' not in ctx:
206
-            ctx['stockrecord_formset'] = self.stockrecord_formset(
207
-                self.product_class, self.request.user, instance=self.object)
208
-        if 'category_formset' not in ctx:
209
-            ctx['category_formset'] \
210
-                = self.category_formset(instance=self.object)
211
-        if 'image_formset' not in ctx:
212
-            ctx['image_formset'] = self.image_formset(instance=self.object)
213
-        if 'recommended_formset' not in ctx:
214
-            ctx['recommended_formset'] \
215
-                = self.recommendations_formset(instance=self.object)
212
+
213
+        for ctx_name, formset_class in self.formsets.iteritems():
214
+            if ctx_name not in ctx:
215
+                ctx[ctx_name] = formset_class(self.product_class,
216
+                                              self.request.user,
217
+                                              instance=self.object)
218
+
216 219
         if self.object is None:
217 220
             ctx['title'] = _('Create new %s product') % self.product_class.name
218 221
         else:
@@ -224,12 +227,6 @@ class ProductCreateUpdateView(generic.UpdateView):
224 227
         kwargs['product_class'] = self.product_class
225 228
         return kwargs
226 229
 
227
-    def form_valid(self, form):
228
-        return self.process_all_forms(form)
229
-
230
-    def form_invalid(self, form):
231
-        return self.process_all_forms(form)
232
-
233 230
     def process_all_forms(self, form):
234 231
         """
235 232
         Short-circuits the regular logic to have one place to have our
@@ -240,39 +237,45 @@ class ProductCreateUpdateView(generic.UpdateView):
240 237
         if self.creating and form.is_valid():
241 238
             self.object = form.save()
242 239
 
243
-        stockrecord_formset = self.stockrecord_formset(
244
-            self.product_class, self.request.user,
245
-            self.request.POST, instance=self.object)
246
-        category_formset = self.category_formset(
247
-            self.request.POST, instance=self.object)
248
-        image_formset = self.image_formset(
249
-            self.request.POST, self.request.FILES, instance=self.object)
250
-        recommended_formset = self.recommendations_formset(
251
-            self.request.POST, self.request.FILES, instance=self.object)
252
-
253
-        is_valid = all([
254
-            form.is_valid(),
255
-            category_formset.is_valid(),
256
-            image_formset.is_valid(),
257
-            recommended_formset.is_valid(),
258
-            stockrecord_formset.is_valid(),
259
-        ])
260
-
261
-        if is_valid:
262
-            return self.forms_valid(
263
-                form, stockrecord_formset, category_formset,
264
-                image_formset, recommended_formset)
240
+        formsets = {}
241
+        for ctx_name, formset_class in self.formsets.iteritems():
242
+            formsets[ctx_name] = formset_class(self.product_class,
243
+                                               self.request.user,
244
+                                               self.request.POST,
245
+                                               self.request.FILES,
246
+                                               instance=self.object)
247
+
248
+        is_valid = form.is_valid() and all([formset.is_valid()
249
+                                            for formset in formsets.values()])
250
+
251
+        cross_form_validation_result = self.clean(form, formsets)
252
+        if is_valid and cross_form_validation_result:
253
+            return self.forms_valid(form, formsets)
265 254
         else:
266 255
             # delete the temporary product again
267
-            if self.creating and form.is_valid():
256
+            if self.creating and self.object and self.object.pk is not None:
268 257
                 self.object.delete()
269 258
                 self.object = None
270
-            return self.forms_invalid(
271
-                form, stockrecord_formset, category_formset,
272
-                image_formset, recommended_formset)
259
+            return self.forms_invalid(form, formsets)
260
+
261
+    # form_valid and form_invalid are called depending on the validation result
262
+    # of just the product form and redisplay the form respectively return a
263
+    # redirect to the success URL. In both cases we need to check our formsets
264
+    # as well, so both methods do the same. process_all_forms then calls
265
+    # forms_valid or forms_invalid respectively, which do the redisplay or
266
+    # redirect.
267
+    form_valid = form_invalid = process_all_forms
268
+
269
+    def clean(self, form, formsets):
270
+        """
271
+        Perform any cross-form/formset validation. If there are errors, attach
272
+        errors to a form or a form field so that they are displayed to the user
273
+        and return False. If everything is valid, return True. This method will
274
+        be called regardless of whether the individual forms are valid.
275
+        """
276
+        return True
273 277
 
274
-    def forms_valid(self, form, stockrecord_formset, category_formset,
275
-                    image_formset, recommended_formset):
278
+    def forms_valid(self, form, formsets):
276 279
         """
277 280
         Save all changes and display a success url.
278 281
         """
@@ -281,23 +284,16 @@ class ProductCreateUpdateView(generic.UpdateView):
281 284
             self.object = form.save()
282 285
 
283 286
         # Save formsets
284
-        category_formset.save()
285
-        image_formset.save()
286
-        recommended_formset.save()
287
-        stockrecord_formset.save()
287
+        for formset in formsets.values():
288
+            formset.save()
288 289
 
289 290
         return HttpResponseRedirect(self.get_success_url())
290 291
 
291
-    def forms_invalid(self, form, stockrecord_formset, category_formset,
292
-                      image_formset, recommended_formset):
292
+    def forms_invalid(self, form, formsets):
293 293
         messages.error(self.request,
294 294
                        _("Your submitted data was not valid - please "
295 295
                          "correct the below errors"))
296
-        ctx = self.get_context_data(form=form,
297
-                                    stockrecord_formset=stockrecord_formset,
298
-                                    category_formset=category_formset,
299
-                                    image_formset=image_formset,
300
-                                    recommended_formset=recommended_formset)
296
+        ctx = self.get_context_data(form=form, **formsets)
301 297
         return self.render_to_response(ctx)
302 298
 
303 299
     def get_url_with_querystring(self, url):

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