예제 #1
0
def test_order_refunds_with_other_lines(rf, admin_user):
    shop = get_default_shop()
    supplier = get_default_supplier()
    supplier.shops.add(shop)

    product = create_product("sku", shop=shop, default_price=10)
    shop_product = product.get_shop_instance(shop=shop)
    shop_product.suppliers.set([supplier])

    order = create_empty_order(shop=shop)
    order.full_clean()
    order.save()

    add_product_to_order(order, supplier, product, 4, 5)

    # Lines without quantity shouldn't affect refunds
    other_line = OrderLine(
        order=order, type=OrderLineType.OTHER, text="This random line for textual information", quantity=0)
    other_line.save()
    order.lines.add(other_line)

    # Lines with quantity again should be able to be refunded normally.
    other_line_with_quantity = OrderLine(
        order=order, type=OrderLineType.OTHER, text="Special service 100$/h", quantity=1, base_unit_price_value=100)
    other_line_with_quantity.save()
    order.lines.add(other_line_with_quantity)

    assert other_line_with_quantity.max_refundable_quantity == 1
    assert other_line_with_quantity.max_refundable_amount.value == 100

    order.cache_prices()
    order.create_payment(order.taxful_total_price)
    assert order.is_paid()
    assert order.taxful_total_price_value == 120 # 100 + 4 * 20

    def get_refund_view_content():
        request = apply_request_middleware(rf.get("/"), user=admin_user)
        view = OrderCreateRefundView.as_view()
        response = view(request, pk=order.pk)
        return BeautifulSoup(response.render().content)

    refund_soup = get_refund_view_content()
    refund_options = refund_soup.find(id="id_form-0-line_number").findAll("option")
    assert len(refund_options) == 4  # 1 empty line, 1 for arbitrary and 2 for lines
    assert len([option for option in refund_options if "Special service 100$/h" in force_text(option)]) == 1
예제 #2
0
    def __init__(self, changing_user, *args, **kwargs):
        super(PermissionChangeFormBase, self).__init__(*args, **kwargs)
        self.changing_user = changing_user
        if not getattr(self.changing_user, 'is_superuser', False):
            self.fields.pop("is_superuser")

        if not (self.changing_user == self.instance
                or getattr(self.instance, 'is_superuser', False)):
            # Only require old password when editing
            self.fields.pop("old_password")

        if "is_superuser" in self.fields:
            self.fields["is_superuser"].label = _(
                "Superuser (Full rights) status")
            self.fields["is_superuser"].help_text = _(
                "Designates whether this user has all permissions without explicitly "
                "assigning them. Assigning Granular Permission Groups to a Superuser "
                "will not have any effect because Granular Permission Groups are only "
                " able to give more rights, but Superuser already has them all."
            )
        self.fields["is_staff"].label = _("Access to Admin Panel status")
        self.fields["is_staff"].help_text = _(
            "Designates whether this user can log into this admin site. Even "
            "Superusers should have this status enabled, otherwise they won't "
            "be able to access the Admin Panel.")

        permission_groups_field = Select2MultipleField(
            model=PermissionGroup,
            required=False,
            label=_("Granular Permission Groups"),
            help_text=
            _("Use Permission Groups to granularly give more permissions. User "
              "can belong to many groups and their permissions add and stack together. "
              "Search for `Permission Groups` to change these and add them to "
              "multiple users. Go to user account -> `Actions` -> `Edit Main "
              "Permissions` to add them to a specific user. Will not influence "
              "Superusers as they already have all the rights and can't be "
              "stripped of them without removing Superuser status first."))
        initial_groups = self._get_initial_groups()
        permission_groups_field.initial = [
            group.pk for group in initial_groups
        ]
        permission_groups_field.widget.choices = [(group.pk, force_text(group))
                                                  for group in initial_groups]
        self.fields["permission_groups"] = permission_groups_field
