Преглед на файлове

[Refactor] Move OfferWizardStepView to separate file (#4174)

* refactor :package: move OfferWizardStepView to separate file

* refactor :package: remove unused offer combinations code

* refactor :package: remove unused get_back_url method
master
Samar Hassan преди 1 година
родител
ревизия
ccf712a520
No account linked to committer's email address
променени са 2 файла, в които са добавени 193 реда и са изтрити 196 реда
  1. 2
    196
      src/oscar/apps/dashboard/offers/views.py
  2. 191
    0
      src/oscar/apps/dashboard/offers/wizard_views.py

+ 2
- 196
src/oscar/apps/dashboard/offers/views.py Целия файл

@@ -1,16 +1,12 @@
1
-import json
2
-
3 1
 from django.conf import settings
4 2
 from django.contrib import messages
5
-from django.core import serializers
6
-from django.core.serializers.json import DjangoJSONEncoder
7 3
 from django.db.models import Count, Q
8 4
 from django.http import HttpResponseRedirect
9 5
 from django.shortcuts import get_object_or_404, redirect
10 6
 from django.urls import reverse
11 7
 from django.utils import timezone
12 8
 from django.utils.translation import gettext_lazy as _
13
-from django.views.generic import DeleteView, FormView, ListView
9
+from django.views.generic import DeleteView, ListView
14 10
 
15 11
 from oscar.core.loading import get_class, get_classes, get_model
16 12
 from oscar.views import sort_queryset
@@ -37,6 +33,7 @@ Benefit = get_model("offer", "Benefit")
37 33
         "OfferSearchForm",
38 34
     ],
39 35
 )
36
+OfferWizardStepView = get_class("dashboard.offers.wizard_views", "OfferWizardStepView")
40 37
 OrderDiscountCSVFormatter = get_class(
41 38
     "dashboard.offers.reports", "OrderDiscountCSVFormatter"
42 39
 )
@@ -125,197 +122,6 @@ class OfferListView(ListView):
125 122
         return ctx
126 123
 
127 124
 
