Django models access outside Django without access to the settings file - python

I would like to allow people that don't have access to the Django project root folder (so no access to settings.py file and no DB password) to use specific models outside of Django.
I would like some users to be able to query certain tables in the database using the powerful Django structure (querysets etc...) without giving full access to all the tables.
Would any of the following strategies work? Is it even possible to do that? And what are the best practices for this kind of issues?
Idea 1: Setting-up django using my_project.settings.
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "my_project.settings")
django.setup()
The problem is that it requires access to the project root folder and give access to all the database
Idea 2: Setting-up django using a different database user with restricted access
from django.conf import settings
settings.configure(
DATABASE_ENGINE = 'django.db.backends.mysql',
DATABASE_NAME = '<db_name>',
DATABASE_USER = 'new_user',
DATABASE_PASSWORD = '<psw>',
DATABASE_HOST = '<host>',
INSTALLED_APPS = ...
)
I didn't manage to make this work yet but I feel like the django.setup() will fail because the DB user won't have access to all the tables. Also it still needs access to the project root folder.
Idea 3: Using the database (MySQL) directly from python, no link at all with Django.
This is probably not advised but that's the only solution I have so far.
Is there any django-like python package that would allow querying the database in a similar way to Django?
Idea 4: Maybe something using a custom manage.py command?

Related

URL rewriting with Django

The Problem I want to solve is the following:
E.g. we have https://example.com/?id=e46Hd3cDe. But I want to make it look nicer so I want users to be able to go to this link: https://example.com/e46Hd3cDe and get the same HTML file returned.
How could I achieve this in Django?
If I would have to change something in the Apache config, how could I do that while testing Django locally? Currently, I test my Django website by calling python manage.py runserver and opening it at localhost:8000.
In Django, in your urls.py, define in url_patterns:
url_patterns = [
path('/<int:id>', view_name_goes_here),
]
Then, configure the corresponding functions in your views.py to accept the id parameter and get the corresponding object.
You don't need to modify your Apache config beyond adding in the WGSI setup for Django.

Django code to execute only in development and production

I need to execute some housekeeping code but only in development or production environment. Unfortunately all management commands execute similar to runserver. Is there any clean way to classify what is the execution environment and run the code selectively.
I saw some solutions like 'runserver' in sys.argv
but it does not work for production. And does not look very clean.
Does django provide anything to classify all these different scenarios code is executing at?
Edit
The real problem is we need to initialise our local cache once the apps are loaded with some data that are frequently accessed. In general I want to fetch DB for some specific information and cache it (currently in memory). The issue is, when it tries to fetch DB, the table may not be created, in fact there may not be migration files created at all. So, when I run makemigrations/migrate, it will run this code which tries to fetch from DB, and throw error saying table does not exist. But if I can't run makemigration/migrate, there will be no table, it is kind of a loop I'm trying to avoid. The part of code will run for all management commands, but I would like to restrict it's execution only to when the app is actually serving requests (that is when the cache is needed) and not for any management commands (including the user defined ones).
```python
from django.apps import AppConfig
from my_app.signals import app_created
class MyAppConfig(AppConfig):
name = 'my_app'
def ready(self):
import my_app.signals
# Code below should be executed only in actual app execution
# And not in makemigration/migrate etc management commands
app_created.send(sender=MyAppConfig, sent_by="MyApp")
```
Q) Send app created signal for app execution other than executions due to management commands like makemigrations, migrate, etc.
There are so many different ways to do this. But generally when I create a production (or staging, or development) server I set an environment variable. And dynamically decide which settings file to load based on that environment variable.
Imagine something like this in a Django settings file:
import os
ENVIRONMENT = os.environ.get('ENVIRONMENT', 'development')
Then you can use
from django.conf import settings
if settings.ENVIRONMENT == 'production':
# do something only on production
Since, I did not get an convincing answer and I managed to pull off a solution, although not a 100% clean. I thought I would just share solution I ended up with.
import sys
from django.conf import settings
if (settings.DEBUG and 'runserver' in sys.argv) or not settings.DEBUG:
"""your code to run only in development and production"""
The rationale is you run the code if it is not in DEBUG mode no matter what. But if it is in DEBUG mode check if the process execution had runserver in the arguments.

Django management command without working db connection

I have a number of projects that use the following configuration model:
settings.py includes default configuration and config specifications, mainly used for development purposes.
The default settings (including db settings) can be overridden by external configuration files, usually defined by admins for the various environments they manage. In order to ease the admins, I have written a management command and packaged separately, which adds the option to create example configuration files based on the default configuration in settings.py
Trying to run the command without the possibility for successful db connection, however, raises django.db.utils.OperationalError.
How can I make the command work without db connection, as it does not need one and normally when the command is needed, most probably the db connection is not configured properly.
settings.DATABASES != {} as there are the default db settings.
Django 1.10.6, Python 3.5.3
Do requires_system_checks = False
class Command(BaseCommand):
requires_system_checks = False
...
def add_arguments(self, parser):
#rest of code
For more info

Managing a database connection object in Django

I'm working with a Postgresql database with Django. Because of licensing reasons, I can't use psycopg2 , so I'm using the alternative pygresql.
I don't need to use the Django ORM at all, I simply need the cursor for cur.execute() and cur.fetchall().
Since I can't use the pygresql pgdb module in the Database settings in settings.py; I've to manually open up a connection object.
What would be the best practice to do this? Currently I've simply created the connection object conn=pgdb.connect(params) in views.py outside of all functions, but this seems a bit hacky.
Any tips?
It might be a good idea to create your own PYGRE_CONFIG dictionary in settings.py that has info about the server hostname, database name, login name etc. You can use it by using from django.conf import settings and settings.PYGRE_CONFIG. Then, create a separate application utils or pygre in the root of your project directory that manages the connection object (opening and closing it as needed using settings.PYGRE_CONFIG) and stores it in a thread-local variable. Your other applications can import things from this module. Keeping it as a separate app can make it easy for you to port it from project to project.

In Flask-SQLAlchemy, where do I initialise and store the database object?

I am building a website using Flask and SQLAlchemy in Python, and having great fun so far.
There is something I'm not sure about, however. The following code is used to connect to the database:
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'bla'
db = SQLAlchemy(app)
How do I reuse this object in different files, though? I have tried storing it in g, but this causes problems in the database models, when I try to use the database outside a web request's scope. Is there a standard method to make db accessible in multiple files/classes?
Put it in a __init__.py file under your project folder. This way, your application becomes a package and you can re-use the variables. For example, if your project is called myproject, then you could have
myproject/
__init__.py
models.py
views.py
Now, in modules such as models.py, you can just do:
from myproject import db

Categories

Resources