Flask blueprint/app factory circular import - flask

I realise that blueprints are meant for modularity, and perform this task well. However, I have several tasks that are required by multiple blueprints as well as the root application (i.e. app/). With this mind, when I make changes to the tasks in app/tasks.py I would like it to propagate out to the blueprints that use these tasks without me having to manual change the code in each blueprints' task file (app/blueprint/tasks.py).
With this in mind I am trying to import app/tasks.py into each of the blueprints that has a copy of some task in app/tasks.py in app/blueprint/tasks.py. Of course, the main issue here is circular imports and I can't seem to get around them, in fact it seems almost impossible. My app factory does not import app/tasks.py until it has returned to application. Is it possible to make this import prior to registering the blueprints in the factory itself? If not, is there any way to circumvent the circular import problem? At the moment I see no way around it, there is no where to place from app import tasks in the blueprint files without creating a circular import.
EDIT: I realised the issue was that I registered my blueprints in my app factory. So when I would attempt from app.tasks import <func> in app/blueprint/tasks.py it would raise an import error since app had not been declared at the point of blueprint registration. I could get around this by moving the blueprint registration outside the app factory but is there a better way of doing this?

From what i can see it should work? Could it be that it is confusing things due to naming? As in thinking that the app is refering to app object and not the folder?
I just tested in my own app and i can import same things into app.py and my blueprint files.
Try maybe changing the folder names so they are not named app.

Related

