pre_delete signal not working in specific directory - django

i want remove file from storage when a File instance removed.trying to use django signal. here is my model File:
class File(models.Model):
orig_name = models.CharField(_('Original Name'), max_length=255)
conversation = models.ForeignKey('conversation.Conversation', on_delete=models.CASCADE)
the architecture of every app are same.means all of app have own signals directory and in signals's directory we have __init__.py and handlers.py files .here is a brief tree of my app with some detail for file's app:
apps
├── conversation
├── post
└── file
├── admin.py
├── apps.py
├── __init__.py
├── models.py
├── signals
│   ├── handlers.py
│   └── __init__.py
├── tests.py
├── urls.py
└── views.py
here is apps/file/apps.py:
from django.apps import AppConfig
class FileConfig(AppConfig):
name = 'apps.file' # exact as INSTALLED_APP in setting.py
def ready(self):
import apps.file.signals.handers
here is apps/file/signals/handlers.py :
from django.db.models.signals import pre_delete
from django.dispatch import receiver
from apps.file.models import File
#receiver(pre_delete, sender=File)
def remove_file_from_storage(sender, instance, *args, **kwargs):
print('pre_delete signal for File working')
# some code is here
and app/file/signals/__init__.py file is empty. in this project we are using multiple signals and all of them working fine but i don't know why this signal not working.other signal are from custom and build-in signal both. please notice when i moving def remove_file_from_storage function into other app into related app_name/signals/handlers.py it's working fine.the process of deleting is a simple generics.DestroyAPIView of DRF. where is the problem with my architect of using signal?thank you

The problem is because you use receiver decorator to register signals. With that you have to place your code inside ready function of your Django application. This document does mention about that:
In practice, signal handlers are usually defined in a signals submodule of the application they relate to. Signal receivers are connected in the ready() method of your application configuration class. If you’re using the receiver() decorator, simply import the signals submodule inside ready().
But in real practice, we won't put all signals code inside ready method, that might make our code harder to read and harder to maintain. So like you did, we will put the signals inside signals.py and then load it into your app via ready method, like so:
from django.apps import AppConfig
class FileConfig(AppConfig):
label = 'file'
name = 'file'
def ready(self):
from apps.file import signals # NOQA
# add # NOQA to ignore error message from Python linter when we just import but never used
and set this to __init__.py so that Django could discover your app:
apps
├── conversation
├── post
└── file
├── admin.py
├── apps.py
├── __init__.py # Add to this file
├── models.py
├── signals
│ ├── handlers.py
│ └── __init__.py
├── tests.py
├── urls.py
└── views.py
default_app_config = 'apps.file.apps.FileConfig'
You could also take a look at this article to gain more details about Django signals
Hope that helps!

Related

Adding dash to flask app where dash need to access db and user session_id

I have a flask app with the following structure:
/test
├── /application
│ ├── __init__.py
│ ├── routes.py
│ ├── /static
│ ├── /templates
│ └── /dashboard
│ └── __init__.py
├── db.py
├── config.py
├── requirements.txt
├── helpers.py
└── wsgi.py
I am trying to implement a dash dashboard by intitating it through calling a function in application.init.py
where the function is define in dashboard.init.py
my application.init.py
def init_app():
"""Construct core Flask application."""
app = Flask(__name__, instance_relative_config=False)
app.config.from_object('config.Config')
# Ensure responses aren't cached
#app.after_request
def after_request(response):
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
response.headers["Expires"] = 0
response.headers["Pragma"] = "no-cache"
return response
# Custom filter
app.jinja_env.filters["usd"] = usd
Session(app)
assets = Environment()
assets.init_app(app)
with app.app_context():
# Import parts of our core Flask app
from . import routes
from .assets import compile_static_assets
# Import Dash application
from .dashboard import init_dashboard
app = init_dashboard(app)
# Compile static assets
compile_static_assets(assets)
return app
in dashboard.init.py file the function init_dashboard need to access the database and the user id, because the dashboard layout need to use values from the database so that it will show the specific dashboard for the user, but of course this does not work as it return the error "Working outside of request context".
If I will try to create the dashboard in routes for example:
#app.route("/dashapp/")
#login_required
def redirect_to_dashapp():
dash_app = dash.Dash(
server=app,
routes_pathname_prefix="/dashapp/")
"""Create a Plotly Dash dashboard."""
stocks = db.session.query(Records.symbol, Records.number_of_shares, Records.purchase_p, Records.execution_time).filter_by(user_id=session["user_id"]).all()
.....
it will return the error "A setup function was called after the first request was handled. "
As the dash layout need values from the database I can't initiate it in init_dashboard() without accessing the db, and I can't initiate in routes either.
Does anyone has a suggestion on how to properly do it?

How to defined a database connecting Flask python file and then import it?

