def get(self, request): # noqa (C901) model_name = request.GET.get("model") object_id = request.GET.get("pk", request.GET.get("id")) if not model_name or not object_id: return HttpResponseBadRequest(_("Invalid object.")) url = None try: model = apps.get_model(model_name) except LookupError: return HttpResponseBadRequest(_("Invalid model.")) instance = model.objects.filter(pk=object_id).first() if instance: try: # try edit first try: url = get_model_url( instance, kind="edit", user=request.user, shop=get_shop(request), raise_permission_denied=True ) except NoModelUrl: # try detail try: url = get_model_url( instance, kind="detail", user=request.user, shop=get_shop(request), raise_permission_denied=True ) except NoModelUrl: pass except PermissionDenied as exception: from django.utils.encoding import force_text raise Problem(force_text(exception)) if url: # forward the mode param if request.GET.get("mode"): url = "{}?mode={}".format(url, request.GET["mode"]) return HttpResponseRedirect(url) raise Http404(_("Object not found"))
def get_help_blocks(self, request, kind): if kind == "setup": shop = request.shop yield SimpleHelpBlock( text=_("Add a logo to make your store stand out"), actions=[{ "text": _("Add logo"), "url": self.get_model_url(shop, "edit"), "hash": "#shop-images-section" }], icon_url="shuup_admin/img/logo_icon.svg", done=shop.logo, required=False ) shop = get_shop(request) yield SimpleHelpBlock( priority=1000, text=_("Publish your store"), description=_("Let customers browse your store and make purchases"), css_class="green ", actions=[{ "method": "POST", "text": _("Publish shop"), "url": reverse("shuup_admin:shop.enable", kwargs={"pk": shop.pk}), "data": { "enable": True, "redirect": reverse("shuup_admin:dashboard") } }], icon_url="shuup_admin/img/publish.png", done=(not shop.maintenance_mode), required=False )
def post(self, request): """ Create the Script from template directly if the template does not have a bound form. If the script template has a bound form, redirect to the template configuration view. If no script template is found, redirect to the script list. """ identifier = request.POST.get("id", None) script_template_class = get_identifier_to_object_map(SCRIPT_TEMPLATES_PROVIDE_CATEGORY).get(identifier) if script_template_class: script_template = script_template_class() # the template has a form for configuration.. lets redirect to the correct view if script_template.get_form(): return redirect("shuup_admin:notify.script-template-config", id=identifier) else: shop = get_shop(request) script = script_template.create_script(shop) if script: script.template = identifier script.save(update_fields=["template"]) messages.success(request, _("Script created from template!")) return redirect("shuup_admin:notify.script.list") else: messages.error(request, _("Template Script not found!")) return redirect("shuup_admin:notify.script.list")
def handle_get_folder(self, data): shop = get_shop(self.request) try: folder_id = int(data.get("id", 0)) if folder_id: folder = _get_folder_query(shop).get(pk=folder_id) subfolders = folder.get_children().filter(_get_folder_query_filter(shop)) files = _get_file_query(shop, folder) else: folder = None subfolders = _get_folder_query(shop).filter(parent=None) files = _get_file_query(shop).filter(folder=None) except ObjectDoesNotExist: return JsonResponse({ "folder": None, "error": "Folder does not exist" }) if self.filter == "images": files = files.instance_of(Image) return JsonResponse({"folder": { "id": folder.id if folder else 0, "name": get_folder_name(folder), "files": [_filer_file_to_json_dict(file) for file in files if file.is_public], "folders": [ # Explicitly pass empty list of children to avoid recursion _filer_folder_to_json_dict(subfolder, children=()) for subfolder in subfolders.order_by("name") ] }})
def get_queryset(self): # get coupons for this shop or for shared shops queryset = super(CouponEditView, self).get_queryset().filter(shop=get_shop(self.request)) supplier = get_supplier(self.request) if supplier: queryset = queryset.filter(supplier=supplier) return queryset
def media_upload(request, *args, **kwargs): shop = get_shop(request) try: folder_id = int(request.POST.get("folder_id") or request.GET.get("folder_id") or 0) path = request.POST.get("path") or request.GET.get("path") or None if folder_id != 0: folder = _get_folder_query(shop).get(pk=folder_id) elif path: folder = get_or_create_folder(shop, path) else: folder = None # Root folder upload. How bold! except Exception as exc: return JsonResponse({"error": "Invalid folder: %s" % force_text(exc)}) try: upload_file = request.FILES["file"] if upload_file.content_type.startswith("image/"): filer_file = filer_image_from_upload(request, path=folder, upload_data=upload_file) else: filer_file = filer_file_from_upload(request, path=folder, upload_data=upload_file) _ensure_media_file(shop, filer_file) except Exception as exc: return JsonResponse({"error": force_text(exc)}) return JsonResponse({ "file": _filer_file_to_json_dict(filer_file), "message": _("%(file)s uploaded to %(folder)s") % { "file": filer_file.label, "folder": get_folder_name(folder) } })
def model_url(context, model, kind="detail", default=None, **kwargs): """ Get a model URL of the given kind for a model (instance or class). :param context: Jinja rendering context :type context: jinja2.runtime.Context :param model: The model instance or class. :type model: django.db.Model :param kind: The URL kind to retrieve. See `get_model_url`. :type kind: str :param default: Default value to return if model URL retrieval fails. :type default: str :return: URL string. :rtype: str """ user = context.get("user") try: request = context.get("request") shop = get_shop(request) if request else None admin_model_url_resolvers = get_provide_objects("admin_model_url_resolver") for resolver in admin_model_url_resolvers: url = resolver(model, kind=kind, user=user, shop=shop, **kwargs) if url: return url except NoModelUrl: return default
def is_url_valid(self, language_code, field_name, url): """ Ensure URL given is unique. Check through the pages translation model objects to make sure that the url given doesn't already exist. Possible failure cases: for new page: * URL already exists for existing page: * URL (other than owned by existing page) exists * URL exists in other languages of existing page """ pages_ids = Page.objects.for_shop(get_shop(self.request)).values_list("id", flat=True) qs = self._get_translation_model().objects.filter(url=url, master_id__in=pages_ids) if not self.instance.pk and qs.exists(): return False other_qs = qs.exclude(master=self.instance) if other_qs.exists(): return False own_qs = qs.filter(master=self.instance).exclude(language_code=language_code) if own_qs.exists(): return False return True
def get_context_data(self, **kwargs): context = super(ProductEditView, self).get_context_data(**kwargs) orderability_errors = [] if self.object.pk: context["title"] = self.object.product.name shop = self.request.shop try: shop_product = self.object orderability_errors.extend( ["%s: %s" % (shop.name, msg.message) for msg in shop_product.get_orderability_errors( supplier=None, quantity=shop_product.minimum_purchase_quantity, customer=None)]) except ObjectDoesNotExist: orderability_errors.extend(["%s: %s" % (shop.name, _("Product is not available."))]) context["orderability_errors"] = orderability_errors context["product_sections"] = [] context["tour_key"] = "product" context["tour_complete"] = is_tour_complete(get_shop(self.request), "product", user=self.request.user) product_sections_provides = sorted(get_provide_objects("admin_product_section"), key=lambda x: x.order) for admin_product_section in product_sections_provides: if admin_product_section.visible_for_object(self.object.product, self.request): context["product_sections"].append(admin_product_section) context[admin_product_section.identifier] = admin_product_section.get_context_data( self.object.product, self.request ) return context
def save_form(self, form): self.object = form.save() contact = self._get_bind_contact() # only touch in shop staff member if the user is not a superuser if not getattr(self.object, "is_superuser", False): shop = get_shop(self.request) if getattr(self.object, "is_staff", False): shop.staff_members.add(self.object) else: shop.staff_members.remove(self.object) if contact and not contact.user: contact.user = self.object contact.save() messages.info(self.request, _(u"User bound to contact %(contact)s.") % {"contact": contact}) if getattr(self.object, "is_staff", False) and form.cleaned_data.get("send_confirmation"): shop_url = "%s://%s/" % (self.request.scheme, self.request.get_host()) admin_url = self.request.build_absolute_uri(reverse("shuup_admin:login")) send_mail( subject=_("You've been added as an admin user to %s" % shop_url), message=NEW_USER_EMAIL_CONFIRMATION_TEMPLATE % { "first_name": getattr(self.object, "first_name") or getattr(self.object, "username", _("User")), "shop_url": shop_url, "admin_url": admin_url, "username": getattr(self.object, "username") or getattr(self.object.email) }, from_email=django_settings.DEFAULT_FROM_EMAIL, recipient_list=[self.object.email] )
def save(self, commit=True): if not self.instance.pk: self.instance.is_active = True obj = super(ContactBaseFormMixin, self).save(commit) shop = get_shop(self.request) obj.groups = [obj.get_default_group()] + list(self.cleaned_data["groups"]) obj.add_to_shops(shop, list(self.cleaned_data["shops"])) return obj
def get_queryset(self): """ Ignore potentially active carts, displaying only those not updated for at least 2 hours. """ shop = get_shop(self.request) cutoff = now() - datetime.timedelta(hours=get_cart_delay_hours(shop)) filters = {"updated_on__lt": cutoff, "product_count__gte": 0, "persistent": False, "shop": shop} return super(CartListView, self).get_queryset().filter(**filters)
def get_context_data(self, **kwargs): context = super(CategoryEditView, self).get_context_data(**kwargs) context["tour_key"] = "category" context["tour_complete"] = is_tour_complete(get_shop(self.request), "category", user=self.request.user) if self.object.pk: context["title"] = self.object.name return context
def __init__(self, **kwargs): self.request = kwargs.pop("request") super(GDPRSettingsForm, self).__init__(**kwargs) shop = get_shop(self.request) choices = [(p.id, p.title) for p in get_possible_consent_pages(shop)] self.fields["privacy_policy_page"].choices = choices self.fields["consent_pages"].required = False self.fields["consent_pages"].choices = choices
def save(self, commit=True): instance = super(SupplierBaseForm, self).save(commit) instance.shop_products.remove( *list(instance.shop_products.exclude(shop_id__in=instance.shops.all()).values_list("pk", flat=True))) if not settings.SHUUP_ENABLE_MULTIPLE_SUPPLIERS or "shops" not in self.fields: instance.shops.add(get_shop(self.request)) return instance
def __init__(self, *args, **kwargs): self.request = kwargs.pop("request") super(TaskForm, self).__init__(*args, **kwargs) shop = get_shop(self.request) self.fields["assigned_to"].queryset = Contact.objects.filter( Q(shops=shop) | Q(id__in=shop.staff_members.values_list("id")) ).distinct() self.fields["assigned_to"].widget.editable_model = "shuup.Contact"
def get_queryset(self): queryset = super(CouponListView, self).get_queryset() if not self.request.user.is_superuser: queryset = queryset.filter(shop=get_shop(self.request)) supplier = get_supplier(self.request) if supplier: queryset = queryset.filter(supplier=supplier) return queryset
def get_queryset(self): queryset = Contact.objects.all() limited = (settings.SHUUP_ENABLE_MULTIPLE_SHOPS and settings.SHUUP_MANAGE_CONTACTS_PER_SHOP and not self.request.user.is_superuser) if limited: queryset = queryset.filter(shops=get_shop(self.request)) return queryset
def process(self, request, ids): shop = get_shop(request) if isinstance(ids, string_types) and ids == "all": query = Q(shop=shop) else: query = Q(product__pk__in=ids, shop=shop) ShopProduct.objects.filter(query).update(visibility=ShopProductVisibility.NOT_VISIBLE) for shop_product in ShopProduct.objects.filter(query).iterator(): context_cache.bump_cache_for_shop_product(shop_product)
def __init__(self, *args, **kwargs): self.request = kwargs.pop("request") super(ContactGroupBaseForm, self).__init__(*args, **kwargs) shop = get_shop(self.request) self.fields["shop"] = forms.ModelChoiceField( queryset=Shop.objects.filter(pk=shop.id), initial=shop, widget=HiddenInput(), label=_('shop'), required=False)
def form_valid(self, form): identifier = form["theme"].cleaned_data["activate"] data = { "settings": { "stylesheet": form["theme"].cleaned_data["selected_style"] } } theme_settings, created = ThemeSettings.objects.get_or_create( theme_identifier=identifier, shop=get_shop(self.request) ) if created: theme_settings.data = data theme_settings.save() else: theme_settings.update_settings(data["settings"]) set_current_theme(identifier, self.object) cache.bump_version(get_theme_cache_key(get_shop(self.request)))
def process(self, request, ids): shop = get_shop(request) if isinstance(ids, six.string_types) and ids == "all": query = Q(shop=shop) else: query = Q(id__in=ids, shop=shop) for order in Order.objects.filter(query): if not order.can_set_canceled(): continue order.set_canceled()
def mark_notification_read_view(self, request, pk): shop = get_shop(request) if request.method == "POST": try: notif = NotificationModel.objects.for_user(request.user).filter(shop=shop).get(pk=pk) except ObjectDoesNotExist: return JsonResponse({"error": "no such notification"}) notif.mark_read(request.user) return JsonResponse({"ok": True}) return JsonResponse({"error": "POST only"})
def handle_post_delete_folder(self, data): shop = get_shop(self.request) folder = _get_folder_query(shop).get(pk=data["id"]) if _is_folder_shared(folder): message = _("Can not delete shared folder.") return JsonResponse({"success": False, "message": message}) new_selected_folder_id = folder.parent_id message = delete_folder(folder) return JsonResponse({"success": True, "message": message, "newFolderId": new_selected_folder_id})
def handle_post_rename_file(self, data): shop = get_shop(self.request) file = _get_file_query(shop).get(pk=data["id"]) if _is_file_shared(file): message = _("Can not rename shared file.") return JsonResponse({"success": False, "message": message}) file.name = data["name"] file.save(update_fields=("name",)) return JsonResponse({"success": True, "message": _("File renamed.")})
def populate(self): super(CarouselConfigForm, self).populate() self.fields["carousel"] = XThemeModelChoiceField( label=_("Carousel"), queryset=Carousel.objects.filter(shops=get_shop(self.request)), required=False, ) self.fields["active"] = BooleanField( label=_("Active"), required=False, )
def get_queryset(self): qs = super(ContactEditView, self).get_queryset() if request_limited(self.request): qs = qs.filter(shops=get_shop(self.request)) # non superusers can't see superusers contacts if not self.request.user.is_superuser: qs = qs.exclude(PersonContact___user__is_superuser=True) return qs
def get_theme(self): """ Get the theme object to configure. :return: Theme object :rtype: shuup.xtheme.Theme """ return get_theme_by_identifier( identifier=self.kwargs["theme_identifier"], shop=get_shop(self.request) )
def handle_post_delete_file(self, data): shop = get_shop(self.request) file = _get_file_query(shop).get(pk=data["id"]) if _is_file_shared(file): message = _("Can not delete shared file.") return JsonResponse({"success": False, "message": message}) try: file.delete() except IntegrityError as ie: raise Problem(str(ie)) return JsonResponse({"success": True, "message": _("File deleted.")})
def __init__(self, request, **kwargs): self.request = request super(CategoryBaseForm, self).__init__(**kwargs) # Exclude `DELETED`. We don't want people to use that field to set a category as deleted. filter_form_field_choices(self.fields["status"], (CategoryStatus.DELETED.value,), invert=True) # Exclude current category from parents, because it cannot be its own child anyways category_queryset = Category.objects.filter(shops=get_shop(request)).exclude(status=CategoryStatus.DELETED) self.fields["parent"].queryset = category_queryset self.fields["parent"].choices = [(None, "----")] + [ (category.pk, force_text(category)) for category in category_queryset.exclude(id=kwargs["instance"].pk) ]
def __init__(self, **kwargs): self.carousel = kwargs.pop("carousel") self.request = kwargs.pop("request") super(SlideForm, self).__init__(**kwargs) self.empty_permitted = False shop = get_shop(self.request) self.fields["category_link"].queryset = Category.objects.filter( shops=shop) self.fields["cms_page_link"].queryset = Page.objects.filter(shop=shop) self.fields["product_link"].widget = ProductChoiceWidget( clearable=True) for lang in self.languages: image_field = "image__%s" % lang self.fields[image_field].widget = FileDnDUploaderWidget( kind="images", upload_path="/carousel", clearable=True) if lang == self.default_language: self.fields[image_field].widget = FileDnDUploaderWidget( kind="images", upload_path="/carousel", clearable=False) self.fields[image_field].required = True self.fields[image_field].widget.is_required = True if not self.fields["available_from"].initial: self.fields["available_from"].initial = now()
def handle_post_delete_folder(self, data): shop = get_shop(self.request) folder = _get_folder_query(shop, self.user).get(pk=data["id"]) # If the folder is not sheard between one or more shop and # the folder is in the subfolder tree of the users root folder or the user has the folder delete permissions. # Then they are alloed to delete the folder. if not _is_folder_shared(folder) and ( subfolder_of_users_root(self.user, folder) or has_permission(self.user, "media.delete-folder") ): new_selected_folder_id = folder.parent_id # This will be changed by the delete function so save it here. try: message = delete_folder(folder) except models.ProtectedError: message = _("This folder is protected and cannot be deleted.") return JsonResponse({"success": False, "message": message}) else: return JsonResponse({"success": True, "message": message, "newFolderId": new_selected_folder_id}) message = _( "Can't delete this folder, either you don't have permssion to do it " "or it's a shared folder between more then one shop" ) return JsonResponse({"success": False, "message": message})
def __init__(self, *args, **kwargs): self.request = kwargs.pop("request") self.shop = get_shop(self.request) super(HappyHourForm, self).__init__(*args, **kwargs) if self.instance.pk: self.fields["discounts"] = Select2MultipleField( label=_("Product Discounts"), help_text=_("Select discounts for this happy hour."), model=Discount, required=False ) initial_discounts = (self.instance.discounts.all() if self.instance.pk else []) self.fields["discounts"].initial = initial_discounts self.fields["discounts"].widget.choices = [ (discount.pk, force_text(discount)) for discount in initial_discounts ] if self.instance.pk: weekdays, from_hour, to_hour = _get_initial_data_for_time_ranges(self.instance) if weekdays and from_hour and to_hour: self.fields["weekdays"].initial = weekdays self.fields["from_hour"].initial = from_hour self.fields["to_hour"].initial = to_hour # Since we touch these views in init we need to reset some # widgets and help texts after setting the initial values. self.fields["from_hour"].widget = TimeInput(attrs={"class": "time"}) self.fields["to_hour"].widget = TimeInput(attrs={"class": "time"}) help_texts = [ ("from_hour", _("12pm is considered noon and 12am as midnight. Start hour is included to the discount.")), ("to_hour", _("12pm is considered noon and 12am as midnight. End hours is included to the discount.")), ("weekdays", _("Weekdays the happy hour is active.")) ] for field, help_text in help_texts: self.fields[field].help_text = help_text
def form_valid(self, form): identifier = form.cleaned_data["activate"] set_current_theme(identifier, get_shop(self.request)) messages.success(self.request, _("Theme activated.")) return HttpResponseRedirect(self.request.path)
def get_context_data(self, **kwargs): context = super(ThemeConfigView, self).get_context_data(**kwargs) shop = get_shop(self.request) context.update(cached_load("SHUUP_XTHEME_ADMIN_THEME_CONTEXT")(shop)) return context
def dispatch(self, request, *args, **kwargs): theme = get_theme_by_identifier(kwargs["theme_identifier"], shop=get_shop(self.request)) self.template_name = theme.guide_template return super(ThemeGuideTemplateView, self).dispatch(request, *args, **kwargs)
def save_form(self, form): super(ThemeConfigDetailView, self).save_form(form) cache.bump_version(get_theme_cache_key(get_shop(self.request)))
def get_object(self, queryset=None): return ThemeSettings.objects.get_or_create( theme_identifier=self.kwargs["theme_identifier"], shop=get_shop(self.request))[0]
def get_form_kwargs(self): kwargs = super(ScriptEditView, self).get_form_kwargs() kwargs["shop"] = get_shop(self.request) return kwargs
def get_admin_shop(context): return get_shop(context["request"])
def get_form_kwargs(self): kwargs = super().get_form_kwargs() kwargs["instance"] = AdminThemeSettings.objects.get_or_create( shop=get_shop(self.request))[0] return kwargs
def __init__(self, **kwargs): # TODO: Revise this. Since this is shop product form then maybe we should have shop available insted of request self.request = kwargs.pop("request", None) super(ShopProductForm, self).__init__(**kwargs) payment_methods_qs = PaymentMethod.objects.all() shipping_methods_qs = ShippingMethod.objects.all() if self.request: shop = self.request.shop payment_methods_qs = payment_methods_qs.filter(shop=shop) shipping_methods_qs = ShippingMethod.objects.filter(shop=shop) self.fields["payment_methods"].queryset = payment_methods_qs self.fields["shipping_methods"].queryset = shipping_methods_qs self.fields["default_price_value"].required = True initial_categories = [] initial_suppliers = [] if self.instance.pk: initial_categories = self.instance.categories.all() initial_suppliers = self.instance.suppliers.all() elif not settings.SHUUP_ENABLE_MULTIPLE_SUPPLIERS: supplier = Supplier.objects.first() initial_suppliers = ([supplier] if supplier else []) if settings.SHUUP_ADMIN_LOAD_SELECT_OBJECTS_ASYNC.get("suppliers"): self.fields["suppliers"] = Select2ModelMultipleField( initial=initial_suppliers, model=Supplier, widget=QuickAddSupplierMultiSelect( initial=initial_suppliers, attrs={"data-search-mode": "enabled"} ), required=False ) else: self.fields["suppliers"].widget = QuickAddSupplierMultiSelect(initial=initial_suppliers) if settings.SHUUP_ADMIN_LOAD_SELECT_OBJECTS_ASYNC.get("categories"): self.fields["primary_category"] = Select2ModelField( initial=(self.instance.primary_category if self.instance.pk else None), model=Category, widget=QuickAddCategorySelect( editable_model="shuup.Category", initial=(self.instance.primary_category if self.instance.pk else None), attrs={"data-placeholder": ugettext("Select a category")} ), required=False ) self.fields["categories"] = Select2ModelMultipleField( initial=initial_categories, model=Category, widget=QuickAddCategoryMultiSelect(initial=initial_categories), required=False ) else: categories_choices = [ (cat.pk, cat.get_hierarchy()) for cat in Category.objects.all_except_deleted(shop=get_shop(self.request)) ] self.fields["primary_category"].widget = QuickAddCategorySelect( initial=( self.instance.primary_category if self.instance.pk and self.instance.primary_category else None ), editable_model="shuup.Category", attrs={"data-placeholder": ugettext("Select a category")}, choices=categories_choices, model=NoModel() ) self.fields["categories"].widget = QuickAddCategoryMultiSelect( initial=initial_categories, choices=categories_choices, model=NoModel() )
def get_queryset(self): shop = get_shop(self.request) return self.model.objects.filter( target__shop=shop).order_by("-created_on")
def save(self, commit=True): if not hasattr(self.instance, "shop") or not self.instance.shop: self.instance.shop = get_shop(self.request) return super(PageForm, self).save(commit)
def get_queryset(self): return self.model.objects.filter(shop=get_shop(self.request))
def check_contact_permission(request, contact): shop = get_shop(request) if request_limited(request) and not contact.in_shop(shop): raise PermissionDenied()
def get_queryset(self): return super(ScriptEditView, self).get_queryset().filter(shop=get_shop(self.request))
def get_queryset(self): if getattr(self.request.user, "is_superuser", False): return Supplier.objects.all() return Supplier.objects.filter( Q(shops=get_shop(self.request)) | Q(shops__isnull=True))
def get_queryset(self): return super(PageListView, self).get_queryset().for_shop( get_shop(self.request)).filter(deleted=False)
def get_queryset(self): return Category.objects.all_except_deleted(shop=get_shop(self.request))
def __init__(self, request, object=None): super(SalesRangesFormPart, self).__init__(request, object) self.shops = [get_shop(request)]
def get_object(self): return GDPRSettings.get_for_shop(get_shop(self.request))
def get_queryset(self): return GDPRSettings.objects.filter(shop=get_shop(self.request))
def get_queryset(self): return TaskType.objects.filter(shop=get_shop(self.request))
def get_queryset(self): return Task.objects.for_shop(get_shop(self.request))
def get_queryset(self): return Discount.objects.active(get_shop(self.request))
def get_queryset(self): return VendorReview.objects.filter(shop=get_shop(self.request))
def validate_shop_for_order(request, order): if get_shop(request) != order.shop: raise Problem(_("Current shop does not match with order shop. Please change currently active shop."))
def get_queryset(self): return Manufacturer.objects.filter(Q(shops=get_shop(self.request)) | Q(shops__isnull=True))
def get_queryset(self): return super(OrderListView, self).get_queryset().exclude( deleted=True).filter(shop=get_shop(self.request))