示例#1
0
    def __init__(self, parent, node=None, attach=False, enlarge=True, reserved=(), skip_slug=False, *args, **kwargs):
        """
            Django will put the extra slug field at the bottom, below
            all model fields. I want it just after the title field
        """
        super(BaseForm, self).__init__(*args, **kwargs)
        slug = self.fields.pop("slug")
        titlepos = self.fields.keyOrder.index("title")
        self.fields.insert(titlepos + 1, "slug", slug)
        self.node = node
        self.parent = parent
        self.attach = attach
        self.reserved = reserved
        self.advanced_fields = self.initial_advanced_fields

        if attach:
            self.fields.pop("slug")

        templates = template_registry.get(self._meta.model, [])
        if templates:
            self.fields["template"] = forms.ChoiceField(choices=templates, required=False)
        else:
            self.fields.pop("template")  ## will default to content_view

        self.fields["state"] = forms.ChoiceField(
            choices=self.workflow_choices(), initial=self.workflow_default(), required=False
        )
        if skip_slug:
            self.fields.pop("slug")

        if enlarge:
            for enlargable_field in self.fields.values():
                self.enlarge_field(enlargable_field)

        ## make the description textarea a bit smaller
        if "description" in self.fields:
            self.fields["description"].widget.attrs["rows"] = 4

        if "tags" in self.fields:
            self.fields["tags"].widget.attrs["class"] = "tagManager"
            self.fields["tags"].required = False

        ## lightforms don't have a language field
        if "language" in self.fields:
            if self.node:
                ## construct allowed languages. Exclude any language for which
                ## the node already has content
                current = self.instance.language if self.instance else None
                c = []
                for lpair in translate.languages():
                    if current == lpair[0] or not self.node.content(language=lpair[0], fallback=False):
                        c.append(lpair)
                self.fields["language"].choices = c
            else:
                self.fields["language"].choices = translate.languages()

        for e in type_registry.extenders(self.Meta.model):
            e.extend_form(self, *args, **kwargs)
示例#2
0
    def rename(self, slug, language=None):
        """ change the slug """
        if self.isroot():
            raise CantRenameRoot()

        ## if no language was specified, rename all
        languages = [language] if language else [l[0] for l in translate.languages()]

        for testmode in (True, False):
            ## first loop checks if all relevant languages can be renamed, second loop renames
            for language in languages:
                try:
                    localized_path = Paths.objects.get(node=self, language=language)
                except Paths.DoesNotExist:
                    continue

                newpath = localized_path.path.rsplit("/", 1)[0] + "/" + slug

                if testmode:
                    if Paths.objects.filter(path=newpath, language=language).exists():
                        raise DuplicatePathException(newpath, language)
                else:
                    for p in Paths.objects.filter(Q(path=localized_path.path) |
                                                  Q(path__startswith=localized_path.path + '/'),
                                                  language=language):
                        remainder = p.path[len(localized_path.path):]
                        p.path = newpath + remainder
                        p.save()
示例#3
0
    def save(self, *args, **kw):
        ## If the object has not yet been saved (ever), create the node's paths
        saved = True
        if self.pk is None:
            saved = False


        ## first save the object so we can create references
        super(NodeBase, self).save(*args, **kw)

        ## create paths based on self._slug / self._parent which were passed to __init__
        if not saved:
            for language, langname in translate.languages():
                try:
                    langpath = Paths.objects.get(node=self, language=language)
                except Paths.DoesNotExist:
                    langpath = Paths(node=self, language=language)

                langslug = translate.language_slug(self._langslugs, self._slug, language)

                if not self._parent:
                    path = '' # '/' + str(self.id) -- be consistent with 'old' behavior, for now
                    langpath.path = langslug
                else:
                    path = self._parent.tree_path + '/' + str(self.id)
                    langpath.path = self._parent.get_path(language) + '/' + langslug
                langpath.save()

            self.tree_path = path
            super(NodeBase, self).save()
示例#4
0
def get_active_language():
    """
        The active language is either forced in settings,
        set in the session (for admin), a GET argument or
        the translation default
    """
    lang = getattr(settings, 'FORCE_LANGUAGE', None)

    if not lang:
        lang = locale.get_content_language()

    langids = (l[0] for l in translate.languages())

    if lang not in langids and getattr(settings, 'FALLBACK', None):
        lang = settings.FALLBACK
    return lang
示例#5
0
    def translations(self):
        """
            Return data for the translations/languages menu. This means
            "switch to" options for translated languages and "translate to"
            for untranslated languages.

            If there's no second language (ignoring 'Any'), don't return
            anything; this will hide the translation menu entirely.
        """
        if not self.instance or self.status == Toolbar.SPECIAL:
            return None

        if len(settings.CONTENT_LANGUAGES) == 1:
            return None

        active = None
        translated = []
        untranslated = []

        active_language = get_active_language()

        for (lang, langtitle) in translate.languages():
            option = dict(id=lang, language=langtitle)
            content = self.instance.content(language=lang)

            ## In view mode toch edit tonen om vertaling te maken!
            base_url = "switch_admin_language?path=" + self.instance.tree_path + "&switchto=" + lang
            if lang == active_language:
                active = option
            else:
                if self.status == Toolbar.UPDATE:
                    option["action_url"] = base_url + "&rest=edit"
                elif self.status == Toolbar.VIEW:
                    option["action_url"] = base_url + ""
                elif self.status == Toolbar.LIST:
                    option["action_url"] = base_url + "&rest=list"
                elif self.status == Toolbar.CREATE:
                    option["action_url"] = (
                        base_url + "&rest=" + urllib2.quote("create?type=" + self.request.GET.get("type"))
                    )

                if content and self.status != Toolbar.CREATE:
                    translated.append(option)
                else:
                    untranslated.append(option)

        return dict(active=active, translated=translated, untranslated=untranslated)
示例#6
0
    def handle_list(self):
        spoke = self.spoke()

        if spoke:
            perm = spoke.permissions.get('list')
        else:
            perm = Spoke.permissions.get('list')

        if not auth.has_access(self.request, spoke, spoke, perm):
            return self.forbidden()

        if self.toolbar:
            self.toolbar.status = Toolbar.LIST
        self.context['breadcrumb'] = self.breadcrumb(operation="Contents")

        self.context['can_paste'] = \
            len(self.request.session.get('clipboard_copy', [])) + \
            len(self.request.session.get('clipboard_cut', []))

        active = self.active_language()

        children = []

        for child in self.instance.children():
            c = dict(node=child, active=None, translations=[],
                     ipath=child.tree_path)
            for lang, langtitle in translate.languages():
                langcontent = child.content(language=lang)
                c["translations"].append((lang, langcontent,
                                          "switch_admin_language?path=" + child.tree_path + "&switchto=" + lang + "&rest=edit"))
                if lang == active:
                    c["active"] = langcontent
            if not c['active']:
                c['active'] = child.primary_content()
            children.append(c)

        self.context['children'] = children

        if spoke:
            return self.template(spoke.list_template())

        return self.template("wheelcms_axle/contents.html")
示例#7
0
def get_active_language(request=None):
    """
        The active language is either forced in settings,
        set in the session (for admin), a GET argument or
        the translation default
    """
    lang = getattr(settings, 'FORCE_LANGUAGE', None)

    if not lang and request:
        admin_language = request.session.get('admin_language')
        lang = admin_language or request.GET.get('language')

    if not lang:
        lang = translation.get_language()

    langids = (l[0] for l in translate.languages())

    if lang not in langids and getattr(settings, 'FALLBACK', None):
        lang = settings.FALLBACK
    return lang
示例#8
0
    def translations(self):
        if not self.instance or self.status == "special":
            return None

        active = None
        translated = []
        untranslated = []

        active_language = get_active_language(self.request)

        for (lang, langtitle) in translate.languages():
            option = dict(id=lang, language=langtitle)
            content = self.instance.content(language=lang)

            ## In view mode toch edit tonen om vertaling te maken!
            base_url = "switch_admin_language?path=" + self.instance.tree_path + "&language=" + lang
            if lang == active_language:
                active = option
            else:
                if self.status == "update":
                    option['action_url'] = base_url + '&rest=edit'
                elif self.status == "view":
                    option['action_url'] = base_url + ''
                elif self.status == "list":
                    option['action_url'] = base_url + '&rest=list'
                elif self.status == "create":
                    option['action_url'] = base_url + '&rest=' + urllib2.quote('create?type=' + self.request.GET.get('type'))

                if content and self.status != 'create':
                    translated.append(option)
                else:
                    untranslated.append(option)

        return dict(active=active,
                    translated=translated,
                    untranslated=untranslated)