1.I was trying to use Pymongo to connect to my MongoDB atlas database. I wrote this file into the connect.py file. Here is the tree folder structure. The connect.py contains the URL information to connect the database.
└── uploading
├── __pycache__
│   └── upload.cpython-38.pyc
└── upload.py
├── Database
│   ├── __pycache__
│   │   └── connect.cpython-38.pyc
│   └── connect.py
├── app.py
2.Here is code for connect.py
import pymongo
client = pymongo.MongoClient("URL",ssl=True, ssl_cert_reqs='CERT_NONE')
db = client.datasets
Here is the code for uplod.py
from flask import Blueprint, current_app
from Database.connect import db
sample = Blueprint('sample', __name__)
#sample.route('/')
def index():
x = current_app.config['UPLOAD_PATH']
return str(db)
Here is the code for app.py:
app = Flask(__name__)
app.secret_key = b'pj&\xe9\xd7\xd7\xabc\xe6KX\xbe\x9f<\x9f\x87'
app.config['UPLOAD_PATH'] = 'public' # to create a folder which is used to save the uploaded file
CORS(app)
app.register_blueprint(sample)
'''
Datasets and model upload
'''
#app.route('/connect-upload', methods=["POST"])
#cross_origin()
def connect_upload():
index=0
# get username
return "result"
When I tried to use : from Database.connect import db to import database in the upload.py, it showed error message :ImportError: cannot import name 'db' from 'Database.connect'. How can I solve this problem?
You are not referencing your module correctly. Your module should be the filename. You should use from connect import db.

Using Flask Restful as a Blueprint in Large Application

I am trying to use Flask restful as a Blueprint in a pattern that works for other blueprints. I keep getting the following error message
I get the following error message
AttributeError: 'Blueprint' object has no attribute 'add_resource'
My project setup is as follows:
Folder structure
├── app
│   ├── __init__.py
│   ├── api
│   │   ├── __init__.py
│   │   └── routes.py
│   ├── main
│   │   ├── __init__.py
│   │   ├── forms.py
│   │   └── views.py
│   └── templates
│   ├── base.html
│   └── home.html
├── config.py
├── manage.py
└── requirements.txt
__init__.py
from flask import Flask
from flask_restful import Api
from flask_bootstrap import Bootstrap
from config import config
bootstrap = Bootstrap()
api = Api()
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
bootstrap.init_app(app)
api.init_app(app)
from .main import main as main_blueprint
from .api import api as api_blueprint
app.register_blueprint(main_blueprint)
app.register_blueprint(api_blueprint)
return app
api/__init__.py
from flask import Blueprint
api = Blueprint('api', __name__)
from . import routes
api/routes.py
from flask_restful import Resource
from . import api
class TodoItem(Resource):
def get(self, id):
return {'task': 'Say "Hello, World!"'}
api.add_resource(TodoItem, '/todos/<int:id>')
What am I doing wrong??
If you follow the instructions from https://flask-restful.readthedocs.io/en/0.3.5/intermediate-usage.html
The key points here are to create a Flask Blueprint instance & pass it to a new instance of flask-restfuls's Api class.
Lastly, make sure to register the flask-restful api blueprint within your create_app function: app.register_blueprint(api_bp)
from flask import Flask, Blueprint
from flask_restful import Api
from flask_bootstrap import Bootstrap
from config import config
bootstrap = Bootstrap()
api_bp = Blueprint('api', __name__)
api = Api(api_bp)
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
bootstrap.init_app(app)
from .users import main as users_blueprint
from .blogs import main as blogs_blueprint
# blueprints for blogs & users
app.register_blueprint(users_blueprint)
app.register_blueprint(blogs_blueprint)
app.register_blueprint(api_bp)
return app
Also note, you don't need to register api.init_app(app) anymore.
You're running in to trouble because of how you've named your blueprint api, whilst also using the api object from flask_restful. In your routes.py you're explicitly importing api from api/__init__.py, and this is a Blueprint object. You can't call add_resource to a Blueprint object, only to an Api object from flask_restful.
If you change your import to:
from .. import api
you'll be importing the correct object. I'd still recommend changing your blueprint name anyway to avoid this sort of confusion.
If you want to have submodules (like your /api) based on resources...
Eg: folder structure
├── app
│ ├── __init__.py
│ ├── foo
│ │ ├── __init__.py
│ │ └── routes.py
│ ├── boo
│ │ ├── __init__.py
│ │ └── routes.py
├── config.py
├── manage.py
... and register their blueprints with url_prefix to not repeat the common part in each added resource. Create new Api instance in each module and pass to it a blueprint.
foo/__init__.py
from flask import Blueprint
from flask_restful import Api
foo_bp = Blueprint('foo', __name__, url_prefix='/foo')
foo_api = Api(foo_bp)
from . import routes
in routes import foo_api and add resources to it
foo/routes.py
from flask_restful import Resource
from . import foo_api
class TodoItem(Resource):
def get(self, id):
return {'task': 'Say "Hello, World!"'}
foo_api.add_resource(TodoItem, '/todos/<int:id>')
Then in main application __init__.py just import modules blueprints and register it. You dont even need to add a "main" application blueprint. If you would import the api from main application __init__ then you can't register each blueprint with it's own params like url_prefix.
__init__.py
from flask import Flask
from config import config
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
from .foo import foo_bp
from .boo import boo_bp
app.register_blueprint(foo_bp)
app.register_blueprint(boo_bp)
return app
You can set the url_prefix on register blueprint (it has priority) or when you create it. To check routes you can print the app.url_map

