diff --git a/parameciofast/libraries/createforms.py b/parameciofast/libraries/createforms.py
new file mode 100644
index 0000000..db66d62
--- /dev/null
+++ b/parameciofast/libraries/createforms.py
@@ -0,0 +1,7 @@
+
+def create_form(pmodel, t):
+
+ model=dict(pmodel)
+
+ return t.load_template('modelform.phtml', model=dict(pmodel))
+
diff --git a/parameciofast/libraries/db/extrafields/datetimefield.py b/parameciofast/libraries/db/extrafields/datetimefield.py
index b33ac12..7a1b251 100644
--- a/parameciofast/libraries/db/extrafields/datetimefield.py
+++ b/parameciofast/libraries/db/extrafields/datetimefield.py
@@ -49,14 +49,14 @@ class DateTimeField(PhangoField):
elif not datetime.obtain_timestamp(value):
self.error=True
- self.txt_error=self.error_default+' '+value
+ self.txt_error=self.error_default+' '+str(value)
return '0000-00-00 00:00:00'
if value==False:
self.error=True
- self.txt_error=self.error_default+' '+value
+ self.txt_error=self.error_default+' '+str(value)
return '0000-00-00 00:00:00'
else:
diff --git a/parameciofast/libraries/db/extraforms/dateform.py b/parameciofast/libraries/db/extraforms/dateform.py
index 0c7cb32..b00cc22 100644
--- a/parameciofast/libraries/db/extraforms/dateform.py
+++ b/parameciofast/libraries/db/extraforms/dateform.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
from parameciofast.libraries.db.coreforms import BaseForm
-#from parameciofast.libraries.mtemplates import standard_t
+from parameciofast.libraries.mtemplates import standard_t
from parameciofast.libraries.datetime import format_timedata
class DateForm(BaseForm):
@@ -11,7 +11,7 @@ class DateForm(BaseForm):
super().__init__(name, value)
self.yes_time=False
- #self.t=standard_t
+ self.t=standard_t
def form(self):
diff --git a/parameciofast/libraries/formsutils.py b/parameciofast/libraries/formsutils.py
new file mode 100644
index 0000000..c2e6c1b
--- /dev/null
+++ b/parameciofast/libraries/formsutils.py
@@ -0,0 +1,272 @@
+#!/usr/bin/env python3
+
+"""
+Parameciofast is a series of wrappers for FastAPI, mako and others and construct a simple headless cms.
+
+Copyright (C) 2025 Antonio de la Rosa Caballero
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+"""
+
+from parameciofast.libraries.db import corefields
+from parameciofast.libraries.db.coreforms import PasswordForm
+from parameciofast.libraries.i18n import I18n
+from parameciofast.libraries.keyutils import create_key_encrypt
+#import sqlite3
+
+# For tests outing the web framework
+
+try:
+ from settings import config
+except:
+ class config:
+ pass
+
+"""
+framework='flask'
+
+if hasattr(config, 'framework'):
+ framework=config.framework
+
+if framework=='flask':
+ from flask import session, request, abort
+elif framework=='fastapi':
+ from parameciofast.libraries.sessions import get_session
+ pass
+"""
+
+# Need unittest
+"""Functions and classes for process forms"""
+
+def pass_values_to_form(post, arr_form, yes_error=True, pass_values=True):
+ """Function for pass a dict with form values for check using forms dict
+
+ Values dict and Forms dict need have the same key. A forms dict is maked of a serie of parameciofast.forms elements, used for check the value.
+
+ Args:
+ post (dict): Dict composed by a series of values. The keys need to be equal to keys of arr_form dict.
+ arr_form (dict): Dict composed by a series or forms objects. The keys need to be equal to keys of post dict.
+ yes_error (bool): Show errors in txt_error form variables.
+ pass_values (bool): Pass default values or values from post dict to arr_form dict items
+
+ Returns:
+ arr_form (dict): Return arr_form dict with checked values from post dict.
+
+ """
+
+ if pass_values:
+ def get_value(key):
+ return post[key]
+
+ else:
+ def get_value(key):
+ return arr_form[key].default_value
+
+ for key, value in arr_form.items():
+
+ post[key]=post.get(key, '')
+
+ #if arr_form[key].default_value=='':
+ arr_form[key].default_value=get_value(key)
+
+ if arr_form[key].field==None:
+ arr_form[key].field=corefields.CharField(key, 255, required=False)
+
+ # Recheck value if no set error field
+ if arr_form[key].field.error == None:
+ arr_form[key].field.check(post[key])
+
+ #arr_form[key].txt_error=""
+
+ if arr_form[key].required==True and arr_form[key].field.error==True and yes_error==True:
+ arr_form[key].txt_error=arr_form[key].field.txt_error
+
+ # Reset error on field.
+
+ arr_form[key].field.error=None
+
+ return arr_form
+
+class CheckForm():
+ """Simple class for make similar check to pass_values_to_form. More simple.
+ """
+
+ def __init__(self):
+
+ self.error=0
+
+ def check(self, post, arr_form):
+ """Simple method for pass a dict with form values for check using forms dict
+
+ Values dict and Forms dict need have the same key. A forms dict is maked of a serie of parameciofast.forms elements, used for check the value.
+
+ Args:
+ post (dict): Dict composed by a series of values. The keys need to be equal to keys of arr_form dict.
+ arr_form (dict): Dict composed by a series or forms objects. The keys need to be equal to keys of post dict.
+
+ Returns:
+ post (dict): Return post dict with values checked
+ arr_form (dict): Return arr_form with errors and values.
+
+ """
+
+ for k in arr_form.keys():
+
+ post[k]=post.get(k, '')
+
+ if arr_form[k].field==None:
+ arr_form[k].field=corefields.CharField(k, 255, required=False)
+
+ post[k]=arr_form[k].field.check(post[k])
+ arr_form[k].txt_error=arr_form[k].field.txt_error
+
+ if arr_form[k].field.error==True and arr_form[k].required==True:
+ self.error+=1
+
+ return post, arr_form
+
+def check_form(post, arr_form, sufix_form='_error'):
+ """Function for make check form, passing errors to extra dict called error_form. Also returns an bool variable setting error.
+
+ Args:
+ post (dict): Dict composed by a series of values. The keys need to be equal to keys of arr_form dict.
+ arr_form (dict): Dict composed by a series or forms objects. The keys need to be equal to keys of post dict.
+ sufix_form (str): Define the sufix of error_form keys
+
+ Returns:
+ error (bool): Return False if not errors in checking, if errors return True
+ error_form (dict): A dict containing the errors in form fields.
+ post (dict): Sanitized values
+ arr_form (dict): arr_form with errors and values.
+
+ """
+
+ error=0
+ error_form={}
+
+ for k in arr_form.keys():
+
+ post[k]=post.get(k, '')
+
+ if arr_form[k].field==None:
+ arr_form[k].field=corefields.CharField(k, 255, required=False)
+
+ post[k]=arr_form[k].field.check(post[k])
+ arr_form[k].txt_error=arr_form[k].field.txt_error
+
+ if arr_form[k].field.error==True and arr_form[k].required==True:
+ error_form['#'+k+sufix_form]=arr_form[k].txt_error
+ error+=1
+
+ return error, error_form, post, arr_form
+
+def show_form(post, arr_form, t, session, yes_error=True, pass_values=True, modelform_tpl='forms/modelform.phtml'):
+ """Function for generate a html form from a template
+
+ Args:
+ post (dict): Dict composed by a series of values. The keys need to be equal to keys of arr_form dict.
+ arr_form (dict): Dict composed by a series of forms objects. The keys need to be equal to keys of post dict.
+ t (PTemplate): Object used for load template for form
+ yes_error (bool): Show errors in txt_error form variables.
+ pass_values (bool): Pass default values or values from post dict to arr_form dict items
+ modelform_tpl (str): Path for the template that generate the html form. By default is parameciofast/libraries/templates/forms/modelform.phtml
+
+ Returns:
+
+ template (str): An html string with the generated form.
+
+ """
+
+
+ # Create csrf_token in session
+
+ generate_csrf(session)
+
+ if pass_values==True:
+ pass_values_to_form(post, arr_form, yes_error, pass_values)
+
+ return t.load_template(modelform_tpl, session=session, forms=arr_form, csrf_token=csrf_token)
+
+def extract_post(post, fields):
+
+ """Helper function for create a simple array from other using fields list for filter
+
+ Args:
+ post (dict): A dict with keys and values to filter.
+ fields (list): A list with keys to validate.
+ """
+
+ return {k:v for k,v in post.items() if k in fields}
+
+#Simple Function for add repeat_password form to user model
+
+def set_extra_forms_user(user_admin):
+
+ """Helper function for add extraforms to UserModel form, not for general use
+
+ Args:
+ user_admin (UserModel): Instance of UserModel object for modify forms and fields
+
+ """
+
+ user_admin.fields['password'].required=True
+ user_admin.fields['email'].required=True
+
+ user_admin.create_forms(['username', 'email', 'password'])
+
+ user_admin.forms['repeat_password']=PasswordForm('repeat_password', '')
+
+ user_admin.forms['repeat_password'].required=True
+
+ user_admin.forms['repeat_password'].label=_('Repeat Password')
+
+def csrf_token(session, token_id='csrf_token'):
+
+ """Function for generate a csrf token html hide form using flask sessions
+
+ Args:
+ token_id (str): Name of the html hide form
+
+ Returns:
+ html (str): Return html input hidden with csrf token saved in session
+ """
+
+ #s=get_session()
+
+ if not 'csrf_token' in session:
+ session['csrf_token']=create_key_encrypt()
+
+ return ''
+
+def generate_csrf(session):
+
+ """Function for generate a csrf token in a variable
+
+ Returns:
+ csrf_token (str): csrf token value
+ """
+
+ if not 'csrf_token' in session:
+ session['csrf_token']=create_key_encrypt()
+
+ return session['csrf_token']
+
+def check_csrf(session, name_csrf_token='csrf_token'):
+
+ csrf_token=session.get('csrf_token', '')
+
+ if csrf_token=='' or csrf_token!=request.form.get(name_csrf_token):
+ abort(403)
+
+
diff --git a/parameciofast/libraries/mtemplates.py b/parameciofast/libraries/mtemplates.py
index 8f1eeb1..857d2b4 100644
--- a/parameciofast/libraries/mtemplates.py
+++ b/parameciofast/libraries/mtemplates.py
@@ -276,7 +276,7 @@ def add_css_home_local(file_css, module):
pass
-#env=env_theme(__file__)
+env=env_theme(__file__)
-#standard_t=PTemplate(env)
+standard_t=PTemplate(env)
diff --git a/parameciofast/libraries/templates/forms/colorform.phtml b/parameciofast/libraries/templates/forms/colorform.phtml
new file mode 100644
index 0000000..bb21e6d
--- /dev/null
+++ b/parameciofast/libraries/templates/forms/colorform.phtml
@@ -0,0 +1,33 @@
+${add_js_home_local('jquery.min.js', 'admin')}
+${add_js_home_local('spectrum.js', 'admin')}
+${add_css_home_local('spectrum.css', 'admin')}
+<%
+
+
+form.default_value=str(hex(int(form.default_value))).replace('0x', '')
+
+c=len(form.default_value)
+
+if(c<6):
+ repeat=6-c
+ form.default_value=('0'*repeat)+form.default_value
+
+form.default_value='#'+form.default_value
+
+%>
+
+
+
diff --git a/parameciofast/libraries/templates/forms/dateform.phtml b/parameciofast/libraries/templates/forms/dateform.phtml
new file mode 100644
index 0000000..6b6d852
--- /dev/null
+++ b/parameciofast/libraries/templates/forms/dateform.phtml
@@ -0,0 +1,71 @@
+${add_js('jquery.min.js', 'admin')}
+
+
+
+
+% if yes_time==True:
+
+
+
+% endif
+
+
+
diff --git a/parameciofast/libraries/templates/forms/fileform.phtml b/parameciofast/libraries/templates/forms/fileform.phtml
new file mode 100644
index 0000000..290f7e6
--- /dev/null
+++ b/parameciofast/libraries/templates/forms/fileform.phtml
@@ -0,0 +1,12 @@
+<%
+
+ import os
+
+ name_file=os.path.basename(form.default_value)
+
+%>
+
+% if name_file:
+ ${name_file}
+% endif
+
diff --git a/parameciofast/libraries/templates/forms/i18nform.phtml b/parameciofast/libraries/templates/forms/i18nform.phtml
new file mode 100644
index 0000000..e0bc53e
--- /dev/null
+++ b/parameciofast/libraries/templates/forms/i18nform.phtml
@@ -0,0 +1,73 @@
+<%
+
+choose=''
+
+%>
+
+<%def name="select_lang(i18n, lang_selected)">
+ % if i18n==lang_selected:
+ <%
+ return "choose_flag"
+ %>
+ % else:
+ <%
+ return "no_choose_flag"
+ %>
+ % endif
+%def>
+<%def name="hide_lang(i18n, lang_selected)">
+ % if i18n!=lang_selected:
+ style="display:none;"
+ % endif
+%def>
+
+% if lang_selected!=None:
+ % for i18n in arr_i18n:
+
+ ${form.change_name(name_form+'_'+i18n)}
+ <%
+ form.default_value=default_value[i18n]
+ %>
+ ${form.form()|n}
+
+ % endfor
+
+
${_('All lenguages activated, if you change to multilanguage, the default language will be ')}${lang_selected}