def test_utils(self): """ Miscellanous tests for the ``mezzanine.utils`` package. """ self.assertRaises(ImportError, import_dotted_path, "mezzanine") self.assertRaises(ImportError, import_dotted_path, "mezzanine.NO") self.assertRaises(ImportError, import_dotted_path, "mezzanine.core.NO") try: import_dotted_path("mezzanine.core") except ImportError: self.fail("mezzanine.utils.imports.import_dotted_path" 'could not import "mezzanine.core"')
def recalculate_cart(request): """ Updates an existing discount code, shipping, and tax when the cart is modified. """ from cartridge.shop import checkout from cartridge.shop.forms import DiscountForm from cartridge.shop.models import Cart # Rebind the cart to request since it's been modified. if request.session.get('cart') != request.cart.pk: request.session['cart'] = request.cart.pk request.cart = Cart.objects.from_request(request) discount_code = request.session.get("discount_code", "") if discount_code: # Clear out any previously defined discount code # session vars. names = ("free_shipping", "discount_code", "discount_total") clear_session(request, *names) discount_form = DiscountForm(request, {"discount_code": discount_code}) if discount_form.is_valid(): discount_form.set_discount() handler = lambda s: import_dotted_path(s) if s else lambda *args: None billship_handler = handler(settings.SHOP_HANDLER_BILLING_SHIPPING) tax_handler = handler(settings.SHOP_HANDLER_TAX) try: if request.session["order"]["step"] >= checkout.CHECKOUT_STEP_FIRST: billship_handler(request, None) tax_handler(request, None) except (checkout.CheckoutError, ValueError, KeyError): pass
def build_modelgraph(docs_path, package_name="mezzanine"): """ Creates a diagram of all the models for mezzanine and the given package name, generates a smaller version and add it to the docs directory for use in model-graph.rst """ to_path = os.path.join(docs_path, "img", "graph.png") build_path = os.path.join(docs_path, "build", "_images") resized_path = os.path.join(os.path.dirname(to_path), "graph-small.png") settings = import_dotted_path(package_name + ".project_template.settings") apps = [ a.rsplit(".")[1] for a in settings.INSTALLED_APPS if a.startswith("mezzanine.") or a.startswith(package_name + ".") ] try: from django_extensions.management.commands import graph_models except ImportError: warn("Couldn't build model_graph, django_extensions not installed") else: options = {"inheritance": True, "outputfile": "graph.png", "layout": "dot"} try: graph_models.Command().execute(*apps, **options) except Exception, e: warn("Couldn't build model_graph, graph_models failed on: %s" % e) else:
def urls(self): urls = [ url("", super(LazyAdminSite, self).urls), ] # Filebrowser admin media library. fb_name = getattr(settings, "PACKAGE_NAME_FILEBROWSER", "") if fb_name in settings.INSTALLED_APPS: try: fb_urls = import_dotted_path("%s.sites.site" % fb_name).urls except ImportError: fb_urls = "%s.urls" % fb_name urls = [ # This gives the media library a root URL (which filebrowser # doesn't provide), so that we can target it in the # ADMIN_MENU_ORDER setting, allowing each view to correctly # highlight its left-hand admin nav item. url("^media-library/$", lambda r: redirect("fb_browse"), name="media-library"), url("^media-library/", include(fb_urls)), ] + urls # Give the urlpattern for the user password change view an # actual name, so that it can be reversed with multiple # languages are supported in the admin. User = get_user_model() for admin in self._registry.values(): user_change_password = getattr(admin, "user_change_password", None) if user_change_password: bits = (User._meta.app_label, User._meta.object_name.lower()) urls = [ url("^%s/%s/(\d+)/password/$" % bits, self.admin_view(user_change_password), name="user_change_password"), ] + urls break return urls
def comment(request, template="generic/comments.html", extra_context=None): """ Handle a ``ThreadedCommentForm`` submission and redirect back to its related object. """ response = initial_validation(request, "comment") if isinstance(response, HttpResponse): return response obj, post_data = response form_class = import_dotted_path(settings.COMMENT_FORM_CLASS) form = form_class(request, obj, post_data) if form.is_valid(): url = obj.get_absolute_url() if is_spam(request, form, url): return redirect(url) comment = form.save(request) response = redirect(add_cache_bypass(comment.get_absolute_url())) # Store commenter's details in a cookie for 90 days. for field in ThreadedCommentForm.cookie_fields: cookie_name = ThreadedCommentForm.cookie_prefix + field cookie_value = post_data.get(field, "") set_cookie(response, cookie_name, cookie_value) return response elif request.is_ajax() and form.errors: return HttpResponse(dumps({"errors": form.errors})) # Show errors with stand-alone comment form. context = {"obj": obj, "posted_comment_form": form} context.update(extra_context or {}) return TemplateResponse(request, template, context)
def build_modelgraph(docs_path, package_name="mezzanine"): """ Creates a diagram of all the models for mezzanine and the given package name, generates a smaller version and add it to the docs directory for use in model-graph.rst """ project_path = os.path.join(docs_path, "..", package_name, "project_template") settings = import_dotted_path(package_name + ".project_template.settings") apps = [a.rsplit(".")[1] for a in settings.INSTALLED_APPS if a.startswith("mezzanine.") or a.startswith(package_name + ".")] os.chdir(project_path) cmd = "python manage.py graph_models -e -o graph.png %s" % " ".join(apps) os.system(cmd) to_path = os.path.join(docs_path, "img", "graph.png") move(os.path.join(project_path, "graph.png"), to_path) build_path = os.path.join(docs_path, "build", "_images") if not os.path.exists(build_path): os.makedirs(build_path) copyfile(to_path, os.path.join(build_path, "graph.png")) image = Image.open(to_path) image.width = 800 image.height = image.size[1] * 800 / image.size[0] resized_path = os.path.join(os.path.dirname(to_path), "graph-small.png") image.save(resized_path, "PNG", quality=100)
def urls(self): from django.conf import settings urls = patterns("", ("", super(LazyAdminSite, self).urls)) # Filebrowser admin media library. fb_name = getattr(settings, "PACKAGE_NAME_FILEBROWSER", "") if fb_name in settings.INSTALLED_APPS: try: fb_urls = import_dotted_path("%s.sites.site" % fb_name).urls except ImportError: fb_urls = "%s.urls" % fb_name urls = patterns("", ("^media-library/", include(fb_urls))) + urls # Give the urlpatterm for the user password change view an # actual name, so that it can be reversed with multiple # languages are supported in the admin. User = get_user_model() for admin in self._registry.values(): user_change_password = getattr(admin, "user_change_password", None) if user_change_password: bits = (User._meta.app_label, User._meta.object_name.lower()) urls = ( patterns( "", url( "^%s/%s/(\d+)/password/$" % bits, self.admin_view(user_change_password), name="user_change_password", ), ) + urls ) break return urls
def test_default_handler_exists(self): """ Ensure that the handler specified in default settings exists as well as the default setting itself. """ settings.use_editable() handler = lambda s: import_dotted_path(s) if s else lambda *args: None self.assertTrue(handler(settings.SHOP_HANDLER_TAX) is not None)
def richtext_filters(content): """ Takes a value edited via the WYSIWYG editor, and passes it through each of the functions specified by the RICHTEXT_FILTERS setting. """ for filter_name in settings.RICHTEXT_FILTERS: filter_func = import_dotted_path(filter_name) content = filter_func(content) return content
def richtext_filter(content): """ This template filter takes a string value and passes it through the function specified by the RICHTEXT_FILTER setting. """ if settings.RICHTEXT_FILTER: func = import_dotted_path(settings.RICHTEXT_FILTER) else: func = lambda s: s return func(content)
def upload_to(field_path, default): """ Used as the ``upload_to`` arg for file fields - allows for custom handlers to be implemented on a per field basis defined by the ``UPLOAD_TO_HANDLERS`` setting. """ for k, v in settings.UPLOAD_TO_HANDLERS.items(): if k.lower() == field_path.lower(): return import_dotted_path(v) return default
def widget_extra_permission(user): from mezzanine.conf import settings try: perm = import_dotted_path(settings.WIDGET_PERMISSION) return perm(user) except AttributeError: return False except ImportError: raise ImproperlyConfigured(_("Could not import the value of ", "settings.WIDGET_PERMISSION: %s" % settings.WIDGET_PERMISSION))
def is_spam(request, form, url): """ Main entry point for spam handling - called from the comment view and page processor for ``mezzanine.forms``, to check if posted content is spam. Spam filters are configured via the ``SPAM_FILTERS`` setting. """ for spam_filter_path in settings.SPAM_FILTERS: spam_filter = import_dotted_path(spam_filter_path) if spam_filter(request, form, url): return True
def save(self, *args, **kwargs): keywords = [] if not self.keywords_string and getattr(settings, "AUTO_TAG", False): func_name = getattr(settings, "AUTO_TAG_FUNCTION", "drum.links.utils.auto_tag") keywords = import_dotted_path(func_name)(self) super(Link, self).save(*args, **kwargs) if keywords: lookup = reduce(ior, [Q(title__iexact=k) for k in keywords]) for keyword in Keyword.objects.filter(lookup): self.keywords.add(AssignedKeyword(keyword=keyword), bulk=True)
def get_profile_form(): """ Returns the profile form defined by ``ACCOUNTS_PROFILE_FORM_CLASS``. """ from mezzanine.conf import settings try: return import_dotted_path(settings.ACCOUNTS_PROFILE_FORM_CLASS) except ImportError: raise ImproperlyConfigured("Value for ACCOUNTS_PROFILE_FORM_CLASS " "could not be imported: %s" % settings.ACCOUNTS_PROFILE_FORM_CLASS)
def formfield(self, **kwargs): """ Apply the widget class defined by the ``HTML_WIDGET_CLASS`` setting. """ try: widget_class = import_dotted_path(settings.HTML_WIDGET_CLASS) except ImportError: raise ImproperlyConfigured(_("Could not import the value of " "settings.HTML_WIDGET_CLASS: %s" % settings.HTML_WIDGET_CLASS)) kwargs["widget"] = widget_class() formfield = super(HtmlField, self).formfield(**kwargs) return formfield
def urls(self): from django.conf import settings urls = patterns("", ("", super(LazyAdminSite, self).urls),) # Filebrowser admin media library. fb_name = getattr(settings, "PACKAGE_NAME_FILEBROWSER", "") if fb_name in settings.INSTALLED_APPS: try: fb_urls = import_dotted_path("%s.sites.site" % fb_name).urls except ImportError: fb_urls = "%s.urls" % fb_name urls += patterns("", ("^media-library/", include(fb_urls)),) return urls
def build_modelgraph(docs_path, package_name="mezzanine"): """ Creates a diagram of all the models for mezzanine and the given package name, generates a smaller version and add it to the docs directory for use in model-graph.rst """ to_path = os.path.join(docs_path, "img", "graph.png") build_path = os.path.join(docs_path, "build", "_images") resized_path = os.path.join(os.path.dirname(to_path), "graph-small.png") settings = import_dotted_path(package_name + ".project_template.project_name.settings") apps = [ a.rsplit(".")[1] for a in settings.INSTALLED_APPS if a.startswith("mezzanine.") or a.startswith(package_name + ".") ] try: from django_extensions.management.commands import graph_models except ImportError: warn("Couldn't build model_graph, django_extensions not installed") else: options = {"inheritance": True, "outputfile": "graph.png", "layout": "dot"} try: graph_models.Command().execute(*apps, **options) except Exception as e: warn("Couldn't build model_graph, graph_models failed on: %s" % e) else: try: move("graph.png", to_path) except OSError as e: warn("Couldn't build model_graph, move failed on: %s" % e) # docs/img/graph.png should exist in the repo - move it to the build path. try: if not os.path.exists(build_path): os.makedirs(build_path) copyfile(to_path, os.path.join(build_path, "graph.png")) except OSError as e: warn("Couldn't build model_graph, copy to build failed on: %s" % e) try: from PIL import Image image = Image.open(to_path) image.width = 800 image.height = image.size[1] * 800 // image.size[0] image.save(resized_path, "PNG", quality=100) except Exception as e: warn("Couldn't build model_graph, resize failed on: %s" % e) return # Copy the dashboard screenshot to the build dir too. This doesn't # really belong anywhere, so we do it here since this is the only # spot we deal with doc images. d = "dashboard.png" copyfile(os.path.join(docs_path, "img", d), os.path.join(build_path, d))
def urls(self): urls = [url(r"", super(LazyAdminSite, self).urls)] # Filebrowser admin media library. fb_name = getattr(settings, "PACKAGE_NAME_FILEBROWSER", "") if fb_name in settings.INSTALLED_APPS: try: fb_urls = import_dotted_path("%s.sites.site" % fb_name).urls except ImportError: fb_urls = "%s.urls" % fb_name urls = [ # This gives the media library a root URL (which filebrowser # doesn't provide), so that we can target it in the # ADMIN_MENU_ORDER setting, allowing each view to correctly # highlight its left-hand admin nav item. url(r"^media-library/$", lambda r: redirect("fb_browse"), name="media-library"), url(r"^media-library/", include(fb_urls)), ] + urls # Give the urlpattern for the user password change view an # actual name, so that it can be reversed with multiple # languages are supported in the admin. User = get_user_model() for admin in self._registry.values(): user_change_password = getattr(admin, "user_change_password", None) if user_change_password: bits = (User._meta.app_label, User._meta.object_name.lower()) urls = [ url(r"^%s/%s/(\d+)/password/$" % bits, self.admin_view(user_change_password), name="user_change_password"), ] + urls break # Misc Mezzanine urlpatterns that should reside under /admin/ url, # specifically for compatibility with SSLRedirectMiddleware. from mezzanine.core.views import displayable_links_js, static_proxy from mezzanine.generic.views import admin_keywords_submit urls += [ url(r"^admin_keywords_submit/$", admin_keywords_submit, name="admin_keywords_submit"), url(r"^asset_proxy/$", static_proxy, name="static_proxy"), url(r"^displayable_links.js$", displayable_links_js, name="displayable_links_js"), ] if "mezzanine.pages" in settings.INSTALLED_APPS: from mezzanine.pages.views import admin_page_ordering urls.append(url(r"^admin_page_ordering/$", admin_page_ordering, name="admin_page_ordering")) return urls
def comment_filter(comment_text): """ Passed comment text to be rendered through the function defined by the ``COMMENT_FILTER`` setting. If no function is defined (the default), Django's ``linebreaksbr`` and ``urlize`` filters are used. """ filter_func = settings.COMMENT_FILTER if not filter_func: def filter_func(s): return linebreaksbr(urlize(s, autoescape=True), autoescape=True) elif not callable(filter_func): filter_func = import_dotted_path(filter_func) return filter_func(comment_text)
def comments_for(context, obj): """ Provides a generic context variable name for the object that comments are being rendered for. """ form_class = import_dotted_path(settings.COMMENT_FORM_CLASS) form = form_class(context["request"], obj) context_form = context.get("posted_comment_form", form) return { 'posted_comment_form': context_form if context_form.target_object == obj else form, 'unposted_comment_form': form, 'comment_url': reverse("comment"), 'object_for_comments': obj, }
def formfield(self, **kwargs): """ Apply the widget class defined by the ``RICHTEXT_WIDGET_CLASS`` setting. """ from mezzanine.conf import settings try: widget_class = import_dotted_path(settings.RICHTEXT_WIDGET_CLASS) except ImportError: raise ImproperlyConfigured(_("Could not import the value of " "settings.RICHTEXT_WIDGET_CLASS: %s" % settings.RICHTEXT_WIDGET_CLASS)) kwargs["widget"] = widget_class() formfield = super(RichTextField, self).formfield(**kwargs) return formfield
def import_field(field_classpath): """ Imports a field by its dotted class path, prepending "django.db.models" to raw class names and raising an exception if the import fails. """ if '.' in field_classpath: fully_qualified = field_classpath else: fully_qualified = "django.db.models.%s" % field_classpath try: return import_dotted_path(fully_qualified) except ImportError: raise ImproperlyConfigured("The EXTRA_MODEL_FIELDS setting contains " "the field '%s' which could not be " "imported." % field_classpath)
def comments_for(context, obj): """ Provides a generic context variable name for the object that comments are being rendered for. """ form_class = import_dotted_path(settings.COMMENT_FORM_CLASS) form = form_class(context["request"], obj) try: context["posted_comment_form"] except KeyError: context["posted_comment_form"] = form context["unposted_comment_form"] = form context["comment_url"] = reverse("comment") context["object_for_comments"] = obj return context
def test_default_handler_exists(self): ''' Ensure that the handler specified in default settings exists as well as the default setting itself. ''' from mezzanine.utils.importing import import_dotted_path settings.use_editable() assert hasattr(settings, 'SHOP_HANDLER_TAX'), \ 'Setting SHOP_HANDLER_TAX not found.' handler = lambda s: import_dotted_path(s) if s else lambda *args: None tax_handler = handler(settings.SHOP_HANDLER_TAX) assert tax_handler is not None, \ 'Could not find default SHOP_HANDLER_TAX function.'
def urls(self): from django.conf import settings urls = patterns("", ("", super(LazyAdminSite, self).urls),) # Filebrowser admin media library. fb_name = getattr(settings, "PACKAGE_NAME_FILEBROWSER", "") if fb_name in settings.INSTALLED_APPS: try: fb_urls = import_dotted_path("%s.sites.site" % fb_name).urls except ImportError: fb_urls = "%s.urls" % fb_name urls = patterns("", ("^media-library/", include(fb_urls)), url("^auth/user/(\d+)/password/$", lambda request, user_id: self.password_change(request), name="password_change"), ) + urls return urls
def test_richtext_widget(self): """ Test that the RichTextField gets its widget type correctly from settings, and is able to be overridden in a form's Meta. """ class RichTextModel(models.Model): text_default = RichTextField() text_overridden = RichTextField() form_class = modelform_factory(RichTextModel, widgets={"text_overridden": Textarea}) form = form_class() richtext_widget = import_dotted_path(settings.RICHTEXT_WIDGET_CLASS) self.assertIsInstance(form.fields["text_default"].widget, richtext_widget) self.assertIsInstance(form.fields["text_overridden"].widget, Textarea)
def formfield(self, **kwargs): """ Apply the widget class defined by the ``RICHTEXT_WIDGET_CLASS`` setting. """ if "widget" not in kwargs: from mezzanine.conf import settings richtext_widget_path = settings.RICHTEXT_WIDGET_CLASS try: widget_class = import_dotted_path(richtext_widget_path) except ImportError: raise ImproperlyConfigured(_("Could not import the value of " "settings.RICHTEXT_WIDGET_CLASS: " "%s" % richtext_widget_path)) kwargs["widget"] = widget_class() kwargs.setdefault("required", False) formfield = super(RichTextField, self).formfield(**kwargs) return formfield
def richtext_filters(content): """ Takes a value edited via the WYSIWYG editor, and passes it through each of the functions specified by the RICHTEXT_FILTERS setting. """ filter_names = settings.RICHTEXT_FILTERS if not filter_names: try: filter_names = [settings.RICHTEXT_FILTER] except AttributeError: pass else: from warnings import warn warn("The `RICHTEXT_FILTER` setting is deprecated in favor of " "the new plural setting `RICHTEXT_FILTERS`.") for filter_name in filter_names: filter_func = import_dotted_path(filter_name) content = filter_func(content) return content
def installed(cls): """ Used in ``mezzanine.pages.views.page`` to ensure ``PageMiddleware`` or a subclass has been installed. We cache the result on the ``PageMiddleware._installed`` to only run this once. Short path is to just check for the dotted path to ``PageMiddleware`` in ``MIDDLEWARE_CLASSES`` - if not found, we need to load each middleware class to match a subclass. """ try: return cls._installed except AttributeError: name = "mezzanine.pages.middleware.PageMiddleware" installed = name in settings.MIDDLEWARE_CLASSES if not installed: for name in settings.MIDDLEWARE_CLASSES: if issubclass(import_dotted_path(name), cls): installed = True break setattr(cls, "_installed", installed) return installed
def validate(self, value, instance): choices = [str(choice[0]) for choice in self.choices] if set(value) - set(choices): error = self.error_messages["invalid_choice"] % {'value': value} raise ValidationError(error) def value_to_string(self, obj): value = self._get_val_from_obj(obj) return ",".join(value) # Define a ``FileField`` that maps to filebrowser's ``FileBrowseField`` # if available, falling back to Django's ``FileField`` otherwise. try: FileBrowseField = import_dotted_path("%s.fields.FileBrowseField" % settings.PACKAGE_NAME_FILEBROWSER) except ImportError: class FileField(models.FileField): def __init__(self, *args, **kwargs): for fb_arg in ("format", "extensions"): kwargs.pop(fb_arg, None) super(FileField, self).__init__(*args, **kwargs) else: class FileField(FileBrowseField): def __init__(self, *args, **kwargs): kwargs.setdefault("directory", kwargs.pop("upload_to", None)) kwargs.setdefault("max_length", 255) super(FileField, self).__init__(*args, **kwargs)
def slugify(s): """ Loads the callable defined by the ``SLUGIFY`` setting, which defaults to the ``slugify_unicode`` function. """ return import_dotted_path(settings.SLUGIFY)(s)
HIDDEN: forms.HiddenInput, } # Some helper groupings of field types. CHOICES = (CHECKBOX, SELECT, RADIO_MULTIPLE) DATES = (DATE, DATE_TIME, DOB) MULTIPLE = (CHECKBOX_MULTIPLE, SELECT_MULTIPLE) # HTML5 Widgets if settings.FORMS_USE_HTML5: html5_field = lambda name, base: type("", (base, ), {"input_type": name}) WIDGETS.update({ DATE: html5_field("date", forms.DateInput), DATE_TIME: html5_field("datetime", forms.DateTimeInput), DOB: html5_field("date", forms.DateInput), EMAIL: html5_field("email", forms.TextInput), NUMBER: html5_field("number", forms.TextInput), URL: html5_field("url", forms.TextInput), }) # Allow extra fields types to be defined via the FORMS_EXTRA_FIELDS # setting, which should contain a sequence of three-item sequences, # each containing the ID, dotted import path for the field class, # and field name, for each custom field type. for field_id, field_path, field_name in settings.FORMS_EXTRA_FIELDS: if field_id in CLASSES: err = "ID %s for field %s in FORMS_EXTRA_FIELDS already exists" raise ImproperlyConfigured(err % (field_id, field_name)) CLASSES[field_id] = import_dotted_path(field_path) NAMES += ((field_id, _(field_name)), )
from filebrowser_safe.templatetags.fb_tags import query_helper from filebrowser_safe.base import FileObject from filebrowser_safe.decorators import flash_login_required from mezzanine.utils.importing import import_dotted_path # Add some required methods to FileSystemStorage storage_class_name = django_settings.DEFAULT_FILE_STORAGE.split(".")[-1] mixin_class_name = "filebrowser_safe.storage.%sMixin" % storage_class_name # Workaround for django-s3-folder-storage if django_settings.DEFAULT_FILE_STORAGE == 's3_folder_storage.s3.DefaultStorage': mixin_class_name = 'filebrowser_safe.storage.S3BotoStorageMixin' try: mixin_class = import_dotted_path(mixin_class_name) storage_class = import_dotted_path(django_settings.DEFAULT_FILE_STORAGE) except ImportError: pass else: if mixin_class not in storage_class.__bases__: storage_class.__bases__ += (mixin_class, ) # Precompile regular expressions filter_re = [] for exp in EXCLUDE: filter_re.append(re.compile(exp)) for k, v in VERSIONS.items(): exp = (r'_%s.(%s)') % (k, '|'.join(EXTENSION_LIST)) filter_re.append(re.compile(exp))
def urls(self): urls = [] # Filebrowser admin media library. fb_name = getattr(settings, "PACKAGE_NAME_FILEBROWSER", "") if fb_name in settings.INSTALLED_APPS: try: fb_urls = import_dotted_path("%s.sites.site" % fb_name).urls except ImportError: fb_urls = "%s.urls" % fb_name urls += [ # This gives the media library a root URL (which filebrowser # doesn't provide), so that we can target it in the # ADMIN_MENU_ORDER setting, allowing each view to correctly # highlight its left-hand admin nav item. re_path( r"^media-library/$", lambda r: redirect("fb_browse"), name="media-library", ), re_path(r"^media-library/", include(fb_urls)), ] # Give the urlpattern for the user password change view an # actual name, so that it can be reversed with multiple # languages are supported in the admin. User = get_user_model() for admin in self._registry.values(): user_change_password = getattr(admin, "user_change_password", None) if user_change_password: bits = (User._meta.app_label, User._meta.object_name.lower()) urls += [ re_path( r"^%s/%s/(\d+)/password/$" % bits, self.admin_view(user_change_password), name="user_change_password", ), ] break # Misc Mezzanine urlpatterns that should reside under /admin/ url, # specifically for compatibility with SSLRedirectMiddleware. from mezzanine.core.views import displayable_links_js, static_proxy from mezzanine.generic.views import admin_keywords_submit urls += [ re_path( r"^admin_keywords_submit/$", admin_keywords_submit, name="admin_keywords_submit", ), re_path(r"^asset_proxy/$", static_proxy, name="static_proxy"), re_path( r"^displayable_links.js$", displayable_links_js, name="displayable_links_js", ), ] if "mezzanine.pages" in settings.INSTALLED_APPS: from mezzanine.pages.views import admin_page_ordering urls += [ re_path( r"^admin_page_ordering/$", admin_page_ordering, name="admin_page_ordering", ) ] return urls + [re_path(r"", super().urls)]
from mezzanine.utils.urls import next_url try: from xhtml2pdf import pisa except (ImportError, SyntaxError): pisa = None from cartridge.shop import checkout from cartridge.shop.forms import (AddProductForm, CartItemFormSet, DiscountForm, OrderForm) from cartridge.shop.models import Product, ProductVariation, Order from cartridge.shop.models import DiscountCode from cartridge.shop.utils import recalculate_cart, sign # Set up checkout handlers. handler = lambda s: import_dotted_path(s) if s else lambda *args: None billship_handler = handler(settings.SHOP_HANDLER_BILLING_SHIPPING) tax_handler = handler(settings.SHOP_HANDLER_TAX) payment_handler = handler(settings.SHOP_HANDLER_PAYMENT) order_handler = handler(settings.SHOP_HANDLER_ORDER) def product(request, slug, template="shop/product.html", form_class=AddProductForm): """ Display a product - convert the product variations to JSON as well as handling adding the product to either the cart or the wishlist. """ published_products = Product.objects.published(for_user=request.user)
def checkout_steps(request, form_class=OrderForm): """ Display the order form and handle processing of each step. """ # Do the authentication check here rather than using standard # login_required decorator. This means we can check for a custom # LOGIN_URL and fall back to our own login view. authenticated = request.user.is_authenticated() if settings.SHOP_CHECKOUT_ACCOUNT_REQUIRED and not authenticated: url = "%s?next=%s" % (settings.LOGIN_URL, reverse("shop_checkout")) return redirect(url) try: settings.SHOP_CHECKOUT_FORM_CLASS except AttributeError: pass else: from warnings import warn warn("The SHOP_CHECKOUT_FORM_CLASS setting is deprecated - please " "define your own urlpattern for the checkout_steps view, " "passing in your own form_class argument.") form_class = import_dotted_path(settings.SHOP_CHECKOUT_FORM_CLASS) initial = checkout.initial_order_data(request, form_class) step = int( request.POST.get("step", None) or initial.get("step", None) or checkout.CHECKOUT_STEP_FIRST) form = form_class(request, step, initial=initial) data = request.POST checkout_errors = [] if request.POST.get("back") is not None: # Back button in the form was pressed - load the order form # for the previous step and maintain the field values entered. step -= 1 form = form_class(request, step, initial=initial) elif request.method == "POST" and request.cart.has_items(): form = form_class(request, step, initial=initial, data=data) if form.is_valid(): # Copy the current form fields to the session so that # they're maintained if the customer leaves the checkout # process, but remove sensitive fields from the session # such as the credit card fields so that they're never # stored anywhere. request.session["order"] = dict(form.cleaned_data) sensitive_card_fields = ("card_number", "card_expiry_month", "card_expiry_year", "card_ccv") for field in sensitive_card_fields: if field in request.session["order"]: del request.session["order"][field] # FIRST CHECKOUT STEP - handle shipping and discount code. if step == checkout.CHECKOUT_STEP_FIRST: # Discount should be set before shipping, to allow # for free shipping to be first set by a discount # code. form.set_discount() try: billship_handler(request, form) tax_handler(request, form) except checkout.CheckoutError as e: checkout_errors.append(e) # FINAL CHECKOUT STEP - handle payment and process order. if step == checkout.CHECKOUT_STEP_LAST and not checkout_errors: # Create and save the initial order object so that # the payment handler has access to all of the order # fields. If there is a payment error then delete the # order, otherwise remove the cart items from stock # and send the order receipt email. order = form.save(commit=False) order.setup(request) # Try payment. try: transaction_id = payment_handler(request, form, order) except checkout.CheckoutError as e: # Error in payment handler. order.delete() checkout_errors.append(e) if settings.SHOP_CHECKOUT_STEPS_CONFIRMATION: step -= 1 else: # Finalize order - ``order.complete()`` performs # final cleanup of session and cart. # ``order_handler()`` can be defined by the # developer to implement custom order processing. # Then send the order email to the customer. order.transaction_id = transaction_id order.complete(request) order_handler(request, form, order) checkout.send_order_email(request, order) # Set the cookie for remembering address details # if the "remember" checkbox was checked. response = redirect("shop_complete") if form.cleaned_data.get("remember"): remembered = "%s:%s" % (sign(order.key), order.key) set_cookie(response, "remember", remembered, secure=request.is_secure()) else: response.delete_cookie("remember") return response # If any checkout errors, assign them to a new form and # re-run is_valid. If valid, then set form to the next step. form = form_class(request, step, initial=initial, data=data, errors=checkout_errors) if form.is_valid(): step += 1 form = form_class(request, step, initial=initial) # Update the step so that we don't rely on POST data to take us back to # the same point in the checkout process. try: request.session["order"]["step"] = step request.session.modified = True except KeyError: pass step_vars = checkout.CHECKOUT_STEPS[step - 1] template = "shop/%s.html" % step_vars["template"] context = { "CHECKOUT_STEP_FIRST": step == checkout.CHECKOUT_STEP_FIRST, "CHECKOUT_STEP_LAST": step == checkout.CHECKOUT_STEP_LAST, "step_title": step_vars["title"], "step_url": step_vars["url"], "steps": checkout.CHECKOUT_STEPS, "step": step, "form": form } return render(request, template, context)
from django.utils.translation import ugettext_lazy as _ from mezzanine.conf import settings from mezzanine.core.fields import FileField from mezzanine.core.models import Orderable, RichText from mezzanine.pages.models import Page from mezzanine.utils.importing import import_dotted_path # Set the directory where gallery images are uploaded to, # either MEDIA_ROOT + 'galleries', or filebrowser's upload # directory if being used. GALLERIES_UPLOAD_DIR = "galleries" if settings.PACKAGE_NAME_FILEBROWSER in settings.INSTALLED_APPS: fb_settings = "%s.settings" % settings.PACKAGE_NAME_FILEBROWSER try: GALLERIES_UPLOAD_DIR = import_dotted_path(fb_settings).DIRECTORY except ImportError: pass class Gallery(Page, RichText): """ Page bucket for gallery photos. """ zip_import = models.FileField( upload_to="galleries", blank=True, verbose_name=_("Zip import"), help_text=_("Upload a zip file containing images, and " "they'll be imported into this gallery."))
from django.core.files.base import ContentFile from django.core.files.storage import default_storage from django.db import models from django.utils.translation import ugettext_lazy as _ from mezzanine.core.fields import RichTextField, FileField from mezzanine.core.models import SiteRelated, Orderable from mezzanine.pages.models import Page from mezzanine.utils.importing import import_dotted_path from mezzanine.utils.models import upload_to EVENTS_UPLOAD_DIR = "galleries" if settings.PACKAGE_NAME_FILEBROWSER in settings.INSTALLED_APPS: fb_settings = "%s.settings" % settings.PACKAGE_NAME_FILEBROWSER try: EVENTS_UPLOAD_DIR = import_dotted_path(fb_settings).DIRECTORY except ImportError: pass class Event(Page): content = RichTextField(blank=True) start = models.DateTimeField() end = models.DateTimeField(blank=True, null=True) type = models.ForeignKey('calendar.EventType', blank=True, null=True) zip_import = models.FileField(verbose_name=_("Zip import"), blank=True, null=True, upload_to=upload_to("calendar.Event.zip_import", "events"), help_text=_("Upload a zip file containing images, and " "they'll be imported into this event.")) class Meta: