Exemple #1
0
def add_plugin(placeholder, plugin_type, language, position='last-child',
               target=None, **data):
    """
    Add a plugin to a placeholder
    
    See docs/extending_cms/api_reference.rst for more info
    """
    # validate placeholder
    assert isinstance(placeholder, Placeholder)
    
    # validate and normalize plugin type
    plugin_model, plugin_type = _verify_plugin_type(plugin_type)
        

    max_pos = CMSPlugin.objects.filter(language=language,
        placeholder=placeholder).aggregate(Max('position'))['position__max'] or 0

    plugin_base = CMSPlugin(
        plugin_type=plugin_type,
        placeholder=placeholder, 
        position=max_pos + 1,
        language=language
    )
    plugin_base.insert_at(target, position=position, save=False)
            
    plugin = plugin_model(**data)
    plugin_base.set_base_attr(plugin)
    plugin.save()
    return plugin
Exemple #2
0
def add_plugin(placeholder,
               plugin_type,
               language,
               position='last-child',
               target=None,
               **data):
    """
    Add a plugin to a placeholder
    
    See docs/extending_cms/api_reference.rst for more info
    """
    # validate placeholder
    assert isinstance(placeholder, Placeholder)

    # validate and normalize plugin type
    plugin_model, plugin_type = _verify_plugin_type(plugin_type)

    max_pos = CMSPlugin.objects.filter(
        language=language, placeholder=placeholder).aggregate(
            Max('position'))['position__max'] or 0

    plugin_base = CMSPlugin(plugin_type=plugin_type,
                            placeholder=placeholder,
                            position=max_pos + 1,
                            language=language)
    plugin_base.insert_at(target, position=position, save=False)

    plugin = plugin_model(**data)
    plugin_base.set_base_attr(plugin)
    plugin.save()
    return plugin
Exemple #3
0
    def test_delete_with_plugins(self):
        """
        Check that plugins and placeholders get correctly deleted when we delete
        a page!
        """
        home = create_page("home", "nav_playground.html", "en")
        page = create_page("page", "nav_playground.html", "en")
        page.rescan_placeholders() # create placeholders
        placeholder = page.placeholders.all()[0]
        plugin_base = CMSPlugin(
            plugin_type='TextPlugin',
            placeholder=placeholder,
            position=1,
            language=settings.LANGUAGES[0][0]
        )
        plugin_base.insert_at(None, position='last-child', save=False)

        plugin = Text(body='')
        plugin_base.set_base_attr(plugin)
        plugin.save()
        self.assertEqual(CMSPlugin.objects.count(), 1)
        self.assertEqual(Text.objects.count(), 1)
        self.assertTrue(Placeholder.objects.count() > 2)
        page.delete()
        home.delete()
        self.assertEqual(CMSPlugin.objects.count(), 0)
        self.assertEqual(Text.objects.count(), 0)
        self.assertEqual(Placeholder.objects.count(), 0)
        self.assertEqual(Page.objects.count(), 0)
Exemple #4
0
    def test_inherit_plugin_with_empty_plugin(self):
        inheritfrompage = create_page('page to inherit from',
                                      'nav_playground.html',
                                      'en', published=True)

        body = inheritfrompage.placeholders.get(slot="body")
        empty_plugin = CMSPlugin(
            plugin_type='TextPlugin', # create an empty plugin
            placeholder=body,
            position=1,
            language='en',
        )
        empty_plugin.insert_at(None, position='last-child', save=True)
        other_page = create_page('other page', 'nav_playground.html', 'en', published=True)
        inherited_body = other_page.placeholders.get(slot="body")
        inherit_plugin = InheritPagePlaceholder(
            plugin_type='InheritPagePlaceholderPlugin',
            placeholder=inherited_body,
            position=1,
            language='en',
            from_page=inheritfrompage,
            from_language='en'
        )
        inherit_plugin.insert_at(None, position='last-child', save=True)
        add_plugin(inherited_body, "TextPlugin", "en", body="foobar")
        # this should not fail, even if there in an empty plugin
        rendered = inherited_body.render(context=self.get_context(other_page.get_absolute_url()), width=200)
        self.assertIn("foobar", rendered)
Exemple #5
0
    def test_delete_with_plugins(self):
        """
        Check that plugins and placeholders get correctly deleted when we delete
        a page!
        """
        page = create_page("page", "nav_playground.html", "en")
        page.rescan_placeholders() # create placeholders
        placeholder = page.placeholders.all()[0]
        plugin_base = CMSPlugin(
            plugin_type='TextPlugin',
            placeholder=placeholder,
            position=1,
            language=settings.LANGUAGES[0][0]
        )
        plugin_base.insert_at(None, position='last-child', save=False)

        plugin = Text(body='')
        plugin_base.set_base_attr(plugin)
        plugin.save()
        self.assertEqual(CMSPlugin.objects.count(), 1)
        self.assertEqual(Text.objects.count(), 1)
        self.assertTrue(Placeholder.objects.count() > 0)
        page.delete()
        self.assertEqual(CMSPlugin.objects.count(), 0)
        self.assertEqual(Text.objects.count(), 0)
        self.assertEqual(Placeholder.objects.count(), 0)
Exemple #6
0
    def add_plugin(self,
                   user=None,
                   page=None,
                   placeholder=None,
                   language='en',
                   body=''):
        if not placeholder:
            if page:
                placeholder = page.placeholders.get(
                    slot__iexact='Right-Column')
            else:
                placeholder = page.placeholders.get(
                    slot__iexact='Right-Column')

        plugin_base = CMSPlugin(
            plugin_type='TextPlugin',
            placeholder=placeholder,
            position=1,
            language=language)
        plugin_base.insert_at(None, position='last-child', commit=False)

        plugin = Text(body=body)
        plugin_base.set_base_attr(plugin)
        plugin.save()
        return plugin.pk
Exemple #7
0
def add_plugin(placeholder, plugin_type, language, position='last-child',
               **data):
    """
    Add a plugin to a placeholder
    
    See docs/extending_cms/api_reference.rst for more info
    """
    # validate placeholder
    assert isinstance(placeholder, Placeholder)
    
    # validate and normalize plugin type
    plugin_model, plugin_type = _verify_plugin_type(plugin_type)
        
    plugin_base = CMSPlugin(
        plugin_type=plugin_type,
        placeholder=placeholder, 
        position=1, 
        language=language
    )
    plugin_base.insert_at(None, position=position, save=False)
            
    plugin = plugin_model(**data)
    plugin_base.set_base_attr(plugin)
    plugin.save()
    return plugin
Exemple #8
0
def add_plugin(placeholder,
               plugin_type,
               language,
               position='last-child',
               target=None,
               **data):
    """
    Add a plugin to a placeholder
    
    See docs/extending_cms/api_reference.rst for more info
    """
    # validate placeholder
    assert isinstance(placeholder, Placeholder)

    # validate and normalize plugin type
    plugin_model, plugin_type = _verify_plugin_type(plugin_type)
    if target:
        if position == 'last-child':
            new_pos = CMSPlugin.objects.filter(language=language,
                                               parent=target,
                                               tree_id=target.tree_id).count()
        elif position == 'first-child':
            new_pos = 0
        elif position == 'left':
            new_pos = target.position
        elif position == 'right':
            new_pos = target.position + 1
        else:
            raise Exception('position not supported: %s' % position)
        for pl in CMSPlugin.objects.filter(language=language,
                                           parent=target.parent_id,
                                           tree_id=target.tree_id,
                                           position__gte=new_pos):
            pl.position += 1
            pl.save()
    else:
        new_pos = CMSPlugin.objects.filter(language=language,
                                           parent__isnull=True,
                                           placeholder=placeholder).count()

    plugin_base = CMSPlugin(plugin_type=plugin_type,
                            placeholder=placeholder,
                            position=new_pos,
                            language=language)
    plugin_base.insert_at(target, position=position, save=False)

    plugin = plugin_model(**data)
    plugin_base.set_base_attr(plugin)
    plugin.save()
    return plugin
Exemple #9
0
    def test_empty_plugin_is_ignored(self):
        page = create_page("page", "nav_playground.html", "en")

        placeholder = page.placeholders.get(slot='body')

        plugin = CMSPlugin(plugin_type='TextPlugin',
                           placeholder=placeholder,
                           position=1,
                           language=self.FIRST_LANG)
        plugin.insert_at(None, position='last-child', save=True)

        # this should not raise any errors, but just ignore the empty plugin
        out = placeholder.render(self.get_context(), width=300)
        self.assertFalse(len(out))
        self.assertFalse(len(placeholder._en_plugins_cache))
Exemple #10
0
    def test_empty_plugin_is_ignored(self):
        page = create_page("page", "nav_playground.html", "en")

        placeholder = page.placeholders.get(slot='body')

        plugin = CMSPlugin(
            plugin_type='TextPlugin',
            placeholder=placeholder,
            position=1,
            language=self.FIRST_LANG)
        plugin.insert_at(None, position='last-child', save=True)

        # this should not raise any errors, but just ignore the empty plugin
        out = placeholder.render(self.get_context(), width=300)
        self.assertFalse(len(out))
        self.assertFalse(len(placeholder._en_plugins_cache))
Exemple #11
0
def add_plugin(placeholder, plugin_type, language, position='last-child', **data):
    """
    Taken from django-cms api (in newer versions)
    https://github.com/divio/django-cms/blob/b8633b42efcd137d96e1e3f42e004cb7595768fe/cms/api.py
    """
    assert isinstance(placeholder, Placeholder)
    plugin_model = plugin_type.model
    plugin_type = plugin_type.__name__
    plugin_base = CMSPlugin(
        plugin_type=plugin_type,
        placeholder=placeholder, 
        position=1,
        language=language
    )
    plugin_base.insert_at(None, position='last-child', commit=False)
    plugin = plugin_model(**data)
    plugin_base.set_base_attr(plugin)
    plugin.save()
    return plugin
Exemple #12
0
 def add_plugin(self, user=None, page=None, placeholder=None, language='en', body=''):
     if not placeholder:
         if page:
             placeholder = page.placeholders.get(slot__iexact='Right-Column')
         else:
             placeholder = page.placeholders.get(slot__iexact='Right-Column')
         
     plugin_base = CMSPlugin(
         plugin_type='TextPlugin',
         placeholder=placeholder, 
         position=1, 
         language=language
     )
     plugin_base.insert_at(None, position='last-child', commit=False)
             
     plugin = Text(body=body)
     plugin_base.set_base_attr(plugin)
     plugin.save()
     return plugin.pk
Exemple #13
0
def add_plugin(placeholder, plugin_type, language, position='last-child',
               target=None, **data):
    """
    Add a plugin to a placeholder
    
    See docs/extending_cms/api_reference.rst for more info
    """
    # validate placeholder
    assert isinstance(placeholder, Placeholder)

    # validate and normalize plugin type
    plugin_model, plugin_type = _verify_plugin_type(plugin_type)
    if target:
        if position == 'last-child':
            new_pos = CMSPlugin.objects.filter(language=language, parent=target, tree_id=target.tree_id).count()
        elif position == 'first-child':
            new_pos = 0
        elif position == 'left':
            new_pos = target.position
        elif position == 'right':
            new_pos = target.position + 1
        else:
            raise Exception('position not supported: %s' % position)
        for pl in CMSPlugin.objects.filter(language=language, parent=target.parent_id, tree_id=target.tree_id, position__gte=new_pos):
            pl.position += 1
            pl.save()
    else:
        new_pos = CMSPlugin.objects.filter(language=language, parent__isnull=True, placeholder=placeholder).count()

    plugin_base = CMSPlugin(
        plugin_type=plugin_type,
        placeholder=placeholder,
        position=new_pos,
        language=language
    )
    plugin_base.insert_at(target, position=position, save=False)

    plugin = plugin_model(**data)
    plugin_base.set_base_attr(plugin)
    plugin.save()
    return plugin
