Using WysiwygFieldWidget in a z3c.form form - forms

I'm creating a form with z3c.form and for a textarea, I would like to have a wysiwyg interface.
So I use plone.directives.form to handle that.
In my interfaces.py :
from zope import schema
from plone.directives import form
from plone.app.z3cform.wysiwyg import WysiwygFieldWidget
from zope.i18nmessageid import MessageFactory
_ = MessageFactory('BSWMinisite')
class IMinisiteProperties(form.Schema):
""" """
form.widget(edito=WysiwygFieldWidget)
edito = schema.Text(title = u"Edito",
required=False)
In my content.py :
from plone.directives import form
from z3c.form import button
from Products.CMFPlone import PloneMessageFactory as plMF
from plone.z3cform.layout import wrap_form
from Products.CMFCore.utils import getToolByName
from Products.BSWMinisite.interfaces import IMinisiteProperties
class MinisitePropertiesForm(form.SchemaForm):
""" """
schema = IMinisiteProperties
ignoreContext = True # don't use context to get widget data
#button.buttonAndHandler(plMF('label_save', default=u'Save'), name='apply')
def handleApply(self, action):
""" stuff """
#button.buttonAndHandler(plMF('label_cancel', default=u'Cancel'),
name='cancel')
def handleCancel( self, action):
self.request.RESPONSE.redirect( self.context.absolute_url() )
MinisitePropertiesView = wrap_form(MinisitePropertiesForm)
And in the configure.zcml I have :
<include package="plone.directives.form" file="meta.zcml" />
<include package="plone.directives.form" />
<browser:page
for="*"
name="minisite_properties"
class=".browser.content.MinisitePropertiesView"
permission="cmf.ModifyPortalContent"
/>
When I go to ##minisite_properties I see my field, but no wysiwyg.
Do you hnow where I missed something ?

Below is my sample code for Dexterity content schema using Dexterity 1.1 pindowns (see Dexterity manual, installation part)
from five import grok
from zope import schema
from plone.directives import form, dexterity
from plone.app.z3cform.wysiwyg import WysiwygFieldWidget
class ICourseInfoContent(form.Schema):
"""
Content page for CourseInfo folders
"""
# Autofilled by course id
title = schema.TextLine(title=u"Title", required=True, default=u"")
# -*- Your Zope schema definitions here ... -*-
form.widget(body=WysiwygFieldWidget)
body = schema.Text(title=u"Body (top)")

So, the problem was I didn't have the correct version of dexterity, and my package wasn't grok'ed correctly.
In the buildout, to pin the correct dexterity :
extends =
base.cfg
versions.cfg
http://good-py.appspot.com/release/dexterity/1.1?plone=4.1.3
In the main configure.zcml :
<configure xmlns="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser"
xmlns:five="http://namespaces.zope.org/five"
xmlns:i18n="http://namespaces.zope.org/i18n"
xmlns:grok="http://namespaces.zope.org/grok"
i18n_domain="BSWMinisite">
<!-- Grok the package to initialise schema interfaces and content classes -->
<grok:grok package="." />
<browser:page
for="*"
name="minisite_properties"
class=".browser.content.MinisitePropertiesView"
permission="cmf.ModifyPortalContent"
/>
...
And then in my content.py :
from five import grok
class MinisitePropertiesForm(form.SchemaForm):
""" """
grok.context(IMinisiteProperties)
schema = IMinisiteProperties

Related

`basename` argument not specified

i created a new project by django restframework
the project name = frame
th project_app name= framework
fram.urls.py:
"""frame URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/3.1/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path,re_path
from django.conf.urls import include,url
from framework.views import myviewset
from rest_framework import routers
router = routers.DefaultRouter();
router.register('task', myviewset)
urlpatterns = [
path('admin/', admin.site.urls),
re_path(r'', include(router.urls)),
]
framework models.py:
from django.db import models
# Create your models here.
class Task (models.Model):
task_name=models.CharField(max_length='200')
task_desc=models.CharField(max_length='200')
date_created=models.DateTimeField(auto_now=True)
serializer.py
from .models import Task
from rest_framework import serializers
class TaskSerializers(serializers.ModelSerializer):
class Meta:
model = Task
fields = ('id', 'task_name', 'task_desc')
views.py:
from django.shortcuts import render
from .serializer import TaskSerializers
from rest_framework import viewsets
from .models import Task
# Create your views here.
class myviewset(viewsets.ModelViewSet):
query = Task.objects.all().order_by('date_created')
serializer_class = TaskSerializers
admin.py:
from django.contrib import admin
from .models import Task
admin.site.register(Task)
# Register your models here.
setting.py:
INSTALLED_APPS = [
'framework',
'rest_framework',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
when i run th server in CMD
this error comes :
AssertionError: basename argument not specified, and could not automatically determine the name from the viewset, as it does not have a .queryset attribute.
You should specify queryset attribute instead of query in your viewset. For example (class name case changed to comply PEP8):
class MyViewSet(viewsets.ModelViewSet):
queryset = Task.objects.all().order_by('date_created')
serializer_class = TaskSerializers
Docs: https://www.django-rest-framework.org/api-guide/viewsets/#modelviewset
Also I recommend always specify basename when you register your viewsets. Like this:
router = routers.DefaultRouter();
router.register('task', MyViewSet, basename='tasks')
https://www.django-rest-framework.org/api-guide/routers/#usage
basename - The base to use for the URL names that are created. If unset the basename will be automatically generated based on the queryset attribute of the viewset, if it has one. Note that if the viewset does not include a queryset attribute then you must set basename when registering the viewset.

How to fix the field error issue in django?

I try to navigate from list page to detail page, when i tried with the below code. I got error stating that field error. For that I've tried with adding a empty Slug field in models, it shows an page not found error.
#urls.py
from django.urls import path
from .views import (TaskListView,TaskDetailView)
app_name = 'Tasks'
urlpatterns = [
path('', TaskListView.as_view(), name='list'),
path('<slug:slug>/', TaskDetailView.as_view(), name='detail'),
]
#views.py
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
from django.views.generic import ListView, DetailView, View
from .models import Taskmanager
def home(request):
return render(request, 'home.html')
class TaskListView(ListView):
template_name = 'Tasks.html'
model = Taskmanager
context_object_name = 'data'
class TaskDetailView(DetailView):
template_name = 'detail.html'
model = Taskmanager
context_object_name = 'data'
#models.py
from django.db import models
from django.urls import reverse
# Create your models here.
week_number = (("week01", "week01"),
("week02", "week02"),
("week03", "week03"),
("week04", "week04"),
("week05", "week05"),
("week06", "week06"),
("week07", "week07"),
("week08", "week08"),
("week09", "week09"),
("week10", "week10"),
("week11", "week11"),
("week12", "week12"),
("week13", "week13"),
("week14", "week14"),
("week15", "week15"),
("week16", "week16"),
("week17", "week17"),
("week18", "week18"),
("week19", "week19"),
("week20", "week20"),
("week21", "week21"),
("week22", "week22"),
("week23", "week23"),
("week24", "week24"),
("week25", "week25"),
("week26", "week26"),
("week27", "week27"),
("week28", "week28"),
("week29", "week29"),
("week30", "week30"),
("week31", "week31"),
("week32", "week32"),
("week33", "week33"),
("week34", "week34"),
("week35", "week35"),
("week36", "week36"),
("week37", "week37"),
("week38", "week38"),
("week39", "week39"),
("week40", "week40"),
("week41", "week41"),
("week42", "week42"),
("week43", "week43"),
("week44", "week44"),
("week45", "week45"),
("week46", "week46"),
("week47", "week47"),
("week48", "week48"),
("week49", "week49"),
("week50", "week50"),
("week51", "week51"),
("week52", "week52"),
("week53", "week53"),
)
class Taskmanager(models.Model):
CurrentSprint = models.CharField(max_length=10, default="week01",
choices=week_number)
todaydate = models.DateField()
taskname = models.SlugField(max_length=200)
testrun = models.URLField(max_length=300)
comments = models.CharField(max_length=300)
assignedto = models.EmailField(max_length=70)
def __str__(self):
return self.taskname
def get_absolute_url(self):
return reverse('Tasks:detail', kwargs={'slug': self.taskname})
#Tasks.html
<a href="{% url 'Tasks:detail' slug='detail'%}"> {{Taskmanager.todaydate}}
</a>
I need an output when I click the link, it needs to navigate to the details page where the details of the task needs to be displayed.
try adding this
#views.py
class TaskDetailView(DetailView):
...
def get_object(self):
instance = get_object_or_404(Taskmanager, slug=self.kwargs['slug'])
return instance
#models.py
django.db.models.signals import pre_save
class Taskmanager(models.Model):
...
taskname = models.CharField(max_length=200)
slug = models.SlugField(max_length=100)
...
def pre_save_Taskmanager_receiver(instance, *args, **kwargs):
if not instance.slug:
instance.slug = instance.taskname
pre_save.connect(pre_save_Taskmanager_receiver, sender= Taskmanager)
# task.html
{{ data.todaydate }}

Alembic autogenerate does not generate upgrade script

I am using sqlalchemy and postgressql in Flask application. The migration tool that I am using is alembic=0.6.3.
if I type alembic current it shows me:
Current revision for postgres://localhost/myDb: None
which is correct database connection. But when I run alembic revision --autogenerate -m 'Add user table' it generates the default alembic template without any sql commands in it. Like:
"""Add user table
Revision ID: 59b6d3503442
Revises: None
Create Date: 2015-04-06 13:42:24.540005
"""
# revision identifiers, used by Alembic.
revision = '59b6d3503442'
down_revision = None
from alembic import op
import sqlalchemy as sa
def upgrade():
### commands auto generated by Alembic - please adjust! ###
pass
### end Alembic commands ###
def downgrade():
### commands auto generated by Alembic - please adjust! ###
pass
### end Alembic commands ###
I couldn't find any proper solution in SO.
Here is my env.py:
from __future__ import with_statement
from logging.config import fileConfig
import os
import sys
import warnings
from alembic import context
from sqlalchemy import create_engine, pool
from sqlalchemy.exc import SAWarning
ROOT = os.path.abspath(
os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)
)
sys.path.append(ROOT)
from myApp import Application
from myApp.extensions import db
# Don't raise exception on `SAWarning`s. For example, if Alembic does
# not recognize some column types when autogenerating migrations,
# Alembic would otherwise crash with SAWarning.
warnings.simplefilter('ignore', SAWarning)
app = Application()
# this is the Alembic Config object, which provides
# access to the values within the .ini file in use.
config = context.config
# Interpret the config file for Python logging.
# This line sets up loggers basically.
fileConfig(config.config_file_name)
target_metadata = db.metadata
def run_migrations_offline():
"""Run migrations in 'offline' mode.
This configures the context with just a URL
and not an Engine, though an Engine is acceptable
here as well. By skipping the Engine creation
we don't even need a DBAPI to be available.
Calls to context.execute() here emit the given string to the
script output.
"""
url = app.config['SQLALCHEMY_DATABASE_URI']
context.configure(url=url)
with context.begin_transaction():
context.run_migrations()
def run_migrations_online():
"""Run migrations in 'online' mode.
In this scenario we need to create an Engine
and associate a connection with the context.
"""
url = app.config['SQLALCHEMY_DATABASE_URI']
engine = create_engine(url, poolclass=pool.NullPool)
connection = engine.connect()
context.configure(
connection=connection,
target_metadata=target_metadata
)
try:
with context.begin_transaction():
context.run_migrations()
finally:
connection.close()
if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()
and this is my alembic.ini:
# A generic, single database configuration.
[alembic]
# path to migration scripts
script_location = myApp/migrations
# template used to generate migration files
# file_template = %%(rev)s_%%(slug)s
# Logging configuration
[loggers]
keys = root,sqlalchemy,alembic
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = WARN
handlers = console
qualname =
[logger_sqlalchemy]
level = WARN
handlers =
qualname = sqlalchemy.engine
[logger_alembic]
level = INFO
handlers =
qualname = alembic
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic
[formatter_generic]
format = %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S
Addition files for more information
This is the extensions.py file from where I import db for metadata:
from flask.ext.sqlalchemy import SQLAlchemy
from raven.contrib.flask import Sentry
from sqlalchemy_utils import force_instant_defaults
db = SQLAlchemy()
sentry = Sentry()
force_instant_defaults()
and this the model user.py file:
#
-*- coding: utf-8 -*-
from datetime import datetime
from flask.ext.login import UserMixin
from sqlalchemy_utils.types.password import PasswordType
from ..extensions import db
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(
db.Unicode(255),
nullable=False
)
surname = db.Column(
db.Unicode(255),
nullable=False
)
email = db.Column(
db.Unicode(255),
nullable=False,
unique=True
)
password = db.Column(
PasswordType(128, schemes=['sha512_crypt']),
nullable=False
)
created_at = db.Column(
db.DateTime,
nullable=False,
default=datetime.utcnow
)
def is_active(self):
return True
def __repr__(self):
return '<{cls} email={email!r}>'.format(
cls=self.__class__.__name__,
email=self.email,
)
def __str__(self):
return unicode(self).encode('utf8')
def __unicode__(self):
return self.email

When does Play load application.conf?

Is application.conf already loaded when the code in Global.scala is executed? I'm asking because I've tried to read some configuration items from Global.scala and I always get None. Is there any workaround?
In Java it's available beforeStart(Application app) already
public class Global extends GlobalSettings {
public void beforeStart(Application app) {
String secret = Play.application().configuration().getString("application.secret");
play.Logger.debug("Before start secret is: " + secret);
super.beforeStart(app);
}
}
As it's required to i.e. configuring DB connection, most probably Scala works the same way (can't check)
Here below is how to read the configuration just after it has been loaded but before the application actually starts:
import play.api.{Configuration, Mode}
import play.api.GlobalSettings
import java.io.File
import utils.apidocs.InfoHelper
object Global extends GlobalSettings {
override def onLoadConfig(
config: Configuration,
path: File, classloader:
ClassLoader,
mode: Mode.Mode): Configuration = {
InfoHelper.loadApiInfo(config)
config
}
}
And here below, just for your info, is the source of InfoHelper.loadApiInfo – it just loads API info for Swagger UI:
package utils.apidocs
import play.api.Configuration
import com.wordnik.swagger.config._
import com.wordnik.swagger.model._
object InfoHelper {
def loadApiInfo(config: Configuration) = {
config.getString("application.name").map { appName =>
config.getString("application.domain").map { appDomain =>
config.getString("application.emails.apiteam").map { contact =>
val apiInfo = ApiInfo(
title = s"$appName API",
description = s"""
Fantastic application that makes you smile. You can find our
more about $appName at $appDomain.
""",
termsOfServiceUrl = s"//$appDomain/terms",
contact = contact,
license = s"$appName Subscription and Services Agreement",
licenseUrl = s"//$appDomain/license"
)
ConfigFactory.config.info = Some(apiInfo)
}}}
}
}
I hope it helps.

scala nodes in html-Strings

my target is to analyze an "html - String". In the end i'd like
to extract the Textnodes and datanodes of a string and store them in
different lists.
With my first appoach I tried to go through a "html - String" recursively.
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import java.util.Iterator
import org.jsoup.nodes
import org.jsoup.nodes.Node
object TextAnalyzer {
def processNode(node: Node) {
if (node.isInstanceOf[TextNode]) println(node.toString())
node.childNodes() foreach processNode
}
def main(args: Array[String]) {
val myHtml = "<html> <head> <title>Welcome</title> </head> <body> <div> <p>Foo</p> </div> </body></html>";
val doc = Jsoup.parse(myHtml);
processNode(doc);
}
}
It ends with the following errow message:
scalac MyModule.scala
MyModule.scala:23: error: value childs is not a member of org.jsoup.nodes.Node
node.childNodes() foreach processNode
^
one error found
>
Can you get me startet in order to be able to
get the data- and textnodes of a textstring ?
... recursively ?
Thanks in advance for help?
greets
Ansgar
I don't really understand your question - but the following compiles. Is it what you were aiming for?
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import java.util.Iterator
import org.jsoup.nodes._
import scala.collection.JavaConversions._
object TextAnalyzer extends App {
def processNode(node: Node) {
if (node.isInstanceOf[TextNode]) println(node.toString())
node.childNodes() foreach processNode
}
val myHtml = "<html> <head> <title>Welcome</title> </head> <body> <div> <p>Foo</p> </div> </body></html>";
val doc = Jsoup.parse(myHtml);
processNode(doc);
}