128
-class OfferWizardStepView(FormView):
129
-    wizard_name = "offer_wizard"
130
-    form_class = None
131
-    step_name = None
132
-    update = False
133
-    url_name = None
134
-    success_url_name = "dashboard:offer-list"
135
-
136
-    # Keep a reference to previous view class to allow checks to be made on
137
-    # whether prior steps have been completed
138
-    previous_view = None
139
-
140
-    # pylint: disable=attribute-defined-outside-init
141
-    def dispatch(self, request, *args, **kwargs):
142
-        if self.update:
143
-            self.offer = get_object_or_404(ConditionalOffer, id=kwargs["pk"])
144
-        if not self.is_previous_step_complete(request):
145
-            messages.warning(
146
-                request,
147
-                _("%s step not complete") % (self.previous_view.step_name.title(),),
148
-            )
149
-            return HttpResponseRedirect(self.get_back_url())
150
-        return super().dispatch(request, *args, **kwargs)
151
-
152
-    def is_previous_step_complete(self, request):
153
-        if not self.previous_view:
154
-            return True
155
-        return self.previous_view.is_valid(self, request)
156
-
157
-    def _key(self, step_name=None, is_object=False):
158
-        key = step_name if step_name else self.step_name
159
-        if self.update:
160
-            key += str(self.offer.id)
161
-        if is_object:
162
-            key += "_obj"
163
-        return key
164
-
165
-    def _store_form_kwargs(self, form):
166
-        session_data = self.request.session.setdefault(self.wizard_name, {})
167
-
168
-        # Adjust kwargs to avoid trying to save the range instance
169
-        form_data = form.cleaned_data.copy()
170
-        product_range = form_data.get("range")
171
-        if product_range is not None:
172
-            form_data["range"] = product_range.id
173
-
174
-        combinations = form_data.get("combinations")
175
-        if combinations is not None:
176
-            form_data["combination_ids"] = [x.id for x in combinations]
177
-            del form_data["combinations"]
178
-
179
-        form_kwargs = {"data": form_data}
180
-        json_data = json.dumps(form_kwargs, cls=DjangoJSONEncoder)
181
-
182
-        session_data[self._key()] = json_data
183
-        self.request.session.save()
184
-
185
-    def _fetch_form_kwargs(self):
186
-        session_data = self.request.session.setdefault(self.wizard_name, {})
187
-        json_data = session_data.get(self._key(self.step_name), None)
188
-        if json_data:
189
-            return json.loads(json_data)
190
-
191
-        return {}
192
-
193
-    def _store_object(self, form):
194
-        session_data = self.request.session.setdefault(self.wizard_name, {})
195
-
196
-        # We don't store the object instance as that is not JSON serialisable.
197
-        # Instead, we save an alternative form
198
-        instance = form.save(commit=False)
199
-        # remove fields that do not exist (yet) on the uncommitted instance, i.e. m2m fields
200
-        cleanfields = [field.name for field in instance._meta.local_fields]
201
-
202
-        json_qs = serializers.serialize("json", [instance], fields=tuple(cleanfields))
203
-
204
-        session_data[self._key(is_object=True)] = json_qs
205
-        self.request.session.save()
206
-
207
-    def _fetch_object(self, step_name, request=None):
208
-        if request is None:
209
-            request = self.request
210
-        session_data = request.session.setdefault(self.wizard_name, {})
211
-        json_qs = session_data.get(self._key(step_name, is_object=True), None)
212
-        if json_qs:
213
-            # Recreate model instance from passed data
214
-            deserialised_obj = list(serializers.deserialize("json", json_qs))
215
-            return deserialised_obj[0].object
216
-
217
-    def _fetch_session_offer(self):
218
-        """Return the offer instance loaded with the data stored in the session.
219
-
220
-        When updating an offer, the updated fields are used with the existing
221
-        offer data.
222
-        """
223
-        offer = self._fetch_object("metadata")
224
-        if offer is None and self.update:
225
-            offer = self.offer
226
-        return offer
227
-
228
-    def _flush_session(self):
229
-        self.request.session[self.wizard_name] = {}
230
-        self.request.session.save()
231
-
232
-    def get_form_kwargs(self, *args, **kwargs):
233
-        form_kwargs = {}
234
-        if self.update:
235
-            form_kwargs["instance"] = self.get_instance()
236
-        session_kwargs = self._fetch_form_kwargs()
237
-        form_kwargs.update(session_kwargs)
238
-        parent_kwargs = super().get_form_kwargs(*args, **kwargs)
239
-        form_kwargs.update(parent_kwargs)
240
-        return form_kwargs
241
-
242
-    def get_context_data(self, **kwargs):
243
-        ctx = super().get_context_data(**kwargs)
244
-        if self.update:
245
-            ctx["offer"] = self.offer
246
-        ctx["session_offer"] = self._fetch_session_offer()
247
-        ctx["title"] = self.get_title()
248
-        return ctx
249
-
250
-    def get_back_url(self):
251
-        if not self.previous_view:
252
-            return None
253
-        if self.update:
254
-            return reverse(
255
-                self.previous_view.url_name, kwargs={"pk": self.kwargs["pk"]}
256
-            )
257
-        return reverse(self.previous_view.url_name)
258
-
259
-    def get_title(self):
260
-        return self.step_name.title()
261
-
262
-    def form_valid(self, form):
263
-        self._store_form_kwargs(form)
264
-        self._store_object(form)
265
-
266
-        if self.update and "save" in form.data:
267
-            # Save changes to this offer when updating and pressed save button
268
-            return self.save_offer(self.offer)
269
-        else:
270
-            # Proceed to next page
271
-            return super().form_valid(form)
272
-
273
-    def save_offer(self, offer):
274
-        # We update the offer with the name/description/offer_type from step 1
275
-        session_offer = self._fetch_session_offer()
276
-        offer.name = session_offer.name
277
-        offer.description = session_offer.description
278
-        offer.offer_type = session_offer.offer_type
279
-
280
-        # Save the related models, then save the offer.
281
-        # Note than you can save already on the first page of the wizard,
282
-        # so le'ts check if the benefit and condition exist
283
-        benefit = self._fetch_object("benefit")
284
-        if benefit:
285
-            benefit.save()
286
-            offer.benefit = benefit
287
-
288
-        condition = self._fetch_object("condition")
289
-        if condition:
290
-            condition.save()
291
-            offer.condition = condition
292
-
293
-        offer.save()
294
-
295
-        self._flush_session()
296
-
297
-        if self.update:
298
-            msg = _("Offer '%s' updated") % offer.name
299
-        else:
300
-            msg = _("Offer '%s' created!") % offer.name
301
-        messages.success(self.request, msg)
302
-
303
-        return HttpResponseRedirect(
304
-            reverse("dashboard:offer-detail", kwargs={"pk": offer.pk})
305
-        )
306
-
307
-    def get_success_url(self):
308
-        if self.update:
309
-            return reverse(self.success_url_name, kwargs={"pk": self.kwargs["pk"]})
310
-        return reverse(self.success_url_name)
311
-
312
-    @classmethod
313
-    def is_valid(cls, current_view, request):
314
-        if current_view.update:
315
-            return True
316
-        return current_view._fetch_object(cls.step_name, request) is not None
317
-
318
-
319 125
 class OfferMetaDataView(OfferWizardStepView):