예제 #3
0
def get_running_reference_number(order):
    from shuup import configuration
    from shuup.admin.modules.settings.consts import (
        ORDER_REFERENCE_NUMBER_LENGTH_FIELD,
        ORDER_REFERENCE_NUMBER_PREFIX_FIELD,
    )

    value = Counter.get_and_increment(CounterType.ORDER_REFERENCE)
    prefix = "%s" % configuration.get(order.shop,
                                      ORDER_REFERENCE_NUMBER_PREFIX_FIELD,
                                      settings.SHUUP_REFERENCE_NUMBER_PREFIX)
    ref_length = configuration.get(order.shop,
                                   ORDER_REFERENCE_NUMBER_LENGTH_FIELD,
                                   settings.SHUUP_REFERENCE_NUMBER_LENGTH)

    padded_value = force_text(value).rjust(ref_length - len(prefix), "0")
    reference_no = "%s%s" % (prefix, padded_value)
    return reference_no + calc_reference_number_checksum(reference_no)
예제 #4
0
    def matches(self, target):
        """
        Evaluate this Pattern against the target.

        :type target: str
        :rtype: bool
        """
        target = force_text(target)
        if target in self.negative_pieces:
            return False

        if any(self._test_piece(piece, target) for piece in self.negative_pieces):
            return False

        if "*" in self.positive_pieces or target in self.positive_pieces:
            return True

        return any(self._test_piece(piece, target) for piece in self.positive_pieces)
예제 #5
0
 def get_known_additional_data(self):
     """
     Get a list of "known additional data" in this order's `payment_data`, `shipping_data` and `extra_data`.
     The list is returned in the order the fields are specified in the settings entries for said known keys.
     `dict(that_list)` can of course be used to "flatten" the list into a dict.
     :return: list of 2-tuples.
     """
     output = []
     for data_dict, name_mapping in (
             (self.payment_data, settings.SHUUP_ORDER_KNOWN_PAYMENT_DATA_KEYS),
             (self.shipping_data, settings.SHUUP_ORDER_KNOWN_SHIPPING_DATA_KEYS),
             (self.extra_data, settings.SHUUP_ORDER_KNOWN_EXTRA_DATA_KEYS),
     ):
         if hasattr(data_dict, "get"):
             for key, display_name in name_mapping:
                 if key in data_dict:
                     output.append((force_text(display_name), data_dict[key]))
     return output
예제 #6
0
    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop("request")
        self.shop = get_shop(self.request)
        super(CouponCodeForm, self).__init__(*args, **kwargs)

        if self.instance.pk:
            self.fields["coupon_code_discounts"] = Select2MultipleField(
                label=_("Product Discounts"),
                help_text=_("Select discounts linked to this coupon code."),
                model=Discount,
                required=False)
            initial_discounts = (self.instance.coupon_code_discounts.all()
                                 if self.instance.pk else [])
            self.fields["coupon_code_discounts"].initial = initial_discounts
            self.fields["coupon_code_discounts"].widget.choices = [
                (discount.pk, force_text(discount))
                for discount in initial_discounts
            ]
예제 #7
0
    def handle_customer_exists(self, request):
        field = request.GET["field"]
        value = request.GET["value"]

        if field in [f.name for f in Contact._meta.get_fields()]:
            contact_model = Contact
        elif field in [f.name for f in CompanyContact._meta.get_fields()]:
            contact_model = CompanyContact
        elif field in [f.name for f in PersonContact._meta.get_fields()]:
            contact_model = PersonContact
        else:
            return {"error": "Error! Invalid field name."}

        customer = contact_model.objects.filter(**{field: value}).first()
        if customer:
            return {"id": customer.pk, "name": force_text(customer)}
        else:
            return {}
예제 #8
0
파일: views.py 프로젝트: wphardware/shuup
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": "Error! Invalid folder `%s`." % force_text(exc)},
            status=400)

    return _process_form(request, folder)
예제 #9
0
    def address_as_string_list(self, address, locale=None):
        assert issubclass(type(address), Address)

        locale = locale or get_current_babel_locale()
        country = address.country.code.upper()

        base_lines = [
            address.company_name, address.full_name, address.name_ext,
            address.street, address.street2, address.street3,
            "%s %s %s" % (address.postal_code, address.city,
                          address.region_code or address.region),
            locale.territories.get(country, country)
            if not address.is_home else None
        ]

        stripped_lines = [
            force_text(line).strip() for line in base_lines if line
        ]
        return [s for s in stripped_lines if (s and len(s) > 1)]
