DjangoCMS: How to check for uniqueness of a field in a plugin model (CMSPlugin)? - django-cms

I build a djangoCMS plugin which contain a slug. I want this slug to be unique.
Since djangoCMS store page content in draft and public versions (with a copy of plugins data), I can't do it at database level because it is normal two have at two plugins (draft and public versions) with the same slug.
I'm pretty sure there is an idiom for this but can't find it.
I've tried to make a check in the clean method of the model, but I can't access instance.placeholder which is None when being in clean method…
class MyPlugin(CMSPlugin):
slug = models.SlugField(
verbose_name=_("Slug"),
db_index=True,
max_length=255,
)
Any idea ?

I think I've found a solution by excluding objects where page is not draft:
def clean(self, *args, **kwargs):
sames_slug = MyPlugin.objects.filter(slug=self.slug).exclude(
placeholder__page__publisher_is_draft=False
)
if self.pk:
sames_slug = sames_slug.exclude(pk=self.pk)
if sames_slug.exists():
raise ValidationError(
{"slug": "There is already one with the same slug"}
)

Related

CategoryManyToManyField tuns to emty QuerySet in non edit mode

I write a new plugin for aldryn_newsblog application. I want to list articles by categories. The plugin takes the list of categories using CategoryManyToManyField.
The plugin displays the articles having requested categories only in edit mode. As soon as I publish page with newly added plugin it displays none of the articles. I checked that self.categories.all() becomes empty.
Why it is happening?
This is for;
aldryn-newsblog2.1.1
Django==1.11.17
django-cms==3.5.3
It acts the same on local django development server and on remote apache
class NewsBlogCategoryPlugin(PluginEditModeMixin, AdjustableCacheModelMixin, NewsBlogCMSPlugin):
....
categories = CategoryManyToManyField('aldryn_categories.Category', verbose_name=_('categories'), blank=True)
....
def get_articles(self, request):
print (self.categories.all())
queryset = Article.objects
main_qs = queryset.all().filter(categories =
self.categories.all())
return main_qs
I believe that the issue is this:
when your page is published, the plugin instance is copied
in the published version of the page, there is now a new plugin instance
this new plugin instance does not have the relations to the Categories that the original did
You need to ensure that when a plugin is copied, so are its relations.
See handling relations in the django CMS documentation.
Thank you #Daniele. I just have added following the handling-relations
def copy_relations(self, oldinstance):
self.categories = oldinstance.categories.all()
And now it works

Drupal 8: Mismatched entity and/or field definitions

While trying to understand why my view is not displaying, I noticed the following error in the log:
I do not think it is possible to delete the URL alias from Taxonomy terms. At least I cannot find how to do this.
I have, however gone through ALL of my taxonomy terms and removed the value for this field.
I have also done the following with Pathauto:
Also, I have checked the report located at admin/reports/fields and can confirm that there are no entities that use a field called URL alias.
I have gone through each content item and ensured that they have the following setting (anyone know how to do this in bulk?). But still the error remains.
Anyone know then how I can fix this strange error?
Im not entirely sure what this command does, but it fixed the error:
drush updb --entity-updates
Since https://www.drupal.org/node/2554097, the magic in Drupal core that took care of updating entity definitions is gone. drush updb --entiy-updates is an alternative to this but it is not a silver bullet. Instead, it is safer to write database updates.
Taking the screenshot at the top as an example, here is a database update that would delete those two field definitions:
/**
* Fix taxonomy and node field definitions.
*
*/
function mymodule_update_8101() {
$manager = \Drupal::entityDefinitionUpdateManager();
if ($field = $manager->getFieldStorageDefinition('alias', 'node')) {
$manager->uninstallFieldStorageDefinition($field);
}
if ($field = $manager->getFieldStorageDefinition('alias', 'term')) {
$manager->uninstallFieldStorageDefinition($field);
}
}
Have a look at the rest of the available methods at https://www.drupal.org/node/2554097 in order to write database updates for each scenario.
use the entity_update module or the devel_entity_updates module

I need to edit a existing form in plone

I've never used plone but I need to edit a form to add a field. I've already looked everywhere but I can't find anything to do this, is there portal_type?
It's a big problem we have on my company, last programmer ran away and left us with Plone :\
Thanks.
Look at your URL, find the Name View, the last Part of url, e.g /fileupload-form
Search with grep on the Commandline in your Productfolder to the Name, you can find a Browserview with the Name 'fileupload-form'
Look at the Definition in the zcml-File you can find the Classdefinition of View/Form
Search the Interface of Form, it could be defined like:
class IMyForm(form.Schema):
""" Define form fields """
name = schema.TextLine(
title=u"Your name",
)
add a new Field of Type NamedBlobFile or NamedFile, look in the Documentation Example

Drupal user permissions & odd content types

I have a permissions problem in Drupal. I want users to be able to create a certain node type, but there are two different paths I need to give them permissions for to let them do this. The type is content created by a module called isbn2node, and there are two ways to make content through it, each with different paths:
?=node/add/isbn2node-book
?=node/add/isbn2node_book/isbn2node
One has an underscore and the other one has a hyphen. The first path leads to a form that lets users enter information on a book manually; the second path lets them enter an ISBN, searches for it, and populates the form for them based on the results.
I've changed permissions in the People menu so they can add isbn2node-book content manually using the first path, but there isn't an option to let them use the second method. Aliasing the url so it didn't have node/add in the path didn't work either.
Creating a duplicate content type seems like an ugly solution to this; is there a more elegant way to let users access that second path?
A little code in a custom module using hook_node_access should do it.
$node is either a node object or the machine name of the content type on which to perform the access check (if the node is being created then the $node object is not available so it will be a string instead).
So this should do it:
function MY_MODULE_node_access($node, $op, $account) {
if ($op == 'create') {
$type = $node;
if($type == 'book' && $account->uid) return NODE_ACCESS_ALLOW;
}
}
I figured this out, and the issues I was having were specific to this content type. The ISBN2Node module requires users to have the Administer Nodes permission to use its lookup and bulk import features.
There is some extra code for the module's hook_permission and hook_menu sections submitted as a fix in the module's issues thread.

Why does my content object not show up in the portal_catalog?

I am trying to implement a basic Zope2 content type directly without using dexterity or Archetypes because I need this to be extremely lean.
from OFS.SimpleItem import SimpleItem
from Products.ZCatalog.CatalogPathAwareness import CatalogAware
from persistent.list import PersistentList
class Doculite(SimpleItem, CatalogAware):
""" implement our class """
meta_type = 'Doculite'
def __init__(self, id, title="No title", desc=''):
self.id = id
self.title = title
self.desc = desc
self.tags = PersistentList()
self.default_catalog = 'portal_catalog'
def add_tags(self, tags):
self.tags.extend(tags)
def Subject(self):
return self.tags
def indexObject(self):
self.reindex_object()
From an external method I am doing this:
def doit(self):
pc = self.portal_catalog
res1 = pc.searchResults()
o1 = self['doc1']
o1.add_tags(['test1', 'test2'])
o1.reindex_object()
res2 = pc.searchResults()
return 'Done'
I clear the catalog and run my external method. My object does not get into the catalog. But from the indexes tab, when I browse the Subject index, I can see my content item listed with the values. Both res1 and res2 and empty.
Why is my content item not showing up inside the searchResuts() of the catalog?
Plone is a full-fat content management system, if you're after something lean it's probably not the right choice (perhaps try Pyramid.)
For your content type to be a full part of a Plone site it has to fulfil a number of requirements across the Zope2, CMF and Plone layers. plone.app.content.item.Item is about the simplest base class you can get for a content item for a Plone site, though a simpler base class in itself will not really make instances of your content type any more 'lean' - an instance of a class in Python is basically just a dict and a pointer to it's class.
Most of the work on a page view will be rendering the various user interface features of a site. Rendering the schema based add/edit forms of frameworks like Archetypes and Dexterity is also relatively expensive.
I'd spend a little time profiling your application using one of the supported content type systems before putting time into building your own.
In order to see your objects in the "Catalog" tab of the portal_catalog your objects need to have a "getPhysicalPath()" method that returns a tuple representing their path (ex. ('','Plone','myobject')).
Also try to use this:
from Products.CMFCore.CMFCatalogAware import CMFCatalogAware
as base class.
You need to register your type with the catalog multiplexer. Look at the configuration in the zmi -> archetypes_tool.
I'm not sure, but you may also need a portal_type registration also...
Like Lawrence said though, you're better off just using one of the current content type frameworks if you want to be able to catalog your data with plone's portal catalog. If you can deal with a separate catalog, take a look at repoze.catalog.
Plone needs every content object to provide an "allowedRolesAndUsers" index to return the object in searchResults.
There is probably a zcml snippet that will enable this for my content type. But I was able to get things working by adding another method as follows:
def allowedRolesAndUsers(self):
return ['Manager', 'Authenticated', 'Anonymous']
CatalogAware will be removed in Zope 4 and then can't be used any more.
cf https://github.com/zopefoundation/Products.ZCatalog/issues/26

Resources