320 126
     step_name = "metadata"
321 127
     form_class = MetaDataForm

+ 191
- 0
src/oscar/apps/dashboard/offers/wizard_views.py Целия файл

@@ -0,0 +1,191 @@
1
+import json
2
+
3
+from django.contrib import messages
4
+from django.core import serializers
5
+from django.core.serializers.json import DjangoJSONEncoder
6
+from django.http import HttpResponseRedirect
7
+from django.shortcuts import get_object_or_404
8
+from django.urls import reverse
9
+from django.utils.translation import gettext_lazy as _
10
+from django.views.generic import FormView
11
+
12
+from oscar.core.loading import get_model
13
+
14
+ConditionalOffer = get_model("offer", "ConditionalOffer")
15
+
16
+
17
+class OfferWizardStepView(FormView):
18
+    wizard_name = "offer_wizard"
19
+    form_class = None
20
+    step_name = None
21
+    update = False
22
+    url_name = None
23
+    success_url_name = "dashboard:offer-list"
24
+
25
+    # Keep a reference to previous view class to allow checks to be made on
26
+    # whether prior steps have been completed
27
+    previous_view = None
28
+
29
+    # pylint: disable=attribute-defined-outside-init
30
+    def dispatch(self, request, *args, **kwargs):
31
+        if self.update:
32
+            self.offer = get_object_or_404(ConditionalOffer, id=kwargs["pk"])
33
+        if not self.is_previous_step_complete(request):
34
+            messages.warning(
35
+                request,
36
+                _("%s step not complete") % (self.previous_view.step_name.title(),),
37
+            )
38
+            return HttpResponseRedirect(reverse(self.previous_view.url_name))
39
+        return super().dispatch(request, *args, **kwargs)
40
+
41
+    def is_previous_step_complete(self, request):
42
+        if not self.previous_view:
43
+            return True
44
+        return self.previous_view.is_valid(self, request)
45
+
46
+    def _key(self, step_name=None, is_object=False):
47
+        key = step_name if step_name else self.step_name
48
+        if self.update:
49
+            key += str(self.offer.id)
50
+        if is_object:
51
+            key += "_obj"
52
+        return key
53
+
54
+    def _store_form_kwargs(self, form):
55
+        session_data = self.request.session.setdefault(self.wizard_name, {})
56
+
57
+        # Adjust kwargs to avoid trying to save the range instance
58
+        form_data = form.cleaned_data.copy()
59
+        product_range = form_data.get("range")
60
+        if product_range is not None:
61
+            form_data["range"] = product_range.id
62
+
63
+        form_kwargs = {"data": form_data}
64
+        json_data = json.dumps(form_kwargs, cls=DjangoJSONEncoder)
65
+
66
+        session_data[self._key()] = json_data
67
+        self.request.session.save()
68
+
69
+    def _fetch_form_kwargs(self):
70
+        session_data = self.request.session.setdefault(self.wizard_name, {})
71
+        json_data = session_data.get(self._key(self.step_name), None)
72
+        if json_data:
73
+            return json.loads(json_data)
74
+
75
+        return {}
76
+
77
+    def _store_object(self, form):
78
+        session_data = self.request.session.setdefault(self.wizard_name, {})
79
+
80
+        # We don't store the object instance as that is not JSON serialisable.
81
+        # Instead, we save an alternative form
82
+        instance = form.save(commit=False)
83
+        # remove fields that do not exist (yet) on the uncommitted instance, i.e. m2m fields
84
+        cleanfields = [field.name for field in instance._meta.local_fields]
85
+
86
+        json_qs = serializers.serialize("json", [instance], fields=tuple(cleanfields))
87
+
88
+        session_data[self._key(is_object=True)] = json_qs
89
+        self.request.session.save()
90
+
91
+    def _fetch_object(self, step_name, request=None):
92
+        if request is None:
93
+            request = self.request
94
+        session_data = request.session.setdefault(self.wizard_name, {})
95
+        json_qs = session_data.get(self._key(step_name, is_object=True), None)
96
+        if json_qs:
97
+            # Recreate model instance from passed data
98
+            deserialised_obj = list(serializers.deserialize("json", json_qs))
99
+            return deserialised_obj[0].object
100
+
101
+    def _fetch_session_offer(self):
102
+        """Return the offer instance loaded with the data stored in the session.
103
+
104
+        When updating an offer, the updated fields are used with the existing
105
+        offer data.
106
+        """
107
+        offer = self._fetch_object("metadata")
108
+        if offer is None and self.update:
109
+            offer = self.offer
110
+        return offer
111
+
112
+    def _flush_session(self):
113
+        self.request.session[self.wizard_name] = {}
114
+        self.request.session.save()
115
+
116
+    def get_form_kwargs(self, *args, **kwargs):
117
+        form_kwargs = {}
118
+        if self.update:
119
+            form_kwargs["instance"] = self.get_instance()
120
+        session_kwargs = self._fetch_form_kwargs()
121
+        form_kwargs.update(session_kwargs)
122
+        parent_kwargs = super().get_form_kwargs(*args, **kwargs)
123
+        form_kwargs.update(parent_kwargs)
124
+        return form_kwargs
125
+
126
+    def get_context_data(self, **kwargs):
127
+        ctx = super().get_context_data(**kwargs)
128
+        if self.update:
129
+            ctx["offer"] = self.offer
130
+        ctx["session_offer"] = self._fetch_session_offer()
131
+        ctx["title"] = self.get_title()
132
+        return ctx
133
+
134
+    def get_title(self):
135
+        return self.step_name.title()
136
+
137
+    def form_valid(self, form):
138
+        self._store_form_kwargs(form)
139
+        self._store_object(form)
140
+
141
+        if self.update and "save" in form.data:
142
+            # Save changes to this offer when updating and pressed save button
143
+            return self.save_offer(self.offer)
144
+        else:
145
+            # Proceed to next page
146
+            return super().form_valid(form)
147
+
148
+    def save_offer(self, offer):
149
+        # We update the offer with the name/description/offer_type from step 1
150
+        session_offer = self._fetch_session_offer()
151
+        offer.name = session_offer.name
152
+        offer.description = session_offer.description
153
+        offer.offer_type = session_offer.offer_type
154
+
155
+        # Save the related models, then save the offer.
156
+        # Note than you can save already on the first page of the wizard,
157
+        # so le'ts check if the benefit and condition exist
158
+        benefit = self._fetch_object("benefit")
159
+        if benefit:
160
+            benefit.save()
161
+            offer.benefit = benefit
162
+
163
+        condition = self._fetch_object("condition")
164
+        if condition:
165
+            condition.save()
166
+            offer.condition = condition
167
+
168
+        offer.save()
169
+
170
+        self._flush_session()
171
+
172
+        if self.update:
173
+            msg = _("Offer '%s' updated") % offer.name
174
+        else:
175
+            msg = _("Offer '%s' created!") % offer.name
176
+        messages.success(self.request, msg)
177
+
178
+        return HttpResponseRedirect(
179
+            reverse("dashboard:offer-detail", kwargs={"pk": offer.pk})
180
+        )
181
+
182
+    def get_success_url(self):
183
+        if self.update:
184
+            return reverse(self.success_url_name, kwargs={"pk": self.kwargs["pk"]})
185
+        return reverse(self.success_url_name)
186
+
187
+    @classmethod
188
+    def is_valid(cls, current_view, request):
189
+        if current_view.update:
190
+            return True
191
+        return current_view._fetch_object(cls.step_name, request) is not None

Loading…
Отказ
Запис