예제 #10
0
파일: list.py 프로젝트: tapan-ghosh/shuup
 def get_object_abstract(self, instance, item):
     bits = filter(None, [
         _("First Name: %s") %
         (getattr(instance, 'first_name', None) or "\u2014"),
         _("Last Name: %s") %
         (getattr(instance, 'last_name', None) or "\u2014"),
         _("Active") if instance.is_active else _(u"Inactive"),
         _("Email: %s") % (getattr(instance, 'email', None) or "\u2014"),
         _("Access to Admin Panel")
         if getattr(instance, 'is_staff', None) else None,
         _("Superuser (Full rights)")
         if getattr(instance, 'is_superuser', None) else None
     ])
     return [{
         "text": instance.get_username() or _("User"),
         "class": "header"
     }, {
         "text": ", ".join([force_text(bit) for bit in bits])
     }]
예제 #11
0
파일: detail.py 프로젝트: tapan-ghosh/shuup
    def get_context_data(self, **kwargs):
        context = super(ContactDetailView, self).get_context_data(**kwargs)
        context["toolbar"] = ContactDetailToolbar(contact=self.object, request=self.request)
        context["title"] = "%s: %s" % (
            self.object._meta.verbose_name.title(),
            force_text(self.object)
        )
        context["contact_sections"] = []

        contact_sections_provides = sorted(get_provide_objects("admin_contact_section"), key=lambda x: x.order)
        for admin_contact_section in contact_sections_provides:
            # Check whether the ContactSection should be visible for the current object
            if admin_contact_section.visible_for_object(self.object, self.request):
                context["contact_sections"].append(admin_contact_section)
                # add additional context data where the key is the contact_section identifier
                section_context = admin_contact_section.get_context_data(self.object, self.request)
                context[admin_contact_section.identifier] = section_context

        return context
예제 #12
0
파일: detail.py 프로젝트: tapan-ghosh/shuup
    def get_context_data(self, **kwargs):
        context = super(OrderDetailView, self).get_context_data(**kwargs)
        context["toolbar"] = self.get_toolbar()
        context["title"] = force_text(self.object)
        context["order_sections"] = []

        order_sections_provides = sorted(
            get_provide_objects("admin_order_section"), key=lambda x: x.order)
        for admin_order_section in order_sections_provides:
            # Check whether the Section should be visible for the current object
            if admin_order_section.visible_for_object(self.object,
                                                      self.request):
                context["order_sections"].append(admin_order_section)
                # Add additional context data where the key is the order_section identifier
                section_context = admin_order_section.get_context_data(
                    self.object, self.request)
                context[admin_order_section.identifier] = section_context

        return context
예제 #13
0
파일: __init__.py 프로젝트: rrosajp/shuup
    def get_search_results(self, request, query):
        shop = request.shop
        minimum_query_length = 3
        skus_seen = set()
        if len(query) >= minimum_query_length:
            pk_counter = Counter()
            pk_counter.update(
                Product.objects.filter(sku__startswith=query).values_list(
                    "pk", flat=True))
            name_q = Q()
            for part in split_query(query, minimum_query_length):
                name_q &= Q(name__icontains=part)
            pk_counter.update(
                Product._parler_meta.root_model.objects.filter(
                    name_q).values_list("master_id", flat=True))
            pks = [pk for (pk, count) in pk_counter.most_common(10)]

            for product in Product.objects.filter(
                    pk__in=pks, shop_products__shop_id=shop.id):
                relevance = 100 - pk_counter.get(product.pk, 0)
                skus_seen.add(product.sku.lower())
                yield SearchResult(
                    text=force_text(product),
                    url=get_model_url(product, shop=request.shop),
                    category=_("Products"),
                    relevance=relevance,
                )

        if len(query) >= minimum_query_length:
            url = reverse("shuup_admin:shop_product.new")
            if " " in query:
                yield SearchResult(
                    text=_('Create Product Called "%s"') % query,
                    url=manipulate_query_string(url, name=query),
                    is_action=True,
                )
            else:
                if query.lower() not in skus_seen:
                    yield SearchResult(
                        text=_('Create Product with SKU "%s"') % query,
                        url=manipulate_query_string(url, sku=query),
                        is_action=True,
                    )
예제 #14
0
    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"] = ObjectSelect2MultipleField(
                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
