django import a view function - django

I have a django application xxx which does a number of things.
I also have a sepaerate application yyy. Which wants to call one of the functions of xxx.
Is there a way for me to import the functions?
For example, in yyy can i say
from toplevel.xxx import doit
Or what is the best approach, I dont want to duplicate code.

Of course, you can fo it.
With a proper import and parameter, you can do it.
#app: app1
#someview.py
def a_view(request, someparam):
#some code here
#app: app2
#otherview.py
from app1.someview import a_view
def another_view(request):
param = 1
a_view(request, param)
As for an example
UPDATE: Wish to mention that, your function a_view() do not have to get a parameter at all. So you can call functions with no paramaters. I just wish to mention that, if your function have paramaters, you have to pass them as if you do within an application.

Related

How to import the same flask limiter in a structured flask app

I'm trying to organize my Flask app, as it's getting quite big in length at close to 1000 lines
I am trying to separate the REST API from my main app, by using the approach shown here: https://flask-restx.readthedocs.io/en/latest/scaling.html#multiple-apis-with-reusable-namespaces
What remains in my main.py is something like
from apiv1 import blueprint as api1
REST_API = Flask(__name__)
REST_API.wsgi_app = ProxyFix(REST_API.wsgi_app, x_for=1)
REST_API.register_blueprint(api1)
However in my app, I am using the flask limiter
# Very basic DOS prevention
try:
limiter = Limiter(
REST_API,
key_func=get_remote_address,
storage_uri="redis://localhost:6379/1",
# storage_options={"connect_timeout": 30},
strategy="fixed-window", # or "moving-window"
default_limits=["90 per minute"]
)
# Allow local workatation run
except:
limiter = Limiter(
REST_API,
key_func=get_remote_address,
default_limits=["90 per minute"]
)
This is likewise placed in a decorator to my various API functions
decorators = [limiter.limit("30/minute")]
def post(self, server_id = ''):
# [..]
Now that I am splitting my REST api from the same file that declaring my endpoints, I don't know how to pass its object. The REST_API var exists only in my main.py
How should I handle passing the limiter variable, or any other global objects for that matter?
I worked for a few hours yesterday but I finally understood the pythonic way to do this sort of thing.
I just couldn't wrap my head around how imports function so I was struggling with questions like "how do I pass the variable during import" etc.
Finally it clicked for me that I need to follow a "pull" method with my imports, instead of trying to push variables into them. I.e. I setup the center location in my package's __init__ which will import my logger module, and then my other modules will import THAT logger variable from there.
So in my app's __init__, I have
from .limiter import limiter
And in the app/apis/v1.py I have
from .. import limiter
And this seems to finally work. I don't know if this is the expected way, meaning to play with relative module paths, so if there;s a more elegant way, please let me know

How to instantiate a class one time and access it in views

I have a class that runs once, which I had in myapp/__init__.py, but each time django starts it would run twice. It also runs when I migrate models, when I don't need it to.
I've read about the ready function https://docs.djangoproject.com/en/dev/ref/applications/#django.apps.AppConfig.ready, but cannot access the instantiated class outside of apps.py
Here is my current workflow:
in init.py:
from .my_module import ResourceHeavyClass
resource_heavy_instance = ResourceHeavyClass()
in my views.py
from . import resource_heavy_instance
This currently works, but I only want to load the module when the server starts, not when I make migrations. Appreciate any tips/advice.
You could make use of a SimpleLazyObject to postpone the creation until you really need it. Like for example:
from .my_module import ResourceHeavyClass
from django.utils.functional import SimpleLazyObject
class SomeClass:
resource_heave_instance = SimpleLazyObject(ResourceHeavyClass)
Now as long as you do not fetch the SomeClass.resource_heave_instance, it will not create the ResourceHeavyClass.
So if you for example have a method, you can use it like:
def some_method():
resource_heave_instance = SomeClass.resource_heave_instance
So here, when you call the some_method, it fetches the attribute, and it will indeed construct the object. But as long as the attribute is not fetched, it will not create a ResourceHeavyClass object. Once constructed, it will not create the object a second time.
So if the attribute is not fetched by just interpreting the file (so only by calling functions, and other continuations), we are safe.

Get argument from route function in my own decorator in flask

In the flask, between the route function and the view function, how can I obtain the argument so that I can define a new decorator? Here I show an example.
#app.route('/Page/<int:Num>')
#HowToGetNum(Num) # here I do not know how to get Num
def Page(Num):
....
The parameter Num will be passed into Page. But before that, I want to define a new decorator "HowToGetNum". However, I found there is no way to pass Num into it. Any solutions?
In python decorator operate on the function before they are used.
What's actually going on is the Page function is being redefined.
Page = HowToGetNum(Page)
What you can do is define HowToGetNum as:
def HowToGetNum(func):
def GetsNum(Num):
# do something with Num
func(Num)
return GetsNum
So the new function has your functionality then runs the original Page

how to call event from another module in tkinter

