i am using wtforms with flask framework. when i use DateTimeField i add format parameter.
But datetime format is coming from user which is logged in
forms.py
from flask import g
from wtforms import *
import wtforms.validators as v
from flask.ext.babel import lazy_gettext as _
from flask.ext.babel import npgettext as _n
from app.app import app
from app.base_forms import *
from app.modules.post.models import *
class PostForm(BaseForm):
post_date = DateTimeField("Post Date", format = app.config.get("DATETIME_FORMAT"), validators =[v.Required(message=_("Post date is required"))] )
i set value of app.config.get("DATETIME_FORMAT") on before request
#app.before_request
def before_request():
if g.user.language == "tr"
app.config["DATETIME_FORMAT"] = "%d.%m.%Y %H:%M"
else:
app.config["DATETIME_FORMAT"] = "%m-%d-%Y %H:%M"
my application structure
/app
/modules
/post
/controllers.py
/forms.py
/models.py
/app.py
/run.py
content of /app/app.py
from flask import Flask, url_for, g, request, redirect, render_template
app = Flask(__name__)
app.config.from_object('app.config.config.ConfigDevelopment')
# Import Modules
from modules.post.controllers.admin import module as modulePostAdmin
app.register_blueprint(modulePostAdmin)
# other codes here
#app.before_request
def before_request():
if g.user.language == "tr"
app.config["DATETIME_FORMAT"] = "%d.%m.%Y %H:%M"
else:
app.config["DATETIME_FORMAT"] = "%m-%d-%Y %H:%M"
content of /run.py
from app.app import app
app.run(host='localhost', port=8080, debug=True)
when i start app it throws that error "KeyError: 'DATETIME_FORMAT'". i think forms.py load before request so it throws keyError.
What is the correct way for solving this problem.
Oh, I see your problem, the date format you want is changing on a per-request basis. app.config won't help you with this.
Here's what I would do:
from flask import g
from wtforms import DateTimeField
class I18NDateTimeField(DateTimeField):
def __init__(self, label=None, validators=None, format=None, **kwargs):
if g.user.language == "tr"
format = "%d.%m.%Y %H:%M"
else:
format = "%m-%d-%Y %H:%M"
super(I18NDateTimeField, self).__init__(label=label, validators=validators, format=format, **kwargs)
class PostForm(Form):
post_date = I18NDateTimeField("Post Date", validators =[v.Required(message=_("Post date is required"))] )
Background
You're (mostly) right, before_request hasn't been called yet. That said, the form definition doesn't happen in a request context at all, it happens when the app is imported, long before any requests arrive, and it won't happen more than once.
However, the form and its fields will be instantiated again for every request, and that's why this works. It's ok to modify self.format here since this field object is only being used for this request anyway.
Update 2:
I edited my answer to subclass Form instead of BaseForm. BaseForm is part of WTForms's low-level API; they say not to use it unless you're sure you need to. I also put that internationalization logic in the constructor rather than process_formdata (thanks to mattupstate from #pocoo for the idea).
I think it's a little clearer that way, and inspecting the field in the debugger will make more sense. Now, the way the code is written, you'd expect the field to be instantiated as a class attribute when the form is defined, which means that wouldn't work and this code wouldn't be thread-safe. But due to some metaclass trickery, the field is actually instantiated as an instance attribute when the form is instantiated. Note that that metaclass trickery doesn't work properly if you use BaseForm, which is another reason to avoid BaseForm.
Update 3:
Sorry, just talked with you on IRC and found out you wrote your own BaseForm that subclasses Form. That's perfectly fine :)
I'm not sure if it would be configured correctly when you do that. Your app.config is probably not on the app because of the structure of how you made it. Did you make it like app = Flask(__name__) and import that?
You could probably solve it by using the app factory pattern
# app/__init__.py
def create_app():
app = Flask(__name__)
app.config.from_object('app.settings.default')
from app.yourforms import bp
app.register_blueprint(bp)
return app
You can make a blueprint in a separate file like so:
# yourforms/__init__.py
from flask import Blueprint
bp = Blueprint('forms', __name__)
from . import views
Then in your views.py file in that same directory, use the blueprint
from flask import current_app
from . import bp
from .forms import PostForm
#bp.before_app_request
def set_datetime_format():
# your code
# access app's config with current_app.config.get('YOURKEY')
then you just need to tweek your runfile a little bit, to do this:
if __name__ == '__main__':
app = create_app()
app.run()
I am trying to build a form package for a Plone website. I am currently working with Plone 4.3. Before I was using Dexterity with five.grok and grok libraries. But after reading the Plone 4.3 migration and five.grok dependency section of this article: http://developer.plone.org/components/grok.html it appears that Plone developers are moving away from using grok all together.
So should I move away from using Grok and how would I go about doing so when all the current documentation is currently using Grok? Additionally I am developing from a Windows based machine.
First creating form without grok is not that hard and do not depends on your Operating System.
Creating a form is always the same. Here is how I proceed:
Some imports
from Products.Five.browser import BrowserView
from plone.autoform.form import AutoExtensibleForm
from plone.app.z3cform import layout
from zope import interface
from zope import schema
from zope import component
from z3c.form import form
from collective.my.i18n import _
Create a schema
class AddFormSchema(interface.Interface):
what = schema.Choice(
title=_(u"What"),
vocabulary="plone.app.vocabularies.UserFriendlyTypes"
)
where = schema.Choice(
title=u"Where",
vocabulary="collective.my.vocabulary.groups"
)
create a generic adapter to fill the form from anywhere
class AddFormAdapter(object):
interface.implements(AddFormSchema)
component.adapts(interface.Interface)
def __init__(self, context):
self.what = None
self.where = None
Then write the form
class AddForm(AutoExtensibleForm, form.Form):
schema = AddFormSchema
form_name = 'add_content'
Add a view
class AddButton(layout.FormWrapper):
"""Add button"""
form = AddForm
Now ZCML time this is the step you don't need when using grok:
<adapter factory=".my.AddFormAdapter"/>
<browser:page
for="*"
name="my.addbutton"
class=".my.AddButton"
template="addbutton.pt"
permission="zope2.View"
/>
Should you move from grok:
This is depending of what are you doing. For an addon I say Yes but for a project, it's up to you.
Grok is not parts of the already big Zope. So adding dependency is something that always should be done only if needed. Grok is an option so I have never used it.
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
I'm using LinguaPlone for my personal website and I have set it up using languages folder.
When I try to copy and paste an image from the en language folder into the 'fr' folder, the language is not changed. So I want to fix this behavior.
I'm trying to fix this at the moment in my own code but I just don't know why it doesn't work.
So the question is: how do I achieve this ? am I on the good way to do this ? what is missing here ?
from zope import component
from zope.globalrequest import getRequest
def updatelang(ob, event):
current = event.object
tools = component.getMultiAdapter((ob, getRequest()), name=u'plone_portal_state')
current_lang = current.getLanguage()
lang = tools.language()
if current_lang != lang:
current_object.setLanguage(lang)
ob.reindexObject(idxs=['Language'])
The setLanguage call throws an attribute error on reference_catalog.
Note, I'm working on Plone4.1
Self answer:
LinguaPlone override setLanguage to move the content in the first translated container in the parent chain.
Modify a bit the code to use getField pattern:
from zope import component
from zope.globalrequest import getRequest
def updatelang(ob, event):
current = event.object
tools = component.getMultiAdapter((ob, getRequest()), name=u'plone_portal_state')
current_lang = current.getLanguage()
lang = tools.language()
if current_lang != lang:
current.getField('language').set(current, lang)
current.reindexObject(idxs=['Language'])
Warning this code doesn do any check on already existing translation (if the current object has a translation in that language it will break things). but doing copy paste from one language to the other is a bad action, may be we should try to make them fail at all with a raise exception.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
The community reviewed whether to reopen this question last year and left it closed:
Original close reason(s) were not resolved
Improve this question
In my endless quest in over-complicating simple stuff, I am researching the most 'Pythonic' way to provide global configuration variables inside the typical 'config.py' found in Python egg packages.
The traditional way (aah, good ol' #define!) is as follows:
MYSQL_PORT = 3306
MYSQL_DATABASE = 'mydb'
MYSQL_DATABASE_TABLES = ['tb_users', 'tb_groups']
Therefore global variables are imported in one of the following ways:
from config import *
dbname = MYSQL_DATABASE
for table in MYSQL_DATABASE_TABLES:
print table
or:
import config
dbname = config.MYSQL_DATABASE
assert(isinstance(config.MYSQL_PORT, int))
It makes sense, but sometimes can be a little messy, especially when you're trying to remember the names of certain variables. Besides, providing a 'configuration' object, with variables as attributes, might be more flexible. So, taking a lead from bpython config.py file, I came up with:
class Struct(object):
def __init__(self, *args):
self.__header__ = str(args[0]) if args else None
def __repr__(self):
if self.__header__ is None:
return super(Struct, self).__repr__()
return self.__header__
def next(self):
""" Fake iteration functionality.
"""
raise StopIteration
def __iter__(self):
""" Fake iteration functionality.
We skip magic attribues and Structs, and return the rest.
"""
ks = self.__dict__.keys()
for k in ks:
if not k.startswith('__') and not isinstance(k, Struct):
yield getattr(self, k)
def __len__(self):
""" Don't count magic attributes or Structs.
"""
ks = self.__dict__.keys()
return len([k for k in ks if not k.startswith('__')\
and not isinstance(k, Struct)])
and a 'config.py' that imports the class and reads as follows:
from _config import Struct as Section
mysql = Section("MySQL specific configuration")
mysql.user = 'root'
mysql.pass = 'secret'
mysql.host = 'localhost'
mysql.port = 3306
mysql.database = 'mydb'
mysql.tables = Section("Tables for 'mydb'")
mysql.tables.users = 'tb_users'
mysql.tables.groups = 'tb_groups'
and is used in this way:
from sqlalchemy import MetaData, Table
import config as CONFIG
assert(isinstance(CONFIG.mysql.port, int))
mdata = MetaData(
"mysql://%s:%s#%s:%d/%s" % (
CONFIG.mysql.user,
CONFIG.mysql.pass,
CONFIG.mysql.host,
CONFIG.mysql.port,
CONFIG.mysql.database,
)
)
tables = []
for name in CONFIG.mysql.tables:
tables.append(Table(name, mdata, autoload=True))
Which seems a more readable, expressive and flexible way of storing and fetching global variables inside a package.
Lamest idea ever? What is the best practice for coping with these situations? What is your way of storing and fetching global names and variables inside your package?
How about just using the built-in types like this:
config = {
"mysql": {
"user": "root",
"pass": "secret",
"tables": {
"users": "tb_users"
}
# etc
}
}
You'd access the values as follows:
config["mysql"]["tables"]["users"]
If you are willing to sacrifice the potential to compute expressions inside your config tree, you could use YAML and end up with a more readable config file like this:
mysql:
- user: root
- pass: secret
- tables:
- users: tb_users
and use a library like PyYAML to conventiently parse and access the config file
I like this solution for small applications:
class App:
__conf = {
"username": "",
"password": "",
"MYSQL_PORT": 3306,
"MYSQL_DATABASE": 'mydb',
"MYSQL_DATABASE_TABLES": ['tb_users', 'tb_groups']
}
__setters = ["username", "password"]
#staticmethod
def config(name):
return App.__conf[name]
#staticmethod
def set(name, value):
if name in App.__setters:
App.__conf[name] = value
else:
raise NameError("Name not accepted in set() method")
And then usage is:
if __name__ == "__main__":
# from config import App
App.config("MYSQL_PORT") # return 3306
App.set("username", "hi") # set new username value
App.config("username") # return "hi"
App.set("MYSQL_PORT", "abc") # this raises NameError
.. you should like it because:
uses class variables (no object to pass around/ no singleton required),
uses encapsulated built-in types and looks like (is) a method call on App,
has control over individual config immutability, mutable globals are the worst kind of globals.
promotes conventional and well named access / readability in your source code
is a simple class but enforces structured access, an alternative is to use #property, but that requires more variable handling code per item and is object-based.
requires minimal changes to add new config items and set its mutability.
--Edit--:
For large applications, storing values in a YAML (i.e. properties) file and reading that in as immutable data is a better approach (i.e. blubb/ohaal's answer).
For small applications, this solution above is simpler.
How about using classes?
# config.py
class MYSQL:
PORT = 3306
DATABASE = 'mydb'
DATABASE_TABLES = ['tb_users', 'tb_groups']
# main.py
from config import MYSQL
print(MYSQL.PORT) # 3306
Let's be honest, we should probably consider using a Python Software Foundation maintained library:
https://docs.python.org/3/library/configparser.html
Config example: (ini format, but JSON available)
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes
[bitbucket.org]
User = hg
[topsecret.server.com]
Port = 50022
ForwardX11 = no
Code example:
>>> import configparser
>>> config = configparser.ConfigParser()
>>> config.read('example.ini')
>>> config['DEFAULT']['Compression']
'yes'
>>> config['DEFAULT'].getboolean('MyCompression', fallback=True) # get_or_else
Making it globally-accessible:
import configpaser
class App:
__conf = None
#staticmethod
def config():
if App.__conf is None: # Read only once, lazy.
App.__conf = configparser.ConfigParser()
App.__conf.read('example.ini')
return App.__conf
if __name__ == '__main__':
App.config()['DEFAULT']['MYSQL_PORT']
# or, better:
App.config().get(section='DEFAULT', option='MYSQL_PORT', fallback=3306)
....
Downsides:
Uncontrolled global mutable state.
A small variation on Husky's idea that I use. Make a file called 'globals' (or whatever you like) and then define multiple classes in it, as such:
#globals.py
class dbinfo : # for database globals
username = 'abcd'
password = 'xyz'
class runtime :
debug = False
output = 'stdio'
Then, if you have two code files c1.py and c2.py, both can have at the top
import globals as gl
Now all code can access and set values, as such:
gl.runtime.debug = False
print(gl.dbinfo.username)
People forget classes exist, even if no object is ever instantiated that is a member of that class. And variables in a class that aren't preceded by 'self.' are shared across all instances of the class, even if there are none. Once 'debug' is changed by any code, all other code sees the change.
By importing it as gl, you can have multiple such files and variables that lets you access and set values across code files, functions, etc., but with no danger of namespace collision.
This lacks some of the clever error checking of other approaches, but is simple and easy to follow.
Similar to blubb's answer. I suggest building them with lambda functions to reduce code. Like this:
User = lambda passwd, hair, name: {'password':passwd, 'hair':hair, 'name':name}
#Col Username Password Hair Color Real Name
config = {'st3v3' : User('password', 'blonde', 'Steve Booker'),
'blubb' : User('12345678', 'black', 'Bubb Ohaal'),
'suprM' : User('kryptonite', 'black', 'Clark Kent'),
#...
}
#...
config['st3v3']['password'] #> password
config['blubb']['hair'] #> black
This does smell like you may want to make a class, though.
Or, as MarkM noted, you could use namedtuple
from collections import namedtuple
#...
User = namedtuple('User', ['password', 'hair', 'name']}
#Col Username Password Hair Color Real Name
config = {'st3v3' : User('password', 'blonde', 'Steve Booker'),
'blubb' : User('12345678', 'black', 'Bubb Ohaal'),
'suprM' : User('kryptonite', 'black', 'Clark Kent'),
#...
}
#...
config['st3v3'].password #> passwd
config['blubb'].hair #> black
I did that once. Ultimately I found my simplified basicconfig.py adequate for my needs. You can pass in a namespace with other objects for it to reference if you need to. You can also pass in additional defaults from your code. It also maps attribute and mapping style syntax to the same configuration object.
please check out the IPython configuration system, implemented via traitlets for the type enforcement you are doing manually.
Cut and pasted here to comply with SO guidelines for not just dropping links as the content of links changes over time.
traitlets documentation
Here are the main requirements we wanted our configuration system to have:
Support for hierarchical configuration information.
Full integration with command line option parsers. Often, you want to read a configuration file, but then override some of the values with command line options. Our configuration system automates this process and allows each command line option to be linked to a particular attribute in the configuration hierarchy that it will override.
Configuration files that are themselves valid Python code. This accomplishes many things. First, it becomes possible to put logic in your configuration files that sets attributes based on your operating system, network setup, Python version, etc. Second, Python has a super simple syntax for accessing hierarchical data structures, namely regular attribute access (Foo.Bar.Bam.name). Third, using Python makes it easy for users to import configuration attributes from one configuration file to another.
Fourth, even though Python is dynamically typed, it does have types that can be checked at runtime. Thus, a 1 in a config file is the integer ‘1’, while a '1' is a string.
A fully automated method for getting the configuration information to the classes that need it at runtime. Writing code that walks a configuration hierarchy to extract a particular attribute is painful. When you have complex configuration information with hundreds of attributes, this makes you want to cry.
Type checking and validation that doesn’t require the entire configuration hierarchy to be specified statically before runtime. Python is a very dynamic language and you don’t always know everything that needs to be configured when a program starts.
To acheive this they basically define 3 object classes and their relations to each other:
1) Configuration - basically a ChainMap / basic dict with some enhancements for merging.
2) Configurable - base class to subclass all things you'd wish to configure.
3) Application - object that is instantiated to perform a specific application function, or your main application for single purpose software.
In their words:
Application: Application
An application is a process that does a specific job. The most obvious application is the ipython command line program. Each application reads one or more configuration files and a single set of command line options and then produces a master configuration object for the application. This configuration object is then passed to the configurable objects that the application creates. These configurable objects implement the actual logic of the application and know how to configure themselves given the configuration object.
Applications always have a log attribute that is a configured Logger. This allows centralized logging configuration per-application.
Configurable: Configurable
A configurable is a regular Python class that serves as a base class for all main classes in an application. The Configurable base class is lightweight and only does one things.
This Configurable is a subclass of HasTraits that knows how to configure itself. Class level traits with the metadata config=True become values that can be configured from the command line and configuration files.
Developers create Configurable subclasses that implement all of the logic in the application. Each of these subclasses has its own configuration information that controls how instances are created.