예제 #15
0
    def __init__(self,
                 attrs=None,
                 choices=(),
                 editable_model=None,
                 initial=None,
                 model=None):
        """
        :param initial list[int]: list of primary keys of the objects that
            are initially selected
        """
        if model is not None:
            self.model = model

        if self.model and initial:
            choices = [(instance.pk, force_text(instance))
                       for instance in initial]

        super(QuickAddRelatedObjectMultipleSelectMixin,
              self).__init__(attrs, choices, editable_model)
예제 #16
0
 def _handle_related_value(self, field, mapping, orig_value, row_session,
                           obj, value):
     has_related = False
     if mapping.get("fk"):
         value = self._handle_row_fk_value(field, orig_value, row_session,
                                           value)
         if not field.null and value is None:
             has_related = True
     elif mapping.get("m2m"):
         self._handle_row_m2m_value(field, orig_value, row_session, obj,
                                    value)
         has_related = True
     elif mapping.get("is_enum_field"):
         for k, v in field.get_choices():
             if fold_mapping_name(
                     force_text(v)) == fold_mapping_name(orig_value):
                 value = k
                 break
     return (value, has_related)
예제 #17
0
    def post(self, request, *args, **kwargs):
        """
        Post action is where Mass Actions post their data.
        """
        data = request.body.decode("utf-8")
        data = json.loads(data)
        action_identifier = data.get("action", None)
        ids = data.get("values", [])

        mass_action = self._get_mass_action(action_identifier)
        if mass_action is None:
            return JsonResponse({
                "error":
                force_text(_("Mass Action encountered an unknown error."))
            })
        if isinstance(mass_action, PicotableFileMassAction):
            return mass_action.process(request, ids)

        mass_action.process(request, ids)
        return JsonResponse({"ok": True})
예제 #18
0
파일: edit.py 프로젝트: yurkobb/shuup
 def __init__(self, *args, **kwargs):
     self.request = kwargs.pop("request")
     super(ManufacturerForm, self).__init__(*args, **kwargs)
     # add shops field when superuser only
     if getattr(self.request.user, "is_superuser", False):
         self.fields["shops"] = Select2MultipleField(
             label=_("Shops"),
             help_text=
             _("Select shops for this manufacturer. Keep it blank to share with all shops."
               ),
             model=Shop,
             required=False,
         )
         initial_shops = self.instance.shops.all(
         ) if self.instance.pk else []
         self.fields["shops"].widget.choices = [(shop.pk, force_text(shop))
                                                for shop in initial_shops]
     else:
         # drop shops fields
         self.fields.pop("shops", None)
예제 #19
0
    def __init__(self, theme, shop, view_name, draft, global_type=False):
        """
        Initialize a view configuration.

        :param theme: Theme object (could be None to not touch the database).
        :type theme: shuup.xtheme.Theme|None
        :param shop: Shop object.
        :type shop: shuup.core.models.Shop
        :param view_name: View name (the class name of the view).
        :type view_name: str
        :param draft: Load in draft mode?
        :type draft: bool
        :param global_type: Boolean indicating whether this is a global config.
        :type global_type: bool|False
        """
        self.theme = theme
        self.shop = shop
        self.view_name = (XTHEME_GLOBAL_VIEW_NAME if global_type else force_text(view_name))
        self.draft = bool(draft)
        self._saved_view_config = None
예제 #20
0
    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop("request")
        self.shop = get_shop(self.request)
        super(AvailabilityExceptionForm, self).__init__(*args, **kwargs)

        if self.instance.pk:
            self.fields["discounts"] = Select2MultipleField(
                label=_("Product Discounts"),
                help_text=_(
                    "Select discounts to be ignored on given time frame."),
                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
            ]