i made a test app for reasons like this. I am trying to have the ButtonRelease-1 event call a function inside another file. I am getting a syntax when trying to run the app.
TypeError: listb() takes exactly 2 arguments (1 given)
this is pretty strait forward syntax but i cannot fix it in this specific situation. I am basically just having the event get the clicked info printed. It's the event that is no working because function inside other file is not reconizing the event?
anyways, curious how to fix this code so it works. The function has to stay in another file. This would be easy if it was in same file but it cannot be.
start.py
from Tkinter import *
import example_funcs as EF
class Page_three(Frame):
def __init__(self):
Frame.__init__(self)
self.pack()
self.listboxs()
def listboxs(self):
self.z = Listbox(self)
self.z.grid()
for item in range(1,10):
self.z.insert(END, item)
self.z.bind("<ButtonRelease-1>", EF.listb(self))
root = Tk()
app = Page_three()
app.mainloop()
example_funcs.py
from Tkinter import *
import Tkinter as tk
def listb(self, event):
selection = self.z.curselection()
print selection
self is used so variables can be called inside the function, if do not call self as instance it will have syntax of not finding my listbox variable.
Passing EF.listb(self) doesn't do what you want it to do. It doesn't partially bind the self parameter to the instance you're calling it from, then let the event paramter get filled in by the callback. Instead, it just calls the function immediately (before the bind call is made) and you get an error about using the wrong number of arguments.
There are a few different ways you could fix this issue.
One option would be to manually bind the self parameter to the listb function using functools.partial:
import example_funcs as EF
import functools
class Page_three(Frame):
...
def listboxs(self):
...
self.z.bind("<ButtonRelease-1>", functools.partial(EF.listb, self)) # bind self
Another approach would be to make listb an actual method in your class, so that you can reference it as a method on self. That could look like this:
import example_funcs as EF
class Page_three(Frame):
...
def listboxs(self):
...
self.z.bind("<ButtonRelease-1>", self.listb) # refer to a method without calling it
listb = EF.listb # add the function from the other module as a method on this class
If listb isn't used anywhere else though, then defining it in another module and copying it over here would be pretty silly. You should just move the definition into this class instead of adding a reference to it after the fact. On the other hand, if listb is being used in several different classes, it suggests that the classes should be using some kind of inheritance to share the method, rather than crudely copying references to the one definition around.

Adding more CoC to Django

I come from a Cake background, and I'm just starting to learn Django now. I'm liking it quite a bit, but I kinda wish it used convention over configuration like cake does. So,
How can I get Cake-style URLs automatically? For example, if I went to mysite.com/posts/view/5 it would load up mysite.posts.views.view and pass an argument 5 to it? I was thinking I could add something like (r'^(.*)/(.*)', 'mysite.$1.$2'), to urls.py, but of course, that won't work.
How can I automatically load up a template? Each view function should automatically load a template like templates/posts/view.html.
Is this even possible, or do I have to hack the core of Django?
Here's my solution, based on what Carl suggested:
urlpatterns = patterns('',
# url pats here
url(r'^(?P<app>\w+)/(?P<view>\w+)/(?P<args>.*)$', 'urls.dispatch')
)
def dispatch(req, app, view, args): # FIXME: ignores decorators on view func!
func = get_callable(app+'.views.'+view)
if args:
ret = func(req, *args.split('/'))
else:
ret = func(req)
if type(ret) is dict:
return render_to_response(app+'/'+view+'.html', ret)
else:
return ret
Seems to be working pretty well with initial tests. Solves both problems with a single function. Probably won't support GET-style arguments tho.
Those points are both implementable without hacking Django core, but either one will require a non-trivial level of familiarity with advanced Python techniques.
You can do the generic URL pattern with a pattern like this:
url(r'^(?P<appname>\w+)/(?P<viewfunc>\w+)/(?P<args>.*)$', 'myresolverfunc')
Then define a 'myresolverfunc' "view" function that takes "appname", "viewfunc", and "args" parameters, and implement whatever logic you want, splitting args on "/" and dynamically importing and dispatching to whatever view function is referenced. The trickiest part is the dynamic import, you can search Django's source for "importlib" to see how dynamic imports are done internally various places.
The automatic template loader can be implemented as a view function decorator similar to the various "render_to" decorators out there, except you'll generate the template name rather than passing it in to the decorator. You'll have to introspect the function object to get its name. Getting the app name will be trickier; you'll probably just want to hardcode it as a module-level global in each views.py file, or else work in conjunction with the above URL dispatcher, and have it annotate the request object with the app name or some such.
I don't you'll need to hack the core of Django for this. It sounds like you might be in need of generic views. Also check out the Generic Views topic guide.
The first example given in the generic views documentation sounds like your first bullet point:
Example:
Given the following URL patterns:
urlpatterns = patterns('django.views.generic.simple',
(r'^foo/$', 'direct_to_template', {'template':'foo_index.html'}),
(r'^foo/(?P<id>\d+)/$', 'direct_to_template', {'template':'foo_detail.html'}),
)
... a request to /foo/ would render the template foo_index.html, and a request to /foo/15/ would render the foo_detail.html with a context variable {{ params.id }} that is set to 15.