How do I make a boolean field required in a z3c.form? - forms

I'm using z3c.form to create a form in Plone 4.1.4. I need a boolean field which is required: the user must tick the box. (In my case, the user must agree to the terms and conditions.)
Using required=True for the field doesn't work: I can submit the form without checking the checkbox.
This is what my code looks like:
from five import grok
from plone.directives import form
from zope import schema
from z3c.form import button
from Products.CMFCore.interfaces import ISiteRoot
from Products.statusmessages.interfaces import IStatusMessage
class ITestSchema(form.Schema):
hasApprovedConditions = schema.Bool(
title=u'I agree to the Terms and Conditions.',
required=True,
)
class TestForm(form.SchemaForm):
grok.name('test-form')
grok.require('zope2.View')
grok.context(ISiteRoot)
schema = ITestSchema
ignoreContext = True
#button.buttonAndHandler(u'Send')
def handleApply(self, action):
data, errors = self.extractData()
if errors:
self.status = self.formErrorsMessage
return
IStatusMessage(self.request).addStatusMessage(u'Thanks', 'info')
self.request.response.redirect(self.context.absolute_url())
The form shows the checkbox and label, but there is no indication that the field is required and indeed it isn't: I can submit the form without ticking the checkbox.
I'm extending these known good sets:
http://dist.plone.org/release/4.1.4/versions.cfg
http://good-py.appspot.com/release/dexterity/1.2?plone=4.1.4
They pin z3c.form to version 2.5.1 but I also tried version 2.6.1.
What am I missing?

You should use a constraint like this:
def validateAccept(value):
if not value == True:
return False
return True
class ITestSchema(form.Schema):
hasApprovedConditions = schema.Bool(
title=u'I agree to the Terms and Conditions.',
required=True,
constraint=validateAccept,
)
More info:
http://plone.org/products/collective.examples.userdata

to respond to the "flaw" you note #Mark van Lent - just add a:
description=_(u'Required'),

Related

Open Web Components Testing / Lit - component not being rendered?