예제 #21
0
    def __init__(self, pattern_text):
        """
        Compile a pattern from the given `pattern_text`.

        Patterns are comma-separated atoms of the forms:

        * `*` -- matches anything
        * `text` -- matched directly
        * `min-max` -- inclusive range matched lexicographically OR as integers if possible
        * `wild*` -- wildcards (asterisks and question marks allowed)

        In addition, atoms may be prefixed with `!` to negate them.

        For instance, "10-20,!15" would match all strings (or numbers) between 10 and 20, but not 15.

        :type pattern_text: str
        """
        self.pattern_text = pattern_text
        self.positive_pieces = set()
        self.negative_pieces = set()

        for piece in force_text(self.pattern_text).split(","):
            piece = piece.strip()
            if not piece:
                continue
            if piece.startswith("!"):
                negate = True
                piece = piece[1:].strip()
            else:
                negate = False

            if "-" in piece:
                (min, max) = piece.split("-", 1)
                piece = (min.strip(), max.strip())
            else:
                piece = (piece.strip(), piece.strip())

            if negate:
                self.negative_pieces.add(piece)
            else:
                self.positive_pieces.add(piece)
예제 #22
0
파일: forms.py 프로젝트: tapan-ghosh/shuup
    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop("request")
        super(SupplierBaseForm, self).__init__(*args, **kwargs)

        # add shops field when superuser only
        if getattr(self.request.user, "is_superuser", False):
            initial_shops = (self.instance.shops.all() if self.instance.pk else [])
            self.fields["shops"] = Select2MultipleField(
                label=_("Shops"),
                help_text=_("Select shops for this supplier. Keep it blank to share with all shops."),
                model=Shop,
                required=False,
                initial=initial_shops
            )
            self.fields["shops"].choices = initial_shops
            self.fields["shops"].widget.choices = [
                (shop.pk, force_text(shop)) for shop in initial_shops
            ]
        else:
            # drop shops fields
            self.fields.pop("shops", None)

        shop = get_shop(self.request)

        self.fields["is_approved"] = forms.BooleanField(
            label=_("Is approved for {}").format(shop),
            required=False,
            initial=True,
            help_text=_("Indicates whether this supplier is approved for the shop."),
        )

        if self.instance.pk:
            supplier_shop = SupplierShop.objects.filter(shop=shop, supplier=self.instance).first()
            self.fields["is_approved"].initial = bool(supplier_shop and supplier_shop.is_approved)
        else:
            self.fields["is_approved"].initial = False

        choices = Supplier.get_module_choices(
            empty_label=(_("No %s module") % Supplier._meta.verbose_name)
        )
        self.fields["module_identifier"].choices = self.fields["module_identifier"].widget.choices = choices
예제 #23
0
    def __init__(self, url, **kwargs):
        """
        :param url: The URL to navigate to. For convenience, if this contains no slashes,
                    `reverse` is automatically called on it.
        :type url: str
        """
        if "/" not in url:
            try:
                url = reverse(url)
            except NoReverseMatch:
                pass
        self.url = url

        if "required_permissions" not in kwargs:
            try:
                permission = resolve(six.moves.urllib.parse.urlparse(force_text(url)).path).url_name
                kwargs["required_permissions"] = (permission,)
            except Resolver404:
                pass

        super(URLActionButton, self).__init__(**kwargs)
예제 #24
0
def test_deleting_script(rf, admin_user):
    shop = factories.get_default_shop()
    request = apply_request_middleware(rf.get("/"), user=admin_user)
    script = Script.objects.create(shop=shop,
                                   event_identifier="order_received",
                                   name="Script 1",
                                   enabled=True)

    delete_url = reverse("shuup_admin:notify.script.delete",
                         kwargs={"pk": script.pk})
    view = ScriptEditView.as_view()
    response = view(request, pk=script.pk).render()
    assert bool(delete_url in force_text(response.content))

    assert Script.objects.count() == 1

    request = apply_request_middleware(rf.post("/"), user=admin_user)
    delete_view = ScriptDeleteView.as_view()
    response = delete_view(request, pk=script.pk)
    assert response.status_code == 302  # Redirect to list view
    assert Script.objects.count() == 0
예제 #25
0
파일: _source.py 프로젝트: yurkobb/shuup
    def add_code(self, code):
        """
        Add a code to this OrderSource.

        At this point it is expected that the customers
        permission to use the code has already been
        checked by the caller.

        The code will be converted to text.

        :param code: The code to add.
        :type code: str
        :return: True if code was added, False if it was already there.
        :rtype: bool
        """
        code_text = force_text(code)
        if code_text.upper() not in [c.upper() for c in self._codes]:
            self._codes.append(code_text)
            self.uncache()
            return True
        return False
