How to filter Serializers in DjangoRestFramework based on user id? - python-3.x

I'm new to django,
I can't seem to find how to return an api based on the user who requested it and created the Transaction object, can you please guide me through? I have read this, but I can't find a clear guide in the docs to update the Serializer straightaway.
In laravel, I can do:
Transaction::where('user_id', Auth::user()->id)->get();
This is my serializer:
class TransactionSerializer(serializers.HyperlinkedModelSerializer):
user = UserSerializer(read_only=True)
tags = TagShortSerializer(read_only=True, many=True)
def get_fields(self, *args, **kwargs):
# Override this method so that the list of DatabaseUsers presented in the browseable API
# is restricted to the DatabaseUsers owned by the current user.
fields = super(TransactionSerializer, self).get_fields(*args, **kwargs)
view = self.context["view"]
user = view.request.user
return Transaction.objects.filter(user=user)
class Meta:
model = Transaction
fields = ["user", "title", "amount", "category", "tags"]
My viewset:
class TransactionViewSet(viewsets.ModelViewSet):
queryset = Transaction.objects.all()
serializer_class = TransactionSerializer
permission_classes = [permissions.IsAuthenticated, IsOwner]
Currently it returns:
Complete traceback:
Environment:
Request Method: GET
Request URL: http://127.0.0.1:8000/transactions/
Django Version: 3.2.5
Python Version: 3.9.5
Installed Applications:
['djmoney',
'rest_framework',
'finance.apps.FinanceConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback (most recent call last):
File "E:\Development\Python\sharkware-api\.venv\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "E:\Development\Python\sharkware-api\.venv\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "E:\Development\Python\sharkware-api\.venv\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "E:\Development\Python\sharkware-api\.venv\lib\site-packages\rest_framework\viewsets.py", line 125, in view
return self.dispatch(request, *args, **kwargs)
File "E:\Development\Python\sharkware-api\.venv\lib\site-packages\rest_framework\views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "E:\Development\Python\sharkware-api\.venv\lib\site-packages\rest_framework\views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "E:\Development\Python\sharkware-api\.venv\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception
raise exc
File "E:\Development\Python\sharkware-api\.venv\lib\site-packages\rest_framework\views.py", line 506, in dispatch
response = handler(request, *args, **kwargs)
File "E:\Development\Python\sharkware-api\.venv\lib\site-packages\rest_framework\mixins.py", line 43, in list
return self.get_paginated_response(serializer.data)
File "E:\Development\Python\sharkware-api\.venv\lib\site-packages\rest_framework\serializers.py", line 745, in data
ret = super().data
File "E:\Development\Python\sharkware-api\.venv\lib\site-packages\rest_framework\serializers.py", line 246, in data
self._data = self.to_representation(self.instance)
File "E:\Development\Python\sharkware-api\.venv\lib\site-packages\rest_framework\serializers.py", line 663, in to_representation
return [
File "E:\Development\Python\sharkware-api\.venv\lib\site-packages\rest_framework\serializers.py", line 664, in <listcomp>
self.child.to_representation(item) for item in iterable
File "E:\Development\Python\sharkware-api\.venv\lib\site-packages\rest_framework\serializers.py", line 500, in to_representation
for field in fields:
File "E:\Development\Python\sharkware-api\.venv\lib\site-packages\rest_framework\serializers.py", line 361, in _readable_fields
for field in self.fields.values():
File "E:\Development\Python\sharkware-api\.venv\lib\site-packages\django\utils\functional.py", line 48, in __get__
res = instance.__dict__[self.name] = self.func(instance)
File "E:\Development\Python\sharkware-api\.venv\lib\site-packages\rest_framework\serializers.py", line 349, in fields
for key, value in self.get_fields().items():
Exception Type: AttributeError at /transactions/
Exception Value: 'QuerySet' object has no attribute 'items'

That is not the correct usage for get_fields. That method returns the list of fields to be used when instantiating the serializer.
What you want is to override get_queryset on your viewset:
class TransactionViewSet(viewsets.ModelViewSet):
queryset = Transaction.objects.all()
serializer_class = TransactionSerializer
permission_classes = [permissions.IsAuthenticated, IsOwner]
def get_queryset(self):
if self.request.user.is_authenticated:
return self.queryset.filter(user=self.request.user)
return Transaction.objects.none()

Related

Upload file from Django app to IBM Cloud Object Storage

I'm trying to connect a django app to IBM COS and having trouble. I'm capturing user video and want to save the file to IBM COS and the user info to Postgres also hosted on IBM. I'm able to connect from both the terminal and my app to IBM COS and move files around, but am having trouble getting the default storage configured properly. I'm using django-storages, trying to adapt the AWS configurations for IBM but I must be missing something.
This code will save the file to IBM COS, but makes no entries in the DB. The problem may be in the configuration?
Also, I am not able to manually upload a file form the django admin panel - I get a similar traceback. Thanks in advance for any help.
settings.py
# IBM STORAGE CONFIG
IBM_API_KEY_ID = 'IBM_API_KEY_ID'
IAM_SERVICE_ID = 'IAM_SERVICE_ID'
ENDPOINT = 'https://s3.us-east.cloud-object-storage.appdomain.cloud'
IBM_AUTH_ENDPOINT = 'https://iam.bluemix.net/oidc/token'
SERVICE_INSTANCE_ID = 'SERVICE_INSTANCE_ID'
IBM_STORAGE_BUCKET_NAME = 'cloud-object-storage-3u-cos-standard-77w'
AWS_S3_FILE_OVERWRITE = False
AWS_DEFAULT_ACL = None
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
models.py
class Video(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
videofilename=models.CharField(max_length=500)
videofile=models.FileField(upload_to="video/", null=True, verbose_name="")
def __str__(self):
return str(self.videofile)
views.py
class upload_to_ibm_auto(LoginRequiredMixin, CreateView):
model = Video
context_object_name = 'Videos'
form_class = VideoForm
template_name = 'app_video/upload_to_ibm_auto.html'
success_url = reverse_lazy('video_upload_local')
def form_valid(self, form):
# create connection to IBM
cos_client = ibm_boto3.client(service_name='s3',
ibm_api_key_id=settings.IBM_API_KEY_ID,
ibm_service_instance_id=settings.IAM_SERVICE_ID,
ibm_auth_endpoint=settings.IBM_AUTH_ENDPOINT,
config=Config(signature_version='oauth'),
endpoint_url=settings.ENDPOINT)
# assign variables for upload to IBM
upload_name = str(form.cleaned_data['videofilename'])
local_file_name = 'C:/zjunk/' + str(form.cleaned_data['videofile'])
userid = str(self.request.user.id)
uploadtime=str(datetime.datetime.now())
key = userid + '-' + uploadtime + '-' + upload_name
#key='test'+form.cleaned_data['videofilename']
#local_file_name=form.cleaned_data['videofile']
#Bucket=str('cloud-object-storage-3u-cos-standard-77w')
bucket = settings.IBM_STORAGE_BUCKET_NAME
print(bucket)
try:
cos_client.upload_file(Filename=local_file_name, Bucket=bucket, Key=key)
except Exception as e:
print(Exception, e)
else:
print('File Uploaded to IBM')
return super(upload_to_ibm_auto, self).form_valid(form)
Traceback:
Environment:
Request Method: POST
Request URL: http://localhost:8000/app_video_upload_to_ibm_auto/
Django Version: 3.2.6
Python Version: 3.9.1
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'drf_spectacular',
'storages',
'app_crm',
'app_video',
'app_library']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback (most recent call last):
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\views\generic\base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\contrib\auth\mixins.py", line 71, in dispatch
return super().dispatch(request, *args, **kwargs)
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\views\generic\base.py", line 98, in dispatch
return handler(request, *args, **kwargs)
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\views\generic\edit.py", line 172, in post
return super().post(request, *args, **kwargs)
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\views\generic\edit.py", line 142, in post
return self.form_valid(form)
File "C:\Users\Kord\source\repos\storyline\dev\01\PythonDjangoAppLMSUS2021-08-23-SL-1\app_video\views.py", line 163, in form_valid
return super(upload_to_ibm_auto, self).form_valid(form)
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\views\generic\edit.py", line 125, in form_valid
self.object = form.save()
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\forms\models.py", line 468, in save
self.instance.save()
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\db\models\base.py", line 726, in save
self.save_base(using=using, force_insert=force_insert,
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\db\models\base.py", line 763, in save_base
updated = self._save_table(
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\db\models\base.py", line 868, in _save_table
results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\db\models\base.py", line 906, in _do_insert
return manager._insert(
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\db\models\query.py", line 1270, in _insert
return query.get_compiler(using=using).execute_sql(returning_fields)
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\db\models\sql\compiler.py", line 1415, in execute_sql
for sql, params in self.as_sql():
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\db\models\sql\compiler.py", line 1358, in as_sql
value_rows = [
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\db\models\sql\compiler.py", line 1359, in <listcomp>
[self.prepare_value(field, self.pre_save_val(field, obj)) for field in fields]
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\db\models\sql\compiler.py", line 1359, in <listcomp>
[self.prepare_value(field, self.pre_save_val(field, obj)) for field in fields]
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\db\models\sql\compiler.py", line 1310, in pre_save_val
return field.pre_save(obj, add=True)
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\db\models\fields\files.py", line 302, in pre_save
file.save(file.name, file.file, save=False)
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\db\models\fields\files.py", line 89, in save
self.name = self.storage.save(name, content, max_length=self.field.max_length)
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\core\files\storage.py", line 53, in save
name = self.get_available_name(name, max_length=max_length)
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\storages\backends\s3boto3.py", line 585, in get_available_name
return super().get_available_name(name, max_length)
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\django\core\files\storage.py", line 87, in get_available_name
while self.exists(name) or (max_length and len(name) > max_length):
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\storages\backends\s3boto3.py", line 457, in exists
self.connection.meta.client.head_object(Bucket=self.bucket_name, Key=name)
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\botocore\client.py", line 386, in _api_call
return self._make_api_call(operation_name, kwargs)
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\botocore\client.py", line 677, in _make_api_call
request_dict = self._convert_to_request_dict(
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\botocore\client.py", line 723, in _convert_to_request_dict
api_params = self._emit_api_params(
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\botocore\client.py", line 752, in _emit_api_params
self.meta.events.emit(
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\botocore\hooks.py", line 357, in emit
return self._emitter.emit(aliased_event_name, **kwargs)
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\botocore\hooks.py", line 228, in emit
return self._emit(event_name, kwargs)
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\botocore\hooks.py", line 211, in _emit
response = handler(**kwargs)
File "C:\Users\Kord\source\repos\storyline\dev\01\venv2\lib\site-packages\botocore\handlers.py", line 235, in validate_bucket_name
if not VALID_BUCKET.search(bucket) and not VALID_S3_ARN.search(bucket):
Exception Type: TypeError at /app_video_upload_to_ibm_auto/
Exception Value: expected string or bytes-like object
Thanks again.

Unable to render template with flask wsgi [duplicate]

This question already has answers here:
Flask raises TemplateNotFound error even though template file exists
(13 answers)
Closed 2 years ago.
I have deployed a flask application, using mod_wsgi with apache2
Now, checking if everything works as intended, it looks like my endpoints which render templates are provoking some 500 status code errors.
Here's an approximative tree of my project:
main_folder
requirements.txt
mainfile.wsgi
app_folder
controllers
views.py
models
repository
services
static
templates
terms
en
terms.html
fr
terms.html
uploads
__init__.py
config.cfg
webapp.py
I am calling an endpoint which is supposed to render the templates/terms/en/terms.html and I get the following in the logs:
Traceback (most recent call last):
File "/usr/local/lib/python3.7/dist-packages/flask/app.py", line 2446, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python3.7/dist-packages/flask/app.py", line 1951, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python3.7/dist-packages/flask/app.py", line 1820, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.7/dist-packages/flask/_compat.py", line 39, in reraise
raise value
File "/usr/local/lib/python3.7/dist-packages/flask/app.py", line 1949, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python3.7/dist-packages/flask/app.py", line 1935, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/var/www/main_folder/app_folder/controllers/views.py", line 33, in gts
return render_template('terms/' + lang + '/terms.html')
File "/usr/local/lib/python3.7/dist-packages/flask/templating.py", line 138, in render_template
ctx.app.jinja_env.get_or_select_template(template_name_or_list),
File "/usr/local/lib/python3.7/dist-packages/jinja2/environment.py", line 869, in get_or_select_template
return self.get_template(template_name_or_list, parent, globals)
File "/usr/local/lib/python3.7/dist-packages/jinja2/environment.py", line 830, in get_template
return self._load_template(name, self.make_globals(globals))
File "/usr/local/lib/python3.7/dist-packages/jinja2/environment.py", line 804, in _load_template
template = self.loader.load(self, name, globals)
File "/usr/local/lib/python3.7/dist-packages/jinja2/loaders.py", line 113, in load
source, filename, uptodate = self.get_source(environment, name)
File "/usr/local/lib/python3.7/dist-packages/flask/templating.py", line 60, in get_source
return self._get_source_fast(environment, template)
File "/usr/local/lib/python3.7/dist-packages/flask/templating.py", line 89, in _get_source_fast
raise TemplateNotFound(template)
jinja2.exceptions.TemplateNotFound: terms/en/terms.html
Here's an excerp of the code where I try to render the template in app_folder/controllers/views.py:
from flask import render_template, request, send_file
from app_folder.controllers import Controllers as controllers
def gts(lang='fr'):
return render_template('terms/' + lang + '/terms.html')
controllers().register(
'/cgu/<string:lang>',
'cgu_lang',
gts
)
I want to specify that endpoints with JSON body results are functionning, uploading ressources are working as well, and getting an uploaded ressource is working.
Only endpoints which should render templates are not working, which is getting me worried as well for endpoints which should send emails using an email template
Is there any fix I should apply when serving the application with wsgi?
Edit: FYI, this is the __init__.py in the controllers folder
import pkgutil
METHODS = set([
'GET',
'POST',
'PUT',
'PATCH',
'DELETE',
'COPY',
'HEAD',
'OPTIONS',
'LINK',
'UNLINK',
'PURGE',
'LOCK',
'UNLOCK',
'PROPFIND',
'VIEW'
])
class Controllers:
class __OnlyOne:
# ======================================================
# the code goes here
# =======================================================
def __init__(self):
self.val = None
self.rules = []
def __str__(self):
return 'self' + self.val
def register(self, rule, view_name, view_func):
r = {}
r["rule"] = rule
r["view_name"] = view_name
r["view_func"] = view_func
self.rules.append(r)
def register_methods(self, rule, view_name, view_func, methods=METHODS):
r = {}
r["rule"] = rule
r["view_name"] = view_name
r["view_func"] = view_func
r["methods"] = methods
self.rules.append(r)
def grab(self, app):
for r in self.rules:
if "methods" not in r.keys():
app.add_url_rule(r["rule"], r["view_name"], r["view_func"])
else:
app.add_url_rule(r["rule"], r["view_name"],
r["view_func"], methods=r["methods"])
# =================================================================
# the code goes up there
# ==================================================================
instance = None
def __new__(cls): # __new__ always a classmethod
if not Controllers.instance:
Controllers.instance = Controllers.__OnlyOne()
return Controllers.instance
def __getattr__(self, name):
return getattr(self.instance, name)
def __setattr__(self, name):
return setattr(self.instance, name)
# import all the modules in folder
__all__ = []
for loader, module_name, is_pkg in pkgutil.walk_packages(__path__):
__all__.append(module_name)
_module = loader.find_module(module_name).load_module(module_name)
globals()[module_name] = _module
I symlinked my app_folder/templates into my main_folder and it's now working

Django-rest-framework: Authentication/permissions error: TypeError: 'str' object is not callable

I am trying to learn about django-rest-framework and I am stuck in the authentication/permissions processes. I hope someone could help me. Below is my code:
settings.py
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'drones.custompagination.LimitOffsetPaginationWithUpperBound',
'PAGE_SIZE': 4,
'DEFAULT_FILTER_BACKENDS': (
'django_filters.rest_framework.DjangoFilterBackend',
'rest_framework.filters.OrderingFilter',
'rest_framework.filters.SearchFilter',
),
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
]
}
models.py
class Drone(models.Model):
name = models.CharField(max_length=250,
unique=True)
drone_category = models.ForeignKey(DroneCategory,
related_name='drones',
on_delete=models.CASCADE)
manufacturing_date = models.DateTimeField()
has_it_competed = models.BooleanField(default=False)
inserted_timestamp = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(
'auth.User',
related_name='drones',
on_delete=models.CASCADE)
class Meta:
ordering = ('name',)
def __str__(self):
return self.name
views.py
class DroneList(generics.ListCreateAPIView):
queryset = Drone.objects.all()
serializer_class = DroneSerializer
name = 'drone-list'
permission_classes = (
'permissions.IsAuthenticatedOrReadOnly',
'custompermission.IsCurrentUserOwnerOrReadOnly',
)
filterset_fields = (
'name',
'drone_category',
'manufacturing_date',
'has_it_competed',
)
search_fileds = (
'name',
)
ordering_fields = (
'name',
'manufacturing_date',
)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
class DroneDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Drone.objects.all()
serializer_class = DroneSerializer
name = 'drone-detail'
permission_classes = (
'permissions.IsAuthenticatedOrReadOnly',
'custompermission.IsCurrentUserOwnerOrReadOnly',
)
custompermission.py
from rest_framework import permissions
class IsCurrentUserOwnerOrReadOnly(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
if request.method in permissions.SAFE_METHODS:
# The method is a safe method
return True
else:
# The method is not a safe method
# Only owners are granted permissions
return obj.owner == request.user
And and below is the error that django is throwing:
[03/Nov/2019 18:01:42] "GET / HTTP/1.1" 200 10070
Internal Server Error: /drones/
Traceback (most recent call last):
File "/home/martin/python/learn_rest/lib/python3.5/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/home/martin/python/learn_rest/lib/python3.5/site-packages/django/core/handlers/base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/martin/python/learn_rest/lib/python3.5/site-packages/django/core/handlers/base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/martin/python/learn_rest/lib/python3.5/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/home/martin/python/learn_rest/lib/python3.5/site-packages/django/views/generic/base.py", line 71, in view
return self.dispatch(request, *args, **kwargs)
File "/home/martin/python/learn_rest/lib/python3.5/site-packages/rest_framework/views.py", line 505, in dispatch
response = self.handle_exception(exc)
File "/home/martin/python/learn_rest/lib/python3.5/site-packages/rest_framework/views.py", line 465, in handle_exception
self.raise_uncaught_exception(exc)
File "/home/martin/python/learn_rest/lib/python3.5/site-packages/rest_framework/views.py", line 476, in raise_uncaught_exception
raise exc
File "/home/martin/python/learn_rest/lib/python3.5/site-packages/rest_framework/views.py", line 493, in dispatch
self.initial(request, *args, **kwargs)
File "/home/martin/python/learn_rest/lib/python3.5/site-packages/rest_framework/views.py", line 411, in initial
self.check_permissions(request)
File "/home/martin/python/learn_rest/lib/python3.5/site-packages/rest_framework/views.py", line 331, in check_permissions
for permission in self.get_permissions():
File "/home/martin/python/learn_rest/lib/python3.5/site-packages/rest_framework/views.py", line 278, in get_permissions
return [permission() for permission in self.permission_classes]
File "/home/martin/python/learn_rest/lib/python3.5/site-packages/rest_framework/views.py", line 278, in <listcomp>
return [permission() for permission in self.permission_classes]
TypeError: 'str' object is not callable
[03/Nov/2019 18:01:45] "GET /drones/ HTTP/1.1" 500 107476
Python version: 3.5.3
Django version: 2.2.6
Django Rest Framework version: 3.10.3
I have been searching here for other people having the same problem, but none of the solutions provided seem to work for this particular case
Thank you so much in advance for your help
Try to set the value of permission_classes to the permission classes directly, something like:
from rest_framework import permissions
#import your custome permission module
class DroneDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Drone.objects.all()
serializer_class = DroneSerializer
name = 'drone-detail'
permission_classes = (
permissions.IsAuthenticatedOrReadOnly,
custompermission.IsCurrentUserOwnerOrReadOnly,
)

How do I use a Custom Provider [keycloak] for OAuth2.0 in Flask-Appbuilder?

I am trying to implement keycloak as a OAuth2.0 provider. I have all the necessary OAUTH_PROVIDER information and I have declared the AUTH_TYPE, AUTH_USER_REGISTRATION, AUTH_USER_REGISTRATION_ROLE (See code below)
AUTH_TYPE = AUTH_OAUTH
AUTH_USER_REGISTRATION = True
AUTH_USER_REGISTRATION_ROLE = "Public"
OAUTH_PROVIDERS = [
{
‘name’: ‘provider_name’,
‘icon’: ‘fa-icon’,
’token_key’: ‘access_token’,
‘remote_app’: {
‘base_url’: ‘https://www.base_url.com‘,
‘request_token_params’: {
‘scope’: ‘email profile’
},
‘request_token_url’: None,
‘access_token_url’: ‘https://www.access_token_url.com’,
‘authorize_url': ‘https://www.authorize_url.com',
‘consumer_key’: ‘PROVIDER_OAUTH_KEY’,
‘consumer_secret’: ‘PROVIDER_OAUTH_SECRET’
}
}
]
Because this is a custom provider (apart from the usual google, facebook, ... providers), in my security manager I have overridden the get_oauth_user_info function that is declared in the flask-appbuilder manager.py
def get_oauth_user_info(self, provider, response=None):
logging.debug("Oauth2 provider: {0}.".format(provider))
me = self.appbuilder.sm.oauth_remotes[provider].get("user")
logging.error(me)
return {
"preferred_username": me.data.get("preferred_username",""),
"first_name": me.data.get("given_name", ""),
"last_name": me.data.get("family_name", ""),
"email": me.data.get("email", "")
I expect results the application to be redirected to the keycloak login page, however the following error is thrown on the post request:
DEBUG:flask_oauthlib:Request 'https://...' with 'POST' method
ERROR:flask_appbuilder.security.manager:User info does not have username or email {}
[2019-05-23 12:52:10,130] ERROR in app: Exception on /oauth-authorized/login [GET]
Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/usr/local/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
raise value
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python3.6/site-packages/flask/app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/usr/local/lib/python3.6/site-packages/flask_appbuilder/security/views.py", line 519, in oauth_authorized
resp = self.appbuilder.sm.oauth_remotes[provider].authorized_response()
If anyone has some pointers as to what I am doing wrong please could you assist me.
You should add annotation #appbuilder.sm.oauth_user_info_getter to the get_oauth_user_info func like in the docs https://flask-appbuilder.readthedocs.io/en/latest/security.html#authentication-oauth
Also change
me = self.appbuilder.sm.oauth_remotes[provider].get("user")
to
me = self.appbuilder.sm.oauth_remotes[provider].get("userinfo")
in case if base_url is like https://{keycloak-domain}/auth/realms/{realm}/protocol/openid-connect/

How do I get $near to work in Flask-mongoalchemy

I have been trying to work on fetching events from my mongoDB database that are close to the current user's location
I have tried to reformat my Model scheme to contain [type: "Point"] and even arranged my longitude and latitude into a list.
I also tried adding "2dsphere" indexes using meta to my Model based on what I saw in mongo-alchemy documentation.
My Model
class Event(db.Document):
meta = {
'indexes': [
("*location.coordinates", "2dsphere")
]
}
user_id = db.StringField()
uuid = db.StringField()
name = db.StringField()
address = db.StringField()
start_time = db.DateTimeField(required=True, default=datetime.datetime.now())
end_time = db.DateTimeField(required=True, default=datetime.datetime.now())
location = db.DictField(db.AnythingField())
This is now my main query code
def get(self):
latitude = float(request.args.get('lat'))
longitude = float(request.args.get('long'))
print(longitude);
print(latitude);
event = Event.query.filter({"location" :
{ "$near" :
{
"$geometry" : {
"type" : "Point",
"coordinates" : [longitude, latitude] },
"$maxDistance" : 4000
}
}
}).first()
print(event);
[2019-01-15 23:20:59,797] ERROR in app: Exception on /v1/event [GET]
Traceback (most recent call last):
File "/home/creative_joe/.local/lib/python3.5/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/home/creative_joe/.local/lib/python3.5/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functionsrule.endpoint
File "/home/creative_joe/.local/lib/python3.5/site-packages/flask_restplus/api.py", line 325, in wrapper
resp = resource(*args, **kwargs)
File "/home/creative_joe/.local/lib/python3.5/site-packages/flask/views.py", line 88, in view
return self.dispatch_request(*args, **kwargs)
File "/home/creative_joe/.local/lib/python3.5/site-packages/flask_restplus/resource.py", line 44, in dispatch_request
resp = meth(*args, **kwargs)
File "/media/creative_joe/3004586c-9a2d-4cb0-8a5f-d41fe99afc05/home/creative_joe/MonkeyMusic.server/app/views/main.py", line 323, in get
"$maxDistance" : 4000
File "/home/creative_joe/.local/lib/python3.5/site-packages/mongoalchemy/query.py", line 139, in first
for doc in iter(self):
File "/home/creative_joe/.local/lib/python3.5/site-packages/mongoalchemy/query.py", line 412, in next
return self._next_internal()
File "/home/creative_joe/.local/lib/python3.5/site-packages/mongoalchemy/query.py", line 416, in _next_internal
value = next(self.cursor)
File "/home/creative_joe/.local/lib/python3.5/site-packages/mongoalchemy/py3compat.py", line 41, in next
return it.next()
File "/home/creative_joe/.local/lib/python3.5/site-packages/pymongo/cursor.py", line 1189, in next
if len(self.__data) or self._refresh():
File "/home/creative_joe/.local/lib/python3.5/site-packages/pymongo/cursor.py", line 1104, in _refresh
self.__send_message(q)
File "/home/creative_joe/.local/lib/python3.5/site-packages/pymongo/cursor.py", line 982, in __send_message
helpers._check_command_response(first)
File "/home/creative_joe/.local/lib/python3.5/site-packages/pymongo/helpers.py", line 155, in _check_command_response
raise OperationFailure(msg % errmsg, code, response)
pymongo.errors.OperationFailure: error processing query: ns=heroku_c9gg06k0.EventTree: GEONEAR field=location maxdist=4000 isNearSphere=0
Sort: {}
Proj: {}
planner returned error: unable to find index for $geoNear query

Resources