I have two modules. One is the core of the website based on web.py (let's name it code.py), and other is an add-on module (addon.py). Using web.py, for each page that the website server there should be class definition in a core, like that:
class Page:
def GET(self):
variable = "Hello!"
return render.page_template(variable) #Here, it returns the rendered template to user
def POST(self):
post_variables = web.input()
pass #Doing something with those variables, maybe, writing in a database...
Now I really need to move that class definition from code.py to addon.py. I can refer to the class definition as a addon.Page instead of simply Page. The Page.GET function still works well... But there's one problem with POST. It seems like at the each call of POST function web.input() in a core module is being set as a storage object storing all the variables. And if my class definition is being stored in addon, the core simply calls addon.Page.POST() (I see no way to change this behaviour). The POST() tries to get web.input()... And fails, of course - web is not imported in addon.py, and even if it was, there wouldn't be any value web.py web-server is getting - just empty dictionary, it would be just another instance of the module. So i don't know...
One solution would be: putting some kind of function in addon.Page.POST(). This function would go one level down, to code.py and execute web.input() there, and return it back, to addon.py, some kind of accessing parent module namespace (like doing import __main__ and accessing __main__.web.input() (which, as I know, is discouraged) ).
Or, for example, putting some kind of C-like pointer that would be shared between the modules, like:
* in code.py there's definition that all the calls to code.addon.web_input() get routed to code.web.input()
* in addon.py - there's simply need to call addon.web_input to get info from code.web.input()
What do I do in this situation? There will be multiple addons, each with the class definition stored in this addon, and I should be able to add new modules, connect and disconnect existing modules easily, without any need to modify code.py. I believe this is possible in Python... Maybe web.py source needs modifying then?
I guess I'll turn my comment into an answer, since it seems to have solved your issue.
Modules that are imported are cached in Python. That means that when you import a module like web (the main web.py module) from multiple other modules, they'll all get the same module object, with the same contents.
So, probably all you need to do is import web at the top of your addon.py module.
Related
A rookie here. As I am reading the django documentation, I came up with a note that I cannot fully understand.
It says:
Note
While your class is instantiated for each request dispatched to it, class attributes set through the as_view() entry point are configured only once at the time your URLs are imported.
Here is the link:
https://docs.djangoproject.com/en/2.2/topics/class-based-views/intro/
So which one is better? What advantage does each have? I've tried both and cannot experience any difference(Pretty sure that's because I've not considered enough)
If you are passing any values into the as_view() method that are likely to change after the server starts, for example some function call or database query whose return value could change after some users use the website, it will be evaluated only once, while the urls are loaded.
Let's say you are passing in the current time like:
path('about/', GreetingView.as_view(greeting=timezone.now())),
That note simply says that the value of the attribute 'greeting' for GreetingView will stay the same for all requests even if the server runs for a month, since timezone.now() is called only once.
Such arguments are good for reusing a View class with minimal changes. It depends completely on your use case.
For example:
path('add-car/', AddView.as_view(form=AddCarForm)),
path('add-bus/', AddView.as_view(form=AddBusForm)),
I initially started a small python project (Python, Tkinter amd PonyORM) and became larger that is why I decided to divide the code (used to be single file only) to several modules (e.g. main, form1, entity, database). Main acting as the main controller, form1 as an example can contain a tkinter Frame which can be used as an interface where the user can input data, entity contains the db.Enttiy mappings and database for the pony.Database instance along with its connection details. I think problem is that during import, I'm getting this error "pony.orm.core.ERDiagramError: Cannot define entity 'EmpInfo': database mapping has already been generated". Can you point me to any existing code how should be done.
Probably you import your modules in a wrong order. Any module which contains entity definitions should be imported before db.generate_mapping() call.
I think you should call db.generate_mapping() right before entering tk.mainloop() when all imports are already done.
A good approach to avoid this is rather than having your db.generate_mapping() call happening at a module's top-level code, have a function that a module exports that calls db.generate_mapping() after all other modules have been imported.
The pattern I use is to put all of my db.Entity subclasses into a single module named model, and then at the bottom of model.py is:
def setup():
""" Set up the database """
db.bind(**database_config, create_db=True)
db.generate_mapping(create_tables=True)
This function is called by my application's own startup (which is also responsible for setting up database_config). This way the correct import and setup order can be guaranteed.
The db object itself is also owned by this model module; if I need to use it somewhere else I import model and use model.db.
If you want to further separate things out (with different model classes living in different modules) you can have a module that owns db, then your separate model modules, and then a third module that imports db and the models and provides the setup function. For example, your directory structure could look like this:
model/
__init__.py -- imports all of the model sub-modules and provides a setup function
db.py -- provides the db object itself and any common entities objects that everyone else needs
form1.py, form2.py, etc. -- imports db and uses its database object to define the entities
Then your main app can do something like:
import model
model.setup()
The setup of the problem is simple enough:
an user selects a language preference (this preference can be read from the user’s session);
based on this choice, load the appropriate .mo from the available translations;
(no separate domains are set up, if it makes any difference)
Problem: since this return has to be done outside the scope of the flask app, it cannot be instantiated and to use #babel.localeselector. Instead, I use a simple function based on webapp2 i18n’ extension which, using Babel’s support function, loads a given translation and returns a translation instance (Translations: "PROJECT VERSION"). (inb4 ‘why not use webapp2 already?’ too many libs already).
From this point on, it is not clear to me what to do with this instance. How can I get Babel to use this specific instance? (at the moment, it always uses the default one, no 'best_match' involved).
Solved by just using the flask app and the way I wanted to avoid - on every request, there is a callback to the app instance and to the localeselector decorator, language is set previously in an attribute in flask.g. Basically, by the books I guess.
I am trying to do some pre-processing at Django startup (I put a startup script that runs once in urls.py) and then use the created instance of an object in my views. How would I go about doing that?
Try to use the singleton design pattern.
You can use a Context Processor to add it to your template context.
If you want it in the View, rather than the Template, then you can either have a base View class that has this, or just import the reference into the module your view is in (and access it directly).
Be aware that each django thread may have a different copy of the object in memory, so this should really only be used for read-only access. If you make changes to it, you are likely to find yourself in a world of hurt.
What is the best idea to fill up data into a Django model from an external source?
E.g. I have a model Run, and runs data in an XML file, which changes weekly.
Should I create a view and call that view URL from a curl cronjob (with the advantage that that data can be read anytime, not only when the cronjob runs), or create a python script and install that script as a cron (with DJANGO _SETTINGS _MODULE variable setup before executing the script)?
There is excellent way to do some maintenance-like jobs in project environment- write a custom manage.py command. It takes all environment configuration and other stuff allows you to concentrate on concrete task.
And of course call it directly by cron.
You don't need to create a view, you should just trigger a python script with the appropriate Django environment settings configured. Then call your models directly the way you would if you were using a view, process your data, add it to your model, then .save() the model to the database.
I've used cron to update my DB using both a script and a view. From cron's point of view it doesn't really matter which one you choose. As you've noted, though, it's hard to beat the simplicity of firing up a browser and hitting a URL if you ever want to update at a non-scheduled interval.
If you go the view route, it might be worth considering a view that accepts the XML file itself via an HTTP POST. If that makes sense for your data (you don't give much information about that XML file), it would still work from cron, but could also accept an upload from a browser -- potentially letting the person who produces the XML file update the DB by themselves. That's a big win if you're not the one making the XML file, which is usually the case in my experience.
"create a python script and install that script as a cron (with DJANGO _SETTINGS _MODULE variable setup before executing the script)?"
First, be sure to declare your Forms in a separate module (e.g. forms.py)
Then, you can write batch loaders that look like this. (We have a LOT of these.)
from myapp.forms import MyObjectLoadForm
from myapp.models import MyObject
import xml.etree.ElementTree as ET
def xmlToDict( element ):
return dict(
field1= element.findtext('tag1'),
field2= element.findtext('tag2'),
)
def loadRow( aDict ):
f= MyObjectLoadForm( aDict )
if f.is_valid():
f.save()
def parseAndLoad( someFile ):
doc= ET.parse( someFile ).getroot()
for tag in doc.getiterator( "someTag" )
loadRow( xmlToDict(tag) )
Note that there is very little unique processing here -- it just uses the same Form and Model as your view functions.
We put these batch scripts in with our Django application, since it depends on the application's models.py and forms.py.
The only "interesting" part is transforming your XML row into a dictionary so that it works seamlessly with Django's forms. Other than that, this command-line program uses all the same Django components as your view.
You'll probably want to add options parsing and logging to make a complete command-line app out of this. You'll also notice that much of the logic is generic -- only the xmlToDict function is truly unique. We call these "Builders" and have a class hierarchy so that our Builders are all polymorphic mappings from our source documents to Python dictionaries.