Read/Write permission for a program run with subprocess? - django

I've got a Django app, which calls a program using subprocess.call(). This program creates a couple of files, which I then use back in my app. The problem is the program doesn't seem to have permission to create files. I also tried calls like subprocess.call(['mkdir','/tmp/myapp']) but the directory was not created. What do I need to do?
This is just with my dev server at the moment, which I invoke with
sudo python manage.py runserver 0.0.0.0:8080
I can run the command from the terminal manually fine.
I can also use subprocess to touch the files, which it does fine, but when it runs the program that accesses the files itself, that program throws an error because it cannot.

The /tmp/myapp directory needs to be created first. If your view function in Django doesn't show you an error it means that you are not catching it properly.
Try something like this:
response = HttpResponse()
calltxt = subprocess.call(['mkdir','/tmp/myapp'])
response.content = calltxt
return response
Append the function to your urls.py and load it in the browser.
0 means the command executed successfully, 1 means error (this is similar to the $! variable in Bash).
I think it's not the case but if your Django app is deployed in the Web Server the user that creates files and executes commands out of the Python environment is the one that owns the web server daemon. For instance www-data in Apache.
Thus, it is needed to change permissions for this user also in order to write and execute commands out of their normal scope.

Related

why do i need to restart my docker container to see changes in django views.py file on windows

Why do I have to restart my docker container every time I make a change in my Django python files? I'm running a Django app via Docker and it seems any changes I make in my Views(and possibly elsewhere) are not reflected until I restart my container.
For example, if I log an output to the terminal or make changes, then refresh, there's no change. If I restart my container and then refresh, I get the result I would expect.
As I know you can consider Docker environment like immutable type doesn’t allow any change in the object once it has been created.
And that will give us more security.
If you want a solution there is some vs code extensions can run script contain some command after you edit your files, you can insert docker command in this script to reload environment after you edit any file.

Can't write to a file with Django in Nginx

I have deployed a Django web app using uWSGI and Nginx, but the app runs into an error when trying to create a file inside a specified folder.
Inside my views file, I specify a function which writes to a file using "with open". This function writes the file to a folder named 'output' inside the Django project folder. When I run the Django server, all the functionality works well, but, when I run the Nginx server, it gives me an error exactly where the "with open" is.
I have already tried to switch the ownership of the 'output' folder, but it did not work. Also tried to run 'sudo chmod -R www-data:www-data' with my whole project folder as an attribute, but I had no success.
I would please like to have more insight on how to fix this issue. The problem is likely about my permissions, but I have tried everything in my knowledge to fix it but it did not work.
In attachment, I am sending an image of the output of the 'ls -la' command inside my Django project folder.
Also, the guide I have followed can be found here: https://tonyteaches.tech/django-nginx-uwsgi-tutorial/.
# views.py
filename = 'Memorial_LaTeX.tex'
filepath = os.path.join(os.getcwd(), 'output', filename)
memorial = open(filepath, 'w')
It is right at this last line that the exception occurs.
output of the ls -la command inside my Django project folder

Where to up django app startup code that must interact with the database?

I have some django code that needs to run once when my app is loaded in the dev server or as a wsgi worker. This code also needs to write to the database. In my particular case I do not need the code to run for many management commands like collectstatic or createsuperuser, etc.
This SO question "Where to put Django startups code?" recommends using AppConfig.ready for startup code.
However, the docs for the ready function clearly warn against interacting with the database:
Although you can access model classes as described above, avoid interacting with the database in your ready() implementation. This includes model methods that execute queries (save(), delete(), manager methods etc.), and also raw SQL queries via django.db.connection. Your ready() method will run during startup of every management command. For example, even though the test database configuration is separate from the production settings, manage.py test would still execute some queries against your production database!
Is there some later startup hook I should use for code that does need to update the database?
The code registers my server as a webhook endpoint with a 3rd party service and stores required connection information in the database. I only register for the webhook if not already configured.
We have a similar use case:
If the server is restarted, it needs to manage database information in order to not leave some procedures in stall state.
The way we solve this is with a systemd script, only executed once during startup, which calls a script, which performs operations in django's database.
1) Create a python script that will do the required operations and changes to the database:
/djangoproject/boot_script.py
Which contains:
from yourdjangoapp.models import XModel
# DO STUFF WITH XModel
2) Create a script wich calls to a python script for django:
/.../execute_boot_script.sh
Which contains:
cd /djangoproject
python manage.py shell < boot_script.py
And has execution rights:
sudo chmod +x /.../execute_boot_script.sh
3) Create a file for the service:
/etc/systemd/system/execute_boot_script.service
which contains:
[Unit]
After=apache2.service
[Service]
Environment=ENVPATH=:/usr/local/... # ONLY IF YOU NEED TO SET SOME ENVIRONMENT VARIABLE
Type=oneshot
ExecStart=/.../execute_boot_script.sh
[Install]
WantedBy=multi-user.target
More info:
https://linuxconfig.org/how-to-automatically-execute-shell-script-at-startup-boot-on-systemd-linux
This answer works in linux, but could be also easily achieved in windows with a programmed task launched at startup, though.

Run program on server forever without manually starting it

I have created an application which resides on a server. The application uses Django to connect. So, if I want to access the web page I have to run the following command to start the server -
python manage.py runserver ip adress:port number
What is the way to keep it running all the time even after shutting down my computer?
But, I also want to save the logs of the application so that I can see it later and debug or just check the running of the program whenever I want to.
I managed to solve the issue by running the following command -
nohup python manage.py runserver ip:port > Output.txt &
The log is getting saved in the Output.txt file.

Insert http request header for debugging

I'm testing a Django application on my local environment using python manage.py runserver 0.0.0.0:8000
When the app is running in production, the client has a web proxy that validates you against AD and inserts a http header. But for debugging, I can't run though that proxy. In order to test, I've been using the Firefox plugin "Modify Headers" to insert a version of this header, but now I've got a bug that requires me to insert that header in IE. I'd rather not modify the source because there is a risk that it might end up getting checked in, so I'm looking for something I can either put in the app settings.py or a script or something I can run between the testing server and the client (but which doesn't require anything to be installed because everything is locked down here).
Let's say this is your settings.py:
VARIABLE_THAT_YOU_NEED = "VALUE A"
In the end of your settings file you just have to add this line:
if 'test' in sys.argv:
try:
from test_settings import *
except ImportError:
pass
Now you create a new file named "test_settings.py", inside of this file you override ONLY what you need for testing, in your case:
VARIABLE_THAT_YOU_NEED = "VALUE B"
So, when you run your server, you will have your variable normally and when run tests this variable will be replaced!