示例#9
0
    def paste(self, node, copy=False):
        """
            Move a node elsewhere in the tree, optionally copying the node
            (copy-paste) or deleting the original (cut-paste)
        """
        ## a move is just rewriting/renaming the child and its offspring,
        ## a copy is recreating the node

        ## ancestor nodes cannot be moved into offspring nodes, they can be
        ## copied, but avoid recursion.

        ## how to deal with the position? Insert at the bottom?

        from .content import ContentCopyException

        failed = []
        success = []

        if copy:
            slug_per_lang = {}
            for p in node.paths.all():
                lang, path = p.language, p.path

                if path == "":
                    slug = "root"
                else:
                    base_slug = slug = path.rsplit('/', 1)[1]

                count = 0
                while self.child(slug, lang):
                    slug = "copy_%s_of_%s" % (count, base_slug)
                slug_per_lang[lang] = slug


            base = self.add(langslugs=slug_per_lang)
            if node.content():
                try:
                    node.content().copy(node=base)
                    success.append(node.tree_path)
                except ContentCopyException:
                    failed.append((node.tree_path, "Content cannot be copied"))
                    base.delete()
                    ## no need to continue
                    return base, success, failed

            for o in Node.objects.offspring(node).order_by("tree_path"):
                ## skip all offspring of a failed node
                for f, reason in failed:
                    if o.tree_path.startswith(f + '/'):
                        break
                else:
                    langslugs = dict((p.language, p.path.rsplit("/", 1)[1]) for  p in o.paths.all())
                    n = Node(langslugs=langslugs, parent=base)
                    n.save()
                    if o.content():
                        try:
                            o.content().copy(node=n)
                            success.append(o.tree_path)
                        except ContentCopyException:
                            n.delete()
                            failed.append((o.tree_path, "Content cannot be copied"))
            return base, success, failed

        else:
            if node == self or node.is_ancestor(self):
                raise CantMoveToOffspring()
            oldpath = node.tree_path
            oldbase, slug = oldpath.rsplit("/", 1)
            if oldbase == self.tree_path:
                ## pasting into its own parent, nothing to do
                return node, success, failed

            ## XXX somehow batch/transaction this
            for o in node_proxy_factory(Node, self.preferred_language).objects.offspring(node):
                o.tree_path = self.tree_path + o.tree_path[len(oldbase):]
                o.save()
                success.append(o.tree_path)
            node.tree_path = self.tree_path + '/' + str(node.id)
            ## move to end
            node.position = self.find_position(position=-1)
            node.save()
            success.append(node.tree_path)

            ## the great renaming
            # import pytest; pytest.set_trace()
            for language, langname in translate.languages():
                try:
                    localized_path = Paths.objects.get(node=node, language=language)
                except Paths.DoesNotExist:
                    continue

                slug = localized_path.path.rsplit('/', 1)[1]

                mypath = self.get_path(language)
                newpath = mypath + '/' + slug
                count = 0

                while Paths.objects.filter(path=newpath, language=language).exists():
                    newpath = mypath + slug + "_" + str(count)
                    count += 1

                #if testmode:
                #if Paths.objects.filter(path=newpath, language=language).exists():
                #    raise DuplicatePathException(newpath, language)
                #else:
                for p in Paths.objects.filter(Q(path=localized_path.path) |
                                              Q(path__startswith=localized_path.path + '/'),
                                              language=language):
                    remainder = p.path[len(localized_path.path):]

                    p.path = newpath + remainder

                    p.save()


        return node, success, failed