django cannot find management command

I am using django 1.5.1 and trying to get moving the management command. I have an app called patient and here is the directory structure.
patient/
├── __init__.py
├── forms.py
├── management
│   ├── __init.py__
│   └── commands
│   ├── __init.py__
│   └── recall1.py
├── models.py
├── urls.py
├── views.py
Here is what happens when I try to run the recall1 command:
$ python manage.py recall1
Unknown command: 'recall1'
Here is how my code looks like:
from django.core.management.base import BaseCommand, CommandError
from recall.model import PatientRecalls, RecallType, RecallMessage
from patient.model import Patient
class Command(BaseCommand):
args = '<patient_id patient_id ...>'
def handle(self, *args, **options):
for patient_id in args:
try:
patient = Patient.objects.get(pk=int(patient_id))
except Patient.DoesNotExist:
raise CommandError('Patient "%s" does not exist' % patient_id)
patient.opened = False
patient.save()
self.stdout.write('Successfully closed patient "%s"' % patient_id)
What wrong do I need to correct before I can run this thing? The app is running great, except for this issue..
Your filename __init.py__ should actually be __init__.py both in the directories management/ and commands/

Moving django apps into subfolder and url.py error

I have a question about putting django apps into "apps" subdirectory. I have the app called “faktura” in a project_root. I didn’t like the fact it lies there and I want to store all my apps under “apps” subdirectory.
So, I found out that I could extend python path to “apps” subdir, so after looking in the internet, I added this string to settings.py: sys.path.insert(0, os.path.join(PROJECT_PATH, "apps")). Then I added the app to INSTALLED_APPS like “faktura”. Everything worked smooth until I added url(r'^faktura/', include('faktura.urls')) to urls.py in the root. Since that, Django throws the error message “No module named faktura” full taceback is here: http://dpaste.com/737380/
What can be wrong here, why only urls.py can’t find the app? And does it can’t find this app if I added it to the PATH? I spent a morning trying to figure out what’s wrong and now I need your help.
I don't know why the previous answer got -1 aside from maybe a few redundant lines that can be corrected. Anyway, I found a slightly different method that doesn't involve adding anything to the python path.
This is my final directory structure, I will explain in a moment:
mysite
├── mysite
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── apps
│ ├── __init__.py
│ └── myfirstapp
│ ├── __init__.py
│ ├── admin.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
└── manage.py
No matter if you have just created your project or if you want to move your apps, create the apps subdirectory that should contain your apps. The trick is to add an __init__.py to that directory.
mkdir apps
touch apps/__init__.py
Now you can move your existing apps into the apps subdirectory. If you would like to create a new one instead here are the commands:
python manage.py mysecondapp
mv mysecondapp apps/
Warning: Don't be tempted to call python manage.py ./apps/mysecondapp. For some reason this deletes all other apps in that directory. I just lost a day of work this way.
Next, you will need to fix a few imports. Your settings.py should be prefixed with apps:
INSTALLED_APPS = (
...
'apps.myfirstapp',
'apps.mysecondapp'
)
Lastly, fix your project's urls.py to prefix apps:
urlpatterns = patterns('',
url(r'^myfirstapp', include('apps.myfirstapp.urls')),
...
)
Depending on how you wrote them, you might also have to fix a few imports inside your app. Either just use from models import MyFirstModel or also prefix it using from apps.myfirstapp.models import MyFirstModel.
In short, if you make your apps directory a python package (by adding __init__.py), you can use it as part of the import path. This should work regardless of the deployment method with no extra configuration.
Use BASE_DIR variable from the settings.py. It should be already defined:
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
Better not use the __file__ attribute in manage.py and wsgi.py, as they are located in different directories.
So, just add the following to manage.py and wsgi.py (and to the celery.py if you use Celery):
from django.conf import settings
sys.path.append(os.path.join(settings.BASE_DIR, "apps"))
You will end up with the following project structure:
project
├── project
│ ├── __init__.py
│ ├── celery.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── apps
│ ├── app1
│ └── app2
└── manage.py
To keep your Django applications in a subfolder (such as apps/), first add the following to your settings.py:
import os
PROJECT_ROOT = os.path.dirname(__file__)
Then in manage.py:
Right under #!/usr/bin/env python add:
import sys
from os.path import abspath, dirname, join
from site import addsitedir
Right before if __name__ == "__main__" : add:
sys.path.insert(0, join(settings.PROJECT_ROOT, "apps"))
#Radu Gheorghiu's answer; It is not necessary to edit settings.py, and the insert path line can be condensed to 1 line of code.
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "apps"))
I sourced this answer from http://obroll.com/nested-application-inside-apps-sub-folder-in-django-1-3/