writing to django session database table after configurating settings.py - python

I'm writing a new backend API using Django.
I have configured the following values in settings.py:
CACHES = {
'default': {
'BACKEND': 'django.contrib.sessions.backends.cached_db'
}
}
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
I can't figure out how to write the session properties to the database. Anyone have any idea?

You have to activate also django.contrib.sessions.middleware.SessionMiddleware middleware first to have access to request.session dictionary in your views.
Here's simplistic example how to use request.session, taken directly from Django session documentation:
def post_comment(request, new_comment):
if request.session.get('has_commented', False):
return HttpResponse("You've already commented.")
c = comments.Comment(comment=new_comment)
c.save()
request.session['has_commented'] = True
return HttpResponse('Thanks for your comment!')

Related

Django redis cache cannot access redis cache set outside of django

I'm setting up redis as a docker service and connect to it through django-cache and python redis library.
First:
from django.http import HttpResponse
from django.core.cache import cache
def test_dj_redis(request):
cache.set('dj_key', 'key_in_dj', 1000)
print(cache.get('dj_key')) # works
print(cache.get('py_key')) # Nope
print(cache.get(':1:py_key')) # No, tried reverse engineer the prefix
return HttpResponse("bla bla bla")
Second:
import redis
r = redis.Redis(
host='redis',
port=6379
)
def cache_it():
r.set('py_key', 'key in py', 1000)
print(r.get('py_key')) # works
print(r.get(':1:dj_key')) # works
print(r.keys()) # show two keys
If I run both of them
first one by refresh the web page related to that django view
second one by python cache_it().
In first, I cannot access 'py_key', it will return None.
But second, I can see cache set in django view. Django cache added a prefix to it and turn 'dj_key' into ':1:key_in_dj', but I can access it nonetheless.
Also in second, the redis_r.keys() return [b'py_key', b':1:key_in_dj'].The value of the key 'py_key' remained the same.
django cache setting
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.redis.RedisCache',
'LOCATION': 'redis://redis:6379',
},
}
Question, how do I use django.core.cache to access redis cache set outside of Django.

Django: settings.DATABASES is improperly configured

I know I am not the first person to ask this question, but I still couldn't find an answer for my situation.
I have a Django environment that works very well, I know I only have one (1) settings.py file and I know that my environment accesses it correctly.
I recently added a new endpoint to my project. I defined its URL in urls.py
urlpatterns = [
...
url(PREFIX + r"^v1/alerts/debug$", alerts_views_v1.debug_trigger_alert_notification),
...
]
It is connected to a method that is in a the file alerts/views_v1.py but is not in any particular class:
#api_view(["POST"])
def debug_trigger_alert_notification(request):
"""
Trigger an Alert. i.e. Create an Alertnotification.
This function is meant to be called by the scheduler service.
"""
workspace_slug = request.data.pop("workspace")
with in_database(workspace_slug, write=True):
serializer = AlertNotificationSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response()
When I send a request to this URL, I receive the following 500 error:
ImproperlyConfigured at /v1/alerts/debug
settings.DATABASES is improperly configured. Please supply the ENGINE value. Check settings documentation for more details.
In my settings.py file, my DATABASES variable seems correct (though it is built in a roundabout way):
DEFAULT_DATABASES = {
"default": { # This DB is supposed to always have the latest version of the schema described by the Django Model
"ENGINE": "django.db.backends.postgresql",
"NAME": os.environ["REFERENCE_DB_NAME"],
"USER": os.environ["DB_USER"],
"PASSWORD": os.environ["DB_PASSWORD"],
"HOST": os.environ["DB_HOST"],
"PORT": os.environ["DB_PORT"],
}
}
# Retrieve all existing workspace databases:
try:
_existing_workspace_database_names = ExistingWorkspace(
db_user=DEFAULT_DATABASES["default"]["USER"],
db_host=DEFAULT_DATABASES["default"]["HOST"],
db_password=DEFAULT_DATABASES["default"]["PASSWORD"],
).list_existing_workspaces()
except Exception as e:
log.critical("settings.py: Error retrieving list of existing databases.")
raise e
else:
log.info("settings.py: Successfully retrieved list of existing databases.")
WORKSPACE_DATABASES = {
db_name_to_slug(existing_workspace_database_name): {
"ENGINE": "django.db.backends.postgresql",
"NAME": existing_workspace_database_name,
"USER": os.environ["DB_USER"],
"PASSWORD": os.environ["DB_PASSWORD"],
"HOST": os.environ["DB_HOST"],
"PORT": os.environ["DB_PORT"],
}
for existing_workspace_database_name in _existing_workspace_database_names
}
DATABASES = {**DEFAULT_DATABASES, **WORKSPACE_DATABASES}
DATABASE_ROUTERS = ["dynamic_db_router.DynamicDbRouter"]
What can I do?

Python/Django universal method passed to template engine