Exemple #14
0
def add_plugin(placeholder,
               plugin_type,
               language,
               position='last-child',
               **data):
    """
    Taken from django-cms api (in newer versions)
    https://github.com/divio/django-cms/blob/b8633b42efcd137d96e1e3f42e004cb7595768fe/cms/api.py
    """
    assert isinstance(placeholder, Placeholder)
    plugin_model = plugin_type.model
    plugin_type = plugin_type.__name__
    plugin_base = CMSPlugin(plugin_type=plugin_type,
                            placeholder=placeholder,
                            position=1,
                            language=language)
    plugin_base.insert_at(None, position='last-child', commit=False)
    plugin = plugin_model(**data)
    plugin_base.set_base_attr(plugin)
    plugin.save()
    return plugin
Exemple #15
0
    def test_11_copy_textplugin(self):
        """
        Test that copying of textplugins replaces references to copied plugins
        """
        
        page = self.create_page()
        
        placeholder = page.placeholders.get(slot='body')
        
        plugin_base = CMSPlugin(
            plugin_type='TextPlugin',
            placeholder=placeholder, 
            position=1, 
            language=self.FIRST_LANG)
        plugin_base.insert_at(None, position='last-child', commit=False)
                
        plugin = Text(body='')
        plugin_base.set_base_attr(plugin)
        plugin.save()
        
        plugin_ref_1_base = CMSPlugin(
            plugin_type='TextPlugin',
            placeholder=placeholder, 
            position=1, 
            language=self.FIRST_LANG)
        plugin_ref_1_base.insert_at(plugin_base, position='last-child', commit=False)    
        
        plugin_ref_1 = Text(body='')
        plugin_ref_1_base.set_base_attr(plugin_ref_1)
        plugin_ref_1.save()
        
        plugin_ref_2_base = CMSPlugin(
            plugin_type='TextPlugin',
            placeholder=placeholder, 
            position=2, 
            language=self.FIRST_LANG)
        plugin_ref_2_base.insert_at(plugin_base, position='last-child', commit=False)    
        
        plugin_ref_2 = Text(body='')
        plugin_ref_2_base.set_base_attr(plugin_ref_2)

        plugin_ref_2.save()
        
        plugin.body = plugin_tags_to_admin_html(' {{ plugin_object %s }} {{ plugin_object %s }} ' % (str(plugin_ref_1.pk), str(plugin_ref_2.pk)))
        plugin.save()
        self.assertEquals(plugin.pk, 1)
        page_data = self.get_new_page_data()

        #create 2nd language page
        page_data.update({
            'language': self.SECOND_LANG,
            'title': "%s %s" % (page.get_title(), self.SECOND_LANG),
        })
        response = self.client.post(URL_CMS_PAGE_CHANGE % page.pk + "?language=%s" % self.SECOND_LANG, page_data)
        self.assertRedirects(response, URL_CMS_PAGE)
        
        self.assertEquals(CMSPlugin.objects.filter(language=self.FIRST_LANG).count(), 3)
        self.assertEquals(CMSPlugin.objects.filter(language=self.SECOND_LANG).count(), 0)
        self.assertEquals(CMSPlugin.objects.count(), 3)
        self.assertEquals(Page.objects.all().count(), 1)
        
        copy_data = {
            'placeholder': placeholder.pk,
            'language': self.SECOND_LANG,
            'copy_from': self.FIRST_LANG,
        }
        response = self.client.post(URL_CMS_PAGE + "copy-plugins/", copy_data)
        self.assertEquals(response.status_code, 200)
        self.assertEqual(response.content.count('<li '), 3)
        # assert copy success
        self.assertEquals(CMSPlugin.objects.filter(language=self.FIRST_LANG).count(), 3)
        self.assertEquals(CMSPlugin.objects.filter(language=self.SECOND_LANG).count(), 3)
        self.assertEquals(CMSPlugin.objects.count(), 6)

        new_plugin = Text.objects.get(pk=6)
        self.assertEquals(plugin_tags_to_id_list(new_plugin.body), [u'4', u'5'])
    def add_plugin(self, request):
        """
        POST request should have the following data:

        - placeholder_id
        - plugin_type
        - plugin_language
        - plugin_parent (optional)
        """
        plugin_type = request.POST['plugin_type']

        placeholder_id = request.POST.get('placeholder_id', None)
        parent_id = request.POST.get('parent_id', None)
        if parent_id:
            warnings.warn("parent_id is deprecated and will be removed in 3.0.1, use plugin_parent instead",
                          DeprecationWarning)
        if not parent_id:
            parent_id = request.POST.get('plugin_parent', None)
        placeholder = get_object_or_404(Placeholder, pk=placeholder_id)
        if not self.has_add_plugin_permission(request, placeholder, plugin_type):
            return HttpResponseForbidden(_('You do not have permission to add a plugin'))
        parent = None
        language = request.POST.get('plugin_language') or get_language_from_request(request)
        try:
            has_reached_plugin_limit(placeholder, plugin_type, language,
                                     template=self.get_placeholder_template(request, placeholder))
        except PluginLimitReached as er:
            return HttpResponseBadRequest(er)
            # page add-plugin
        if not parent_id:

            position = request.POST.get('plugin_order',
                                        CMSPlugin.objects.filter(language=language, placeholder=placeholder).count())
        # in-plugin add-plugin
        else:
            parent = get_object_or_404(CMSPlugin, pk=parent_id)
            placeholder = parent.placeholder
            position = request.POST.get('plugin_order',
                                        CMSPlugin.objects.filter(language=language, parent=parent).count())
            # placeholder (non-page) add-plugin

        # Sanity check to make sure we're not getting bogus values from JavaScript:
        if settings.USE_I18N:
            if not language or not language in [lang[0] for lang in settings.LANGUAGES]:
                return HttpResponseBadRequest(_("Language must be set to a supported language!"))
            if parent and parent.language != language:
                return HttpResponseBadRequest(_("Parent plugin language must be same as language!"))
        else:
            language = settings.LANGUAGE_CODE
        plugin = CMSPlugin(language=language, plugin_type=plugin_type, position=position, placeholder=placeholder)

        if parent:
            plugin.position = CMSPlugin.objects.filter(parent=parent).count()
            plugin.insert_at(parent, position='last-child', save=False)
        plugin.save()
        self.post_add_plugin(request, placeholder, plugin)
        response = {
            'url': force_unicode(
                reverse("admin:%s_%s_edit_plugin" % (self.model._meta.app_label, self.model._meta.module_name),
                        args=[plugin.pk])),
            'breadcrumb': plugin.get_breadcrumb(),
        }
        return HttpResponse(simplejson.dumps(response), content_type='application/json')