예제 #26
0
    def __init__(self, **kwargs):
        super(ShopBaseForm, self).__init__(**kwargs)
        self.fields["currency"] = forms.ChoiceField(
            choices=get_currency_choices(),
            required=True,
            label=_("Currency"),
            help_text=_("The primary shop currency. This is the currency used when selling your products.")
        )

        staff_members = Select2MultipleField(
            label=_("Staff"),
            help_text=_("Select staff members for this shop."),
            model=get_user_model(),
            required=False
        )
        staff_members.widget = QuickAddUserMultiSelect(attrs={"data-model": "auth.User"})
        initial_members = (self.instance.staff_members.all() if self.instance.pk else [])
        staff_members.widget.choices = [(member.pk, force_text(member)) for member in initial_members]
        self.fields["staff_members"] = staff_members
        self.fields["domain"].required = ShuupSettings.get_setting("SHUUP_ENABLE_MULTIPLE_SHOPS")
        self.disable_protected_fields()
예제 #27
0
def generate_multilanguage_slugs(object, name_getter, slug_length=128):
    translations_model = object._parler_meta.root_model
    for language_code, language_name in settings.LANGUAGES:
        try:
            translation = object.get_translation(language_code=language_code)
            translation.refresh_from_db()
        except ObjectDoesNotExist:
            # For some reason the `get_translation` raises if the object is created recently
            translation = translations_model.objects.filter(
                master_id=object.id, language_code=language_code).first()
            if not translation:
                # Guessing the translation is deleted recently so let's just skip this language
                continue

        # Since slugs can be set by the merchant let's not override if already set
        if not translation or translation.slug:
            continue

        name = force_text(name_getter(object, translation))
        slug = slugify(name)
        translation.slug = (slug[:slug_length] if slug else None)
        translation.save()
예제 #28
0
    def _render_cell(self, write, layout, x, cell):
        """
        Render a layout cell into HTML.

        :param write: Writer function
        :type write: callable
        :param x: Cell X coordinate
        :type x: int
        :param cell: Cell
        :type cell: shuup.xtheme.view_config.LayoutCell
        """
        classes = ["xt-ph-cell"]
        for breakpoint, width in cell.sizes.items():
            if width is None or width == 0:
                continue
            if width < 0:
                classes.append(layout.hide_cell_class_template % {
                    "breakpoint": breakpoint,
                    "width": width
                })
            else:
                classes.append(layout.cell_class_template % {
                    "breakpoint": breakpoint,
                    "width": width
                })

        classes.append(cell.align)
        if cell.extra_classes:
            classes.append(cell.extra_classes)

        cell_attrs = {"class": classes}
        if self.edit:
            cell_attrs.update({"data-xt-cell": str(x)})
        write("<div%s>" % get_html_attrs(cell_attrs))
        content = cell.render(self.context)
        if content is not None:  # pragma: no branch
            write(force_text(content))
        write("</div>")
예제 #29
0
    def __init__(self, model, required=True, label=None,
                 initial=None, help_text='', extra_widget_attrs={}, *args, **kwargs):
        widget_attrs = {"data-model": model}
        widget_attrs.update(extra_widget_attrs)

        choices = []
        if initial:
            from django.apps import apps
            app_label, model_name = model.split(".")
            model = apps.get_model(app_label, model_name)
            instance = model.objects.filter(pk=initial).first()
            if instance:
                choices = [(instance.pk, force_text(instance))]

        super(XThemeSelect2ModelChoiceField, self).__init__(
            choices=choices,
            required=required,
            widget=forms.Select(attrs=widget_attrs),
            label=label,
            initial=initial,
            help_text=help_text,
            *args, **kwargs
        )
예제 #30
0
    def get_display_value(self, context, object):
        # Look for callable from view context
        display_callable = maybe_callable(self.display, context=context)
        if display_callable:
            return display_callable(object)

        # Look for callable from provided column objects contexts
        display_callable = self.search_from_provided_contexts(object)
        if display_callable:
            return display_callable(object)

        value = object
        for bit in self.display.split("__"):
            value = getattr(value, bit, None)

        return_value = self.check_different_types(value)
        if return_value is not None:
            return return_value

        if not value:
            value = ""

        return force_text(value)