I have a large Django Project that has hundreds of views already. I am creating a tasks feature where users are able to complete specific tasks associated with the specific application in the project they are using. I have multiple interfaces (aka Django apps in the project) : admin, management, onsite, etc... and each interface has its own navigation with a tasks link.
What I want is to be able to change the color of this link if a user is in an interface where a task has yet to be completed.
This is easy to check in each view and then I could universally render the correct color for the link based on a variable passed into the view, but that is extremely tedious with hundreds of views.
I suppose I could add a filter in each interface/Django App to simplify this a bit, but is that the most simple solution?
Here is an example of the method I want to be called in each interface's navigation:
from objects_client.task_models.task_models import Tasks
def does_interface_have_open_tasks(current_interface, db_alias):
if Tasks.objects.using(db_alias)\
.filter(interface=current_interface, completed=0).exists():
return True
return False
I ended up using a Context Processor to solve my needs like I show below:
import traceback
from objects_client.task_models.task_models import Tasks
def universally_used_data(request):
# I use multiple DBs
db_alias = request.session.get('db_alias')
# dictionary for global context values
dictionary_to_return = dict()
# interfaces and URL equivalents
interface_dictionary = {
'adm': 'admin',
'mgt': 'management',
'onsite': 'onsite',
'secu': 'security',
'maint': 'maintenance'
}
try:
# get interface url
short_url = request.path[1:-1].split('/')[1]
# get interface from dictionary above
interface = interface_dictionary.get(short_url)
dictionary_to_return['SHORT_URL'] = short_url
dictionary_to_return['INTERFACE'] = interface
# see if there is an open task...
if Tasks.objects.using(db_alias) \
.filter(interface=interface, completed=0).exists():
dictionary_to_return['OPEN_TASKS'] = True
else:
dictionary_to_return['OPEN_TASKS'] = False
except Exception as ex:
print(ex, traceback.format_exc())
return dictionary_to_return
Here is how I load the Context Processor:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR, 'templates'),
...
]
,
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
...
# custom processors
'utils.context_processors.context_processors.universally_used_data'
],
},
},
]
Then I can just call the this variable in the template like so to change an HTML element's color, no {% load [whatever] %} or anything:
{% if OPEN_TASKS %}
style="color:red;"
{% endif %}
Thank you #Daniel Roseman for the suggestion/comment. This had me stumped for a bit :)

How to use one db to run the django service and other to fetch data

i have an existing application data base from which my web site should only fetch the data according to user input. Added database details in the settings.py file and I tried python manage.py integratedb and get the all the 300+ tables came off to my models.py file. I was never able to do python manage.py runserver it threw a million errors. Now i found a work around but i need your opinion on this.
I added the default server into the settings.py and using it i was able to run the server. settings.py looks like this.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'mydatabase',
},
'user': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME' : 'test',
'USER' : 'testuser',
'PASSWORD': 'readonly',
'HOST' : '10.20.30.40',
'PORT' : '5446',
}
}
Now can i access the user db to fetch data from my form? for example
views.py looks like this
from django.shortcuts import render_to_response
from .models import TestCases
from django.shortcuts import HttpResponse
from django.http import JsonResponse
from django.forms.models import model_to_dict
from django.views.decorators.csrf import csrf_exempt
# Create your views here.
#csrf_exempt
def index(request):
posts = TestCases.objects.all()[:10]
return render_to_response('index.html',{'posts':posts})
where TestCases is a class name from the models.py file.
Now when i click the button to retrieve data i get "no such table: test_cases"
models.py looks like
class TestCases(models.Model):
id = models.BigIntegerField(primary_key=True)
clientid = models.ForeignKey(Clients, db_column='clientid')
projectid = models.ForeignKey(Projects, db_column='projectid')
class Meta:
managed = False
db_table = 'test_cases'
what am i doing wrong to get the data from the user input. please help.
Queryset .using() method
I guess Django is going for the default database.
Try this:
#csrf_exempt
def index(request):
posts = TestCases.objects.using('user').all()[:10]
return render_to_response('index.html',{'posts':posts})
When you set using to your queryset, you can specify which database django is going to query.
More information in Django docs
A better approach, so you don't have to manually set it to all your queries.
You can manually add it to all your queries, or you can create a custom manager to your objects and force it to use a specific database for objects.
Ex:
# this will override the default queryset for objects that use this Manager
class UserDatabaseManager(models.Manager):
def get_queryset(self):
return super().get_queryset().using('user')
class MyModel(models.Models):
objects = UserDatabaseManager()
Then, when you use MyModel, you can query as usually and Django will use the user db for default just for models that have objects = UserDatabaseManager().
Keep in mind that this is just a simple use of the Manager, you can have multiple managers and do a lot of cool stuff.
Take a look at the Django Managers docs
first of all you need to do:
python manage.py inspectdb > models.py
to store your models to models.py
By default, inspectdb creates unmanaged models. That is, managed = False in the model’s Meta class tells Django not to manage each table’s creation, modification, and deletion, if you do want to allow Django to manage the table’s lifecycle, you’ll need to change the managed option above to True (or simply remove it because True is its default value).
Next, run the migrate command to install any extra needed database
python manage.py migrate
integrating docs

Django REST Framework + Django REST Swagger

Having a hard time configuring Swagger UI Here are the very explanatory docs in - https://django-rest-swagger.readthedocs.io/en/latest/. My settings.py looks like this.
urls.py looks like this.
But the swagger web page isn't loading properly.
and the console log is as follows.
What might be the problem here?
Take a look at django-rest-swagger schema documentation, there is some code examples there about how this ties into DRF. You can read some more about this by visiting the DRF Schema Generator documentation.
If you just want to get up and running without learning more about the library, this article does a good job about showing project architecture and integrating DRS with DRF.
very first, install django rest framework into your application and import that in setting.py file
make few APIs using DRF and then add swagger setting inside your setting.py file
SWAGGER_SETTINGS = {
'SECURITY_DEFINITIONS': {
'api_key': {
'type': 'apiKey',
'in': 'header',
'name': 'Authorization'
}
}, # setting to pass token in header
'USE_SESSION_AUTH': False,
# set to True if session based authentication needed
'JSON_EDITOR': True,
'api_path': 'api/',
'api_version': 'v0',
"is_authenticated": False, # Set to True to enforce user authentication,
"is_superuser": False, # Set to True to enforce admin only access
'unauthenticated_user': 'django.contrib.auth.models.AnonymousUser',
# unauthenticated user will be shown as Anonymous user in swagger UI.
}
Note:- You can edit the swagger setting according to you need.

Categories