I'm writing a quick little test view that I can GET every few minutes to check that my application and database servers are online and functioning.
from django.http import HttpResponse, HttpResponseServerError
from my_app.models import Model
def test(request):
'''
Returns a HttpResponse to prove the application/db servers work
'''
if request.method == "GET":
#test database access
count = Model.objects.values_list('id', flat=True).count()
if count:
return HttpResponse("OK")
return HttpResponseServerError("Error")
Is there a more minimal inbuilt database query that I could do to test that the db server is working and takling to the app server, without having to do a fake one like I did above?
You can import django connections and check with your databases:
from django.db import connections
try:
cursor = connections['default'].cursor()
except OperationalError:
return HttpResponseServerError("Error")
else:
return HttpResponse("OK")
return HttpResponseServerError("Error")
Documentation here
Related
I'm trying to use the django rest framework to identify when an API Request is coming from my own website (in order to send an error to these requests).
views.py
from django.shortcuts import render
from django.http import JsonResponse
from rest_framework.request import Request as RESTRequest
def is_rest_request(request):
return isinstance(request, RESTRequest)
def payment(request, *args, **kwargs):
if is_rest_request(request):
return JsonResponse({"result": 502})
else:
return JsonResponse({"result": 209})
However, when I make the following request from an online python compiler:
import requests
x = requests.get('https://url.com/api/payment')
print(x.text)
I get this output: {"result": 209}, when I should be getting {"result": 502}
Any reasons why?
I'm writing functional tests to test API endpoints with pytest.
I want to achieve:
that at the end of each test DB transaction rolls back so that each test starts with the same data.
at the end of the test session, I want to delete the testing DB.
Bellow is my conftest.py file, and what is currently happening is that transactions aren't rolled back, and when it comes to the end of the session, it keeps hanging at drop_database on teardown, while it doesn't hang at the beginning when checking if DB exists (marked also in comments).
What do I need to do to make those rollbacks? And is there anything else I need to close, in order for that drop_database to take place?
Thank you!
import pytest
import sqlalchemy
from sqlalchemy_utils import database_exists, create_database, drop_database
from alembic.command import upgrade
from alembic.config import Config
from flask import Flask
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
from api.views import dtm_api, diagrams_api, labels_api
from .data.dummy_data import import_dummy
ALEMBIC_CONFIG = 'migrations/alembic.ini'
#pytest.fixture(scope='session')
def app(request):
_app = Flask(__name__)
_app.config.from_object('api.config.TestingConfig')
_app.register_blueprint(diagrams_api.bp)
_app.register_blueprint(dtm_api.bp)
_app.register_blueprint(labels_api.bp)
ctx = _app.app_context()
ctx.push()
def teardown():
ctx.pop()
request.addfinalizer(teardown)
yield _app
#pytest.fixture(scope='session')
def test_client(app, request):
yield app.test_client()
#pytest.yield_fixture(scope='session')
def db(app, request):
engine = sqlalchemy.create_engine(app.config.get("SQLALCHEMY_DATABASE_URI"))
if database_exists(engine.url):
drop_database(engine.url) #here it doesn't hang
create_database(engine.url)
_db = SQLAlchemy()
_db.init_app(app)
_db.app = app
#Make migrations and add dummy data
Migrate(app, _db)
config = Config(ALEMBIC_CONFIG)
config.set_main_option("script_location", "migrations")
with app.app_context():
upgrade(config, 'head')
import_dummy(_db)
def teardown():
drop_database(engine.url) #here it hangs
engine.dispose()
request.addfinalizer(teardown)
yield _db
#pytest.fixture(scope='function', autouse=True)
def session(db, request):
connection = db.engine.connect()
options = dict(bind=connection, binds={}, autoflush=False, autocommit=False)
db.session = db.create_scoped_session(options=options)
def teardown():
db.session.rollback()
db.session.close()
connection.close()
request.addfinalizer(teardown)
yield db.session
I'm building a system where I store a Member model on a Django server, one of the attributes of Member is score which is what I want to change using API calls. My question is what would be the best way to do this? I looked into the Django REST framework but it seems a bit overkill for what I'm trying to do. I've been trying to pass the necessary information through the url using regular expressions but I'm unsure if it will work. Outline of what I need is below
iOS/Android app makes request sending pk and score to add to total
server updates appropriate model instance and returns True/False to app depending if save was successful
You can achieve this by this quite dirty solution:
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('<int:member_id>/<int:score_to_add>/', views.update_score, name='update_score'),
]
views.py
from django.http import HttpResponse
from .models import Member
def update_score(request, member_id, score_to_add):
member = Member.objects.get(pk=member_id)
member.score += score_to_add
try:
member.save
return HttpResponse("True")
except:
return HttpResponse("False")
Also you can respond with Json. Here is alternative views:
Alternative views.py
from django.http import JsonResponse
from .models import Member
def update_score(request, member_id, score_to_add):
member = Member.objects.get(pk=member_id)
member.score += score_to_add
try:
member.save
return JsonResponse({'status': True})
except:
return JsonResponse({'status': False})
But i think Django Rest Framework is a better way to do this.
You can create a view to return JsonResponse. Take example of polls app in django and convert a post view to return a JSON response.
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.http import JsonResponse
from .models import Choice, Question
# Need to disable csrf here
#csrf_exempt
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
# If you want Json requests Or you can use
# received_json_data=request.POST if you are using normal form data request.
received_json_data=json.loads(request.body)
try:
selected_choice = question.choice_set.get(pk=received_json_data['choice'])
except (KeyError, Choice.DoesNotExist):
# If failed
return JsonResponse({'result': False})
else:
selected_choice.votes += 1
selected_choice.save()
return JsonResponse({'result': True})
Although It works but I would still recommend using DRF because what you are doing needs proper REST API and DRF eases a lot of pain points.
can anyone tell me, how to make a separate Database just for Flask admin and maybe flask security?
this is how i am working with my PostgreSQL database just to load some tables and perform CRUD:
import flask_admin
from flask import Flask
from sqlalchemy import create_engine
app =Flask(__name__)
engine = create_engine{'postgresql://name:password#localhost/tablesdatabase')
i wish to make a separate database for flask-admin :( this is what i am trying)
admin = flask_admin.Admin(app)
app.config['SQLALCHEMY_BINDS'] = {'admindb' : 'postgresql://name:password#localhost/adminedatabase'}
admin.add_view(ModelView) ? // how can i impelement this ? with a seperate datbase ?
There is no official support, but you can customize Flask-SQLalchemy session to use different connections, here the example for using master slave connections, you can easily add as many connections as you want
from functools import partial
from sqlalchemy import orm
from flask import current_app
from flask_sqlalchemy import SQLAlchemy, get_state
class RoutingSession(orm.Session):
def __init__(self, db, autocommit=False, autoflush=True, **options):
self.app = db.get_app()
self.db = db
self._bind_name = None
orm.Session.__init__(
self, autocommit=autocommit, autoflush=autoflush,
bind=db.engine,
binds=db.get_binds(self.app),
**options,
)
def get_bind(self, mapper=None, clause=None):
try:
state = get_state(self.app)
except (AssertionError, AttributeError, TypeError) as err:
current_app.logger.info(
'cant get configuration. default bind. Error:' + err)
return orm.Session.get_bind(self, mapper, clause)
# If there are no binds configured, use default SQLALCHEMY_DATABASE_URI
if not state or not self.app.config['SQLALCHEMY_BINDS']:
return orm.Session.get_bind(self, mapper, clause)
# if want to user exact bind
if self._bind_name:
return state.db.get_engine(self.app, bind=self._bind_name)
else:
# if no bind is used connect to default
return orm.Session.get_bind(self, mapper, clause)
def using_bind(self, name):
bind_session = RoutingSession(self.db)
vars(bind_session).update(vars(self))
bind_session._bind_name = name
return bind_session
class RouteSQLAlchemy(SQLAlchemy):
def __init__(self, *args, **kwargs):
SQLAlchemy.__init__(self, *args, **kwargs)
self.session.using_bind = lambda s: self.session().using_bind(s)
def create_scoped_session(self, options=None):
if options is None:
options = {}
scopefunc = options.pop('scopefunc', None)
return orm.scoped_session(
partial(RoutingSession, self, **options),
scopefunc=scopefunc,
)
Than the default session will be master, when you want to select from slave you can call it directly, here the examples:
In your app:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql:///master'
app.config['SQLALCHEMY_BINDS'] = {
'slave': 'postgresql:///slave'
}
db = RouteSQLAlchemy(app)
Select from master
session.query(User).filter_by(id=1).first()
Select from slave
session.using_bind('slave').query(User).filter_by(id=1).first()
the following code throws attribute error
''Database' object has no attribute 'exists''.
from django.shortcuts import render
from django.views import View
from django.views.decorators.cache import cache_page
from django.views.decorators.csrf import csrf_protect
import pyrebase
from django.contrib import auth
import json
import requests
from . import services
from .models import Product
authe = services.firebase_key().auth()
database = services.firebase_key().database()
def Login(request):
return render(request, "Login.html")
def postsign(request):
data = services.get_products()
print(data)
context = {'data': data}
number = request.POST.get('number')
password = request.POST.get("password")
if database.child("users").child(number).exists():
user = database.child("users").child(number).get().val()
if user['number'] == number:
if user['password'] == password:
return render(request,"Welcome.html",context)
I need to check if the number exists in the database or not since I want the existing users to log in using numbers and passwords.
Check if child exist in Python using Pyrebase, should be something similar, see official docs here
if not database.child('users').shallow().get().val():
print("users does not exist")
else:
print("users exist")
You can try below.
if database.child('users').child(number).shallow().get().val():
print("user exists")
else:
print("user does not exist")