def convert(request, slug = "dryrun"):
    # this dictionary store the information for the conversions
    execute=slug
    models_dictionary = {
        "messages": {},                             # a general set of messages for the user
        "modules":  {
            "news_and_events.models": {             # each module containing the models must be represented, like this
                "application": "News & Events",     # this is the human-friendly name of the module
                "models": {                         # a dictionary with each model in that module
                    "NewsArticle": {                # the actual name of the class
                        "fields": [                 # a list of the fields we're working on
                            {                       # a dictionary for each field
                                "old_field": "content",
                                "new_field": "body",                
                                "slot": "body",
                                },
                            ],
                        "model": "News articles",   # the human-friendly name of the model
                        "actions": {},              # an empty dictionary where we we store the results
                        },
                    "Event": {                      # a second model in that module
                        "fields": [                 
                            {                       
                                "old_field": "content",
                                "new_field": "body",                
                                "slot": "body",
                                },
                            ],
                        "model": "Events",
                        "actions": {},
                        },
                    },
                },
            "vacancies_and_studentships.models": {  # and a second module
                "application": "Vacancies & Studentships",
                "models": {
                    "Vacancy": {
                        "fields": [                 
                            {                       
                                "old_field": "description",
                                "new_field": "body",                
                                "slot": "body",
                                },
                            ],
                        "model": "Vacancies",
                        "actions": {},
                        },
                    "Studentship": {
                        "fields": [                 
                            {                       
                                "old_field": "description",
                                "new_field": "body",                
                                "slot": "body",
                                },
                                ],
                        "model": "Studentships",
                        "actions": {},
                        },
                    },
                },
            "publications.models": {                
                "application": "Publications",
                "models": {
                    "Researcher": {
                        "fields": [                 
                            {                       
                                "old_field": "research_synopsis",
                                "new_field": "synopsis_of_research",                
                                "slot": "body",
                                },
                            {                       
                                "old_field": "research_description",
                                "new_field": "description_of_research",                
                                "slot": "body",
                                },
                            ],
                        "model": "Researcher",
                        "actions": {},
                        },
                    },
                },
            },
        }

    # loop over the modules
    for module, module_values in models_dictionary["modules"].items():

        # loop over the models in the module
        for model, model_values in module_values["models"].items():
            
            # mmodel is the human-readable name of the model, used for the report summary
            mmodel = models_dictionary["modules"][module]["models"][model]["model"]
            models_dictionary["messages"][mmodel]={}

            # import the model
            actual_model = getattr(__import__(module, globals(), locals(), module_values["models"], -1), model)
                                            
            # loop over the fields that need converting
            for field in model_values["fields"]:
                print field

                
                old_field = field["old_field"]
                new_field = field["new_field"]
                slot = field["slot"]

                # create a summary report for this field
                models_dictionary["messages"][mmodel][old_field]={}

                try:
                    getattr(actual_model, new_field)
                except AttributeError:
                    message = "field " + new_field + " is missing - check the model and try agin"
                    models_dictionary["messages"][mmodel][old_field]["Error"]=message
                    continue
                    
                junk_content = []   # a record of those items with nothing but <br /> in them
                moved_items =[]     # a record of the items we migrated to placeholders

                # loop over each item in the class
                for item in actual_model.objects.all():

                    old_field_content = getattr(item, old_field)  # the old field we want to convert

                    # first get rid of junk content (change "<br />" to "")
                    if old_field_content == "<br />":
                        old_field_content = ""
                        setattr(item, old_field, "") # item.content = ""
                        if execute == "convert":
                            item.save()
                    
                    # now the serious business of converting the fields
            
                    # if the item lacks a placeholder, create the placeholder and the reference to it
                    if old_field_content and not getattr(item, new_field, None):

                        # check to see if it's worth converting
                        if len(old_field_content) > 60:

                            # create the placeholder
                            placeholder=Placeholder(slot=slot)
                            if execute == "convert":
                                placeholder.save()
        
                            # refer to the placeholder from the item
                            setattr(item, new_field, placeholder)
        
                            # I copied this from one of the test files
                            plugin_base = CMSPlugin(
                                plugin_type='TextPlugin',
                                placeholder=placeholder, 
                                position=1, 
                                language=settings.LANGUAGES[0][0]) # we assume the original field was in the first language
                            plugin_base.insert_at(None, position='last-child', commit=False)
        
                            # create a text plugin
                            plugin = Text(body='')
                            plugin_base.set_base_attr(plugin)
                            plugin.body = getattr(item, old_field)
                            if execute == "convert":
                                plugin.save()
        
                            # set the old field to ""
                            setattr(item, old_field, "")
                            if execute == "convert":
                                item.save()
                                item.status = "Converted to placeholder"
                            else:
                                item.status = "Unconverted"
                                        
                        else:
                            print "too short", old_field_content
                            # this item is so short it must be junk
                            if execute == "convert":
                                setattr(item, old_field, "")
                                item.status = "Junk field - too short; was deleted instead of converted:" + old_field_content
                                item.save()
                            else:    
                                item.status = "Junk field - too short; will be deleted instead of converted:" + old_field_content
                            # make a note that this was a junk item
                            junk_content.append(item)
                                # make a note that we moved this item

                        moved_items.append(item)    
 
                # information about junk content items
                if execute == "convert":
                    message = " ".join((str(len(junk_content)), "junk items not converted items"))
                else:
                    message = " ".join((str(len(junk_content)), "junk items found"))                    

                models_dictionary["messages"][mmodel][old_field]["Junk fields"]=message

                # information about items that have been/need to be converted
                if execute == "convert":
                    message = str(len(moved_items)) + " items were converted to placeholder " + new_field
                else:
                    message = str(len(moved_items)) + " items need to be converted to placeholder " + new_field
            
                models_dictionary["messages"][mmodel][old_field]["Conversions"]=message
            
                # list every item that was copied for the full report
                if execute == "convert":
                    action = "Fields that were copied"
                else:
                    action = "Fields to be copied"
                    
                models_dictionary["modules"][module]["models"][model]["actions"][action]=moved_items
                

    return shortcuts.render_to_response(
        "housekeeping/convert_to_placeholders.html", {
            "execute": execute,
            "converted": models_dictionary,
            },
        RequestContext(request),
        )
    def add_plugin(self, request):
        """
        POST request should have the following data:

        - placeholder_id
        - plugin_type
        - plugin_language
        - plugin_parent (optional)
        """
        plugin_type = request.POST['plugin_type']

        placeholder_id = request.POST.get('placeholder_id', None)
        parent_id = request.POST.get('parent_id', None)
        if parent_id:
            warnings.warn("parent_id is deprecated and will be removed in 3.1, use plugin_parent instead",
                          DeprecationWarning)
        if not parent_id:
            parent_id = request.POST.get('plugin_parent', None)
        placeholder = get_object_or_404(Placeholder, pk=placeholder_id)
        if not self.has_add_plugin_permission(request, placeholder, plugin_type):
            return HttpResponseForbidden(force_unicode(_('You do not have permission to add a plugin')))
        parent = None
        language = request.POST.get('plugin_language') or get_language_from_request(request)
        try:
            has_reached_plugin_limit(placeholder, plugin_type, language,
                                     template=self.get_placeholder_template(request, placeholder))
        except PluginLimitReached as er:
            return HttpResponseBadRequest(er)
            # page add-plugin
        if not parent_id:

            position = request.POST.get('plugin_order',
                                        CMSPlugin.objects.filter(language=language, placeholder=placeholder).count())
        # in-plugin add-plugin
        else:
            parent = get_object_or_404(CMSPlugin, pk=parent_id)
            placeholder = parent.placeholder
            position = request.POST.get('plugin_order',
                                        CMSPlugin.objects.filter(language=language, parent=parent).count())
            # placeholder (non-page) add-plugin

        # Sanity check to make sure we're not getting bogus values from JavaScript:
        if settings.USE_I18N:
            if not language or not language in [lang[0] for lang in settings.LANGUAGES]:
                return HttpResponseBadRequest(force_unicode(_("Language must be set to a supported language!")))
            if parent and parent.language != language:
                return HttpResponseBadRequest(force_unicode(_("Parent plugin language must be same as language!")))
        else:
            language = settings.LANGUAGE_CODE
        plugin = CMSPlugin(language=language, plugin_type=plugin_type, position=position, placeholder=placeholder)

        if parent:
            plugin.position = CMSPlugin.objects.filter(parent=parent).count()
            plugin.insert_at(parent, position='last-child', save=False)
        plugin.save()
        self.post_add_plugin(request, placeholder, plugin)
        response = {
            'url': force_unicode(
                reverse("admin:%s_%s_edit_plugin" % (self.model._meta.app_label, self.model._meta.module_name),
                        args=[plugin.pk])),
            'delete': force_unicode(
                reverse("admin:%s_%s_delete_plugin" % (self.model._meta.app_label, self.model._meta.module_name),
                        args=[plugin.pk])),
            'breadcrumb': plugin.get_breadcrumb(),
        }
        return HttpResponse(json.dumps(response), content_type='application/json')