示例#10
0
    def edit(self):
        language = self.active_language()

        instance = self.instance

        supported_languages = (l[0] for l in translate.languages())
        if language not in supported_languages:
            return self.redirect(instance.get_absolute_url(),
                                 error="Unsupported Language")

        if self.spoke():
            ## update the context with addtional data from the spoke
            self.context.update(self.spoke().context(self, self.request,
                                self.instance))


        content = instance.content(language=language)
        create_translation = False

        if content is None:
            pcontent = instance.primary_content()
            typename = pcontent.get_name()
            typeinfo = type_registry.get(typename)
            create_translation = True
            spoke = pcontent.spoke()
        else:
            typename = content.get_name()
            typeinfo = type_registry.get(typename)
            spoke = content.spoke()

        perm = typeinfo.permissions.get('edit')

        if not auth.has_access(self.request, typeinfo, spoke, perm):
            return self.forbidden()

        # reset tabs with current language tabs
        self.context['tabs'] = self.tabs(spoke)

        parent = instance.parent()

        self.context['redirect_cancel'] = self.instance.get_absolute_url() + \
                                          "?info=Update+cancelled"
        if self.toolbar:
            self.toolbar.status = Toolbar.UPDATE

        formclass =  typeinfo.form
        slug = instance.slug(language=language)

        if self.is_post:
            args = dict(parent=parent, data=self.request.POST,
                        reserved=self.reserved(),
                        skip_slug=self.instance.isroot(),
                        node=self.instance,
                        files=self.request.FILES)
            if content:
                args['instance'] = content

            self.context['form'] = form = formclass(**args)

            if form.is_valid():
                try:
                    if create_translation:
                        content = form.save(commit=False)
                    else:  # ordinary update
                        content = form.save()
                except OSError, e:
                    messages.error("An error occured while saving: %s" % str(e))

                if create_translation:
                    if self.user().is_authenticated():
                        content.owner = self.user()
                    content.node = self.instance
                    content.save()
                    form.save_m2m()

                ## handle changed slug
                slug = form.cleaned_data.get('slug', None)
                content_language = form.cleaned_data.get('language', settings.FALLBACK)


                if slug and slug != self.instance.slug(language=content_language):
                    self.instance.rename(slug, language=content_language)

                return self.redirect(instance.get_absolute_url(),
                                     success="Updated")
示例#11
0
    def __init__(self, parent, node=None, attach=False, enlarge=True,
                 reserved=(),
                 skip_slug=False, *args, **kwargs):
        """
            Django will put the extra slug field at the bottom, below
            all model fields. I want it just after the title field
        """
        super(BaseForm, self).__init__(*args, **kwargs)
        slug = self.fields.pop('slug')
        titlepos = self.fields.keyOrder.index('title')
        self.fields.insert(titlepos+1, 'slug', slug)
        self.node = node
        self.parent = parent
        self.attach = attach
        self.reserved = reserved
        self.advanced_fields = self.initial_advanced_fields

        ## Pass parent to ParentFields
        for field in self.fields.values():
            if isinstance(field, ParentField):
                field.parent = parent

        if attach:
            self.fields.pop('slug')

        templates = template_registry.get(self._meta.model, [])
        if templates:
            self.fields['template'] = forms.ChoiceField(choices=templates,
                                                        required=False)
        else:
            self.fields.pop('template')  ## will default to content_view

        self.fields['state'] = forms.ChoiceField(choices=self.workflow_choices(),
                                                 initial=self.workflow_default(),
                                                 required=False)
        if skip_slug:
            self.fields.pop("slug")

        if enlarge:
            for enlargable_field in self.fields.values():
                self.enlarge_field(enlargable_field)

        ## make the description textarea a bit smaller
        if 'description' in self.fields:
            self.fields['description'].widget.attrs['rows'] = 4


        ## workaround for https://code.djangoproject.com/ticket/21173
        for patch_dt in ("publication", "expire", "created"):
            if patch_dt in self.fields:
                f = self.fields[patch_dt]
                f.widget = DateTimeInput()

        ## lightforms don't have a language field
        if 'language' in self.fields:
            if self.node:
                ## construct allowed languages. Exclude any language for which
                ## the node already has content
                current = self.instance.language if self.instance else None
                c = []
                for lpair in translate.languages():
                    if current == lpair[0] or \
                       not self.node.content(language=lpair[0], fallback=False):
                        c.append(lpair)
                self.fields['language'].choices = c
            else:
                self.fields['language'].choices = translate.languages()

        for e in type_registry.extenders(self.Meta.model):
            e.extend_form(self, *args, **kwargs)

        if "allowed" in self.fields:
            self.fields["allowed"].choices = ((t.name(), t.title)
                for t in sorted(type_registry.values(),
                                key=operator.attrgetter("title")))
            if self.instance:
                allowed = self.instance.allowed
                if allowed == "" and "no_subcontent" in self.fields:
                        self.fields["no_subcontent"].initial = True