Where to put initialisation code (in Mioguel Grinberg's Flasky app)

I am building an app using Miguel's Flasky code as the basic framework to start with. I'm following his structure but with separate Blueprints for each major discrete part of my own additional functionality.
During any initial deployment, I need the app to initialise the database with a system user, various system-related defaults, etc.
Where in the Flasky app should I put the code to do this? It obviously has to be invoked before any user interactions but will need to reference app, db and SQLAlchemy models defined in several of the Bluprints, so must be after these have all been imported.
I'm thinking it should be in a function in the app __init__.py which I then call at the end of the app.create_app function, after all the blueprint imports. It would obviously test for whether initialisation has already happened (i.e. is this a first run, not just a restart of the app).
Is that where people usually put first-time initialisation code?

How to make a reusable Django apps if there are some modules which have a dependencies in another apps?

Should a component be its own application?. So we have separate our apps for that reason.
Now reusability does matter in Django. It is trivial to make our apps reusable when each module in the apps does not depends on another apps.
However, It is common to refer a model in another apps by adding ForeignKey('appname.MyModel'). It creates a hard dependency of the Django apps with another apps.
The same thing happened with import of another apps (i.e. from appname import MyModel). It creates a dependencies of the apps to another apps.
If the app contains such dependency of another apps, then it does not seems to be viable to share our apps (i.e. Not reusable).
What do I have to do to make the dependencies loose. And allow me to share my apps without having to hardcode another apps in the app.
So, it's worth noting that we don't really need to depend on your specific apps. We depend instead on having something that satisfies the same interfaces your apps expose.
This is the 'Pythonic' way to do things (sometimes referred to as duck typing as 'if it walks like a duck and quacks like a duck... it must be a duck').
You've had in comments how to solve the ForeignKey problem
To summarise, you can just add the value in settings.py:
MY_FK_MODEL = 'someapp.SomeModel'
and then use it in your models.py like so:
from django.conf import settings
class ReusableAppModel(models.Model):
some_model = models.ForeignKey(settings.MY_FK_MODEL)
So far, so easy; now to solve the import.
We actually already have an example of this from Django itself. Which is the get_user_model() method.
We could make something like that by adding the following in settings.py:
MY_APP_DEPENDENCY = 'myapp.my_module.MyClass'
along with a helper function similar to get_user_model() somewhere in your reusable app. Let's say reusable_app/helpers.py for the sake of argument:
from django.conf import settings
from pydoc import locate
def get_my_app_dependency():
dependency = locate(settings.MY_APP_DEPENDENCY)
# locate() returns None if the class is not found,
# so you could return a default class instead if you wished.
return dependency
Then you can get that class wherever you need it by calling the method:
from reusable_app.helpers import get_my_app_dependency
MyAppDependency = get_my_app_dependency()
app_dep_instance = MyAppDependency()
The summary here is that you can allow users to specify a class/method/whatever as a string in settings.py and then use that to refer to your dependency.
This lets users 'inject' a dependency into your app.
One final note:
Whenever you have an app/module that has lots of dependencies on others, it's worth double checking to see if they really should be separate. You want to avoid creating one giant module satisfying lots of disparate responsibilities, but likewise you want to avoid artificially breaking code up when it doesn't make sense. It's a careful balance.

Coupled flask blueprints and circular imports

What is the properly flask-way to implement application with coupled blueprints?
I'm currently working on project with several modules. I've separate application into modules logically, in dependence of database entities, and specify these modules as blueprints. But some of these blueprints have dependencies on each other: for example, view of blueprint A uses internal method (like a search in db, not view) from blueprint B, while another view from B uses another internal method from A.
Of course, it's cause circular imports.
The best way to handle this would to be decouple your internal Blueprint calls into a separate module. Try to concentrate your database logic in one module and only create specific calls when needed.
Your project layout might look like:
+ App
|
|`--+ models
| |`-- __init__.py
| |`-- models.py
| `-- utils.py
|
`--+ blueprints
|`-- __init__.py
|`-- blueprint_a.py
`-- blueprint_b.py
And then in App/blueprints/__init__.py you'd import your models and your models helpers. From within blueprint_a.py you'd import the model stuff you'd need and blueprint_b.py you'd import the other model stuff you need there.

django - reusing functions in many views

I have a bunch of functions that I created in some views that must be reused in many other views. Do I need to create a class and put those functions in a class? If yes how exactly has to be done in Django and then how do I call and initiate them in the new views?
Django views are just Python functions. You can call other Python functions from them just as you can from any other Python code. Put your functions into a .py file, import it, and invoke the functions.
Of course, it may make sense for other reasons to create a class to hold the functions, but you certainly don't need to in order to call them from views.
The solution would be to create the myfunctions.py file in your app folder and import it in your views. Your views file would look like:
import myfunctions
def my_view(request):
.....
foo = myfunctions.bar()
....
You look to complicated to Django. Django is just another Python application and lives in the Python world. For example you can create file library.py and import this file where is needed (in modules where the function from library is needed). If you need you library's functions to get data from database, just import models in the library.py and use them.
Django doesn't have such a big think as "module". You creating the architecture, you can define what in your case is module. In general this is just simple directory with init.py file inside to be able to import files from there.
Hope that helped.
From my point of view, if you have a lot of functions that are widely used in your project it make sense put all this in some separate application. I create some module named 'contrib' for this purposes. It can avoid some time for maintaining this code in future

Django and Eclipse, making a portable project

I like Eclipse for a number of reasons. One of them is, when I'm doing a java project, I can copy and paste my project or rename it, to make a new one, and it will update all the names of everything.
I'm trying to do something similar for a django project.
I can set an APPNAME variable with the following code
APPNAME = os.path.basename(os.path.dirname(__file__))
and then I could import this in any file that needed to know the name of the application. This isn't an ideal solution however but it would work for my settings.py file as well as my urls.py files.
It won't work for situations where I need to import something from somewhere like so:
from myproject.someapp import forms
Is there a way for django/python to know what "myproject" is? Or can I use an import statement relative to the current app?
Or maybe there's a better way to copy django projects.
EDIT: I imagine there are also database dependencies as well that I'd have to deal with.
I follow a couple of rules to keep my applications portable. I'll list them below in the hope that someone finds them useful.
Include my apps in the PYTHONPATH rather than my projects. This way I can execute from app import forms rather than from project.app ....
Following #1, I always import from app only. This means I can reuse my apps in other projects without having to change import statements within the app or in other dependent apps.
If you stick to #1 and #2 you can generally copy and paste projects without too much trouble. You'll still have to modify settings.py though.