I'm trying to test my Lit components with #open-wc/testing. Lit has an example repo here, with this test:
https://github.com/lit/lit-element-starter-ts/blob/main/src/test/my-element_test.ts#L44
When I try to render my element like they do in their example, I get this error:
jtests/components/coding-editor.test.ts:
🚧 Browser logs:
HTMLElement: <coding-editor></coding-editor>
❌ renders
TypeError: Cannot read properties of null (reading 'querySelector')
at o.<anonymous> (jtests/components/coding-editor.test.ts:16:30)
My component works in the browser and uses the name "coding-editor". It's as if this test renderer has no idea that I'm using a custom component though. I don't know why shadowRoot is null in my case.
My code is roughly this:
import { CodingEditor } from '../../app/javascript/components/coding-editor';
import {expect, fixture} from '#open-wc/testing';
import {html} from 'lit/static-html.js';
it('renders', async () => {
const el = await fixture(html`
<coding-editor></coding-editor>
`) as CodingEditor;
console.log(el);
const text = el.shadowRoot!.querySelector('.table-constrainer');
// expect(text).to.not.be.null
});
How can I get my test to render this properly, with the shadowRoot populated?
This is likely due to TypeScript removing the CodingEditor import that's only used as a type so the side effect of defining the custom element is not happening.
You can either set the TS compiler option importsNotUsedAsValues to preserve (See https://www.typescriptlang.org/tsconfig/#importsNotUsedAsValues) or add another import line for the side-effect like
import '../../app/javascript/components/coding-editor';
Additional explanation here too: https://github.com/Microsoft/TypeScript/wiki/FAQ#why-are-imports-being-elided-in-my-emit
As a side-note, in the starter example you linked to, the imported class is used in assert.instanceOf as a value so it does not get elided by TypeScript.

How do I get UUID FIELD value in Django ModelFORM?

I am doing something fairly straightforward...I am creating a record with a unique identifier using the UUID field in my POSTRGRESQL database. It's working fine. I'm trying to use that value and do a compare when the user is updating records. However, even though the value is in the database, when I try to get it via a ModelFORM in my CLEAN it is showing up as NONE. I'm guessing there's a special way to get this value but I can't figure out what it is. I tried to use this as a reference....https://stackoverflow.com/questions/54914961/django-form-with-a-modelchoicefield-on-a-uuid-do-not-show-its-content-in-cleaned but I can't work it out.
My Model...
class Model(models.Model):
unique_identifier = models.UUIDField(primary_key=False, default=uuid.uuid4, editable=False)
My FORM...
class FORM(forms.ModelForm):
class Meta:
model = Model
def clean(self):
cleaned_data = super(UpdateSavedNewProcedureForm, self).clean()
unique_identifier = cleaned_data.get('unique_identifier')
print(unique_identifier)
When I print the unique_identifier it comes back as NONE even though I can see the value in the database. If I store the value as a CHARFIELD I can get the value...but I'm trying to avoid duplicating this field just for readability. I'm certain there's a special way to get this value but I'm stumped at the moment.
Thanks in advance for any thoughts.
My final answer thanks to #Willem Van Onsem
My Model...
class Model(models.Model):
unique_identifier = models.UUIDField(primary_key=False,
default=uuid.uuid4, editable=False)
My Form...
class FORM(forms.ModelForm):
class Meta:
model = Model
def clean(self):
cleaned_data = super(UpdateSavedNewProcedureForm, self).clean()
unique_identifier = self.instance.unique_identifier
If unique_identifier:
Do Something Cool.....

Is there a way to create a "Verify Element Text is Not" keyword?

I need to verify an element had been randomized from a fixed starting state. I already have a test step that verifies the fixed state is working that uses "Verify Element Text" is "inserttexthere".
So I need a way to verify that the text is not "inserttexthere" after I click the randomizing button.
Is there anyway to do this that wouldn't require too much programming knowledge? (I use katalon studio because I have limited tech knowledge)
or is there an if else statement I can use that would pass the step only if the text is different?
Background and other methods I do know of or tried:
I can create another verify text command and just accept it as an intended to fail step. However that's harder to be aware of, especially if the text doesnt change because the test step will pass and I have to remember thats bad.
The other commands that are available only cover if the element no longer has text or if the element is no longer visible/clickable. There is nothing that lets me verify an attribute as "!=" or "NOT"
This is how you need to create a custom keyword in Katalon: Click
Code:
class help_keyword_elemtnotPresent {
#Keyword
def isElemetNotPresent() {
WebUI.verifyElementNotPresent(findTestObject(‘someobject’, timeout, FailureHandling.OPTIONAL)
}
for : if/else
More example
Here's a short beginners' practical tutorial:
Create a keyword in Keywords (1) (right-click, new keyword).
Create a package (2) (right-click, new package) called examplePackage.
Create a new class called ExampleClass inside that package:
public class ExampleClass {
#Keyword
public static verifyElementTextIsNot(String text1, String text2){
assert text1 != text2
}
}
Example test case showing how you can call the above keyword (Keyword is Katalon's name for method):
import static com.kms.katalon.core.checkpoint.CheckpointFactory.findCheckpoint
import static com.kms.katalon.core.testcase.TestCaseFactory.findTestCase
import static com.kms.katalon.core.testdata.TestDataFactory.findTestData
import static com.kms.katalon.core.testobject.ObjectRepository.findTestObject
import static com.kms.katalon.core.testobject.ObjectRepository.findWindowsObject
import com.kms.katalon.core.checkpoint.Checkpoint as Checkpoint
import com.kms.katalon.core.cucumber.keyword.CucumberBuiltinKeywords as CucumberKW
import com.kms.katalon.core.mobile.keyword.MobileBuiltInKeywords as Mobile
import com.kms.katalon.core.model.FailureHandling as FailureHandling
import com.kms.katalon.core.testcase.TestCase as TestCase
import com.kms.katalon.core.testdata.TestData as TestData
import com.kms.katalon.core.testobject.TestObject as TestObject
import com.kms.katalon.core.webservice.keyword.WSBuiltInKeywords as WS
import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
import com.kms.katalon.core.windows.keyword.WindowsBuiltinKeywords as Windows
import internal.GlobalVariable as GlobalVariable
import examplePackage.ExampleClass
String someText = "It is a rainy day"
String someOtherText = "It is a sunny day"
ExampleClass.verifyElementTextIsNot(someText, someOtherText)

how to make a custom filter in flask admin

What am I doing wrong in this?? I am getting an exception thrown.
Exception: Invalid field : does not contains any columns.
I actually want to filter results from three different columns containing the cost of rooms.If any room satisfies a certain condition from the three rooms then it should appear on the list. That's why I want to make a custom filter.
Please help me. Thanks in advance.
from flask.ext.admin.babel import lazy_gettext
from flask.ext.admin.model import filters
class MyBaseFilter(filters.BaseFilter):
"""
Base SQLAlchemy filter.
"""
def __init__(self, column, name, options=None, data_type=None):
"""
Constructor.
:param column:
Model field
:param name:
Display name
:param options:
Fixed set of options
:param data_type:
Client data type
"""
super(MyBaseFilter, self).__init__(name, options, data_type)
self.column = column
class Views():
class HotelAdmin(ModelView):
class FilterCost(MyBaseFilter):
def apply(self, query, value):
return query.filter(self.column > value)
def operation(self):
return lazy_gettext('Cost')
column_labels = {'hotel_name':'Hotel Details'}
column_list = ('hotel_name','website')
column_searchable_list = ('city',)
column_filters = (FilterCost(Table.Hotel.deluxe_room,'Cost'),'state')
I did the following and it worked:
added:
from flask.ext.admin.contrib.sqla import filters
removed:
from flask.ext.admin.model import filters AND
class MyBaseFilter(filters.BaseFilter)
and then I inherited "filters.BaseSQLAFilter" in my filter class.
But still, How can I use "class MyBaseFilter(filters.BaseFilter)", It is still throwing an error

Django-Nonrel with Mongodb listfield

I am trying to implement manytomany field relation in django-nonrel on mongodb. It was suggessted at to:
Django-nonrel form field for ListField
Following the accepted answer
models.py
class MyClass(models.Model):
field = ListField(models.ForeignKey(AnotherClass))
i am not sure where the following goes, it has been tested in fields.py, widgets,py, models.py
class ModelListField(ListField):
def formfield(self, **kwargs):
return FormListField(**kwargs)
class ListFieldWidget(SelectMultiple):
pass
class FormListField(MultipleChoiceField):
"""
This is a custom form field that can display a ModelListField as a Multiple Select GUI element.
"""
widget = ListFieldWidget
def clean(self, value):
#TODO: clean your data in whatever way is correct in your case and return cleaned data instead of just the value
return value
admin.py
class MyClassAdmin(admin.ModelAdmin):
form = MyClassForm
def __init__(self, model, admin_site):
super(MyClassAdmin,self).__init__(model, admin_site)
admin.site.register(MyClass, MyClassAdmin)
The following Errors keep popping up:
If the middle custom class code is used in models.py
name 'SelectMultiple' is not defined
If custom class code is taken off models.py:
No form field implemented for <class 'djangotoolbox.fields.ListField'>
You just need to import SelectMultiple by the sound of it. You can put the code in any of those three files, fields.py would make sense.
Since it's pretty usual to have:
from django import forms
at the top of your file already, you probably just want to edit the code below to:
# you'll have to work out how to import the Mongo ListField for yourself :)
class ModelListField(ListField):
def formfield(self, **kwargs):
return FormListField(**kwargs)
class ListFieldWidget(forms.SelectMultiple):
pass
class FormListField(forms.MultipleChoiceField):
"""
This is a custom form field that can display a ModelListField as a Multiple Select GUI element.
"""
widget = ListFieldWidget
def clean(self, value):
#TODO: clean your data in whatever way is correct in your case and return cleaned data instead of just the value
return value
You probably also want to try and learn a bit more about how python works, how to import modules etc.