I am trying to implement logging in my Django project (django 1.11, Python 3.6). I'm using default django logger.
To get the username in log, I have used django-requestlogging 1.0.1.
As of now, I don't have any user other than admin superuser.
When I'm trying a GET request on front-end side, an error occurs that says 'LogSetupMiddleware' is not callable.
What is the reason for this error? How do I make the logging work?
How do I get AnonymousUser in the logs?
File settings.py snippet:
INSTALLED_APPS= [
...
'django_requestlogging',
]
MIDDLEWARE = [
...
'django_requestlogging.middleware.LogSetupMiddleware',
...
]
LOGGING = {
'version': 1,
'formatters': {
'standard' : {
'format': '%(asctime)s %(username)s %(request_method)s',
},
},
}
As I can see here middleware class is really not callable. To fix it you have to override that class like this:
some/middlware/path.py
from django.utils.deprecation import MiddlewareMixin
from django_requestlogging.middleware import LogSetupMiddleware as Original
class LogSetupMiddleware(MiddlewareMixin, Original):
pass
And replace middleware path in settings.py by new one:
some.middleware.path.LogSetupMiddleware
Related
I'm new to django and got struck with csrf tokens. I'm making a post request from android using retrofit to my django server which is using csrf protection. I had obtained the csrf token by making a get request first and then I'm passing this csrftoken from the body of POST request. However, my server is showing 'CSRF cookie not set' error. The server is responding well to the calls from POSTMAN but when I make calls from android, I get this error. I think there is some simple thing I'm missing, but I'm not able to figure it out.
Session based authorization is usually used in web-apps. In case of android apps which are backed by API.
So rather than you can do Token Based Authorization using rest_framework in Django.
In your settings.py
INSTALLED_APPS = [
...
'rest_framework',
]
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication', # <-- And here
],
}
Now migrate the migrations to the database.
python manage.py migrate
Run this command to generate token for the specific user.
python manage.py drf_create_token <username>
Now add this line to urls.py.
from rest_framework.authtoken.views import obtain_auth_token
urlpatterns = [
#Some other urls.
path('api-token-auth/', obtain_auth_token, name='api_token_auth'),
]
Using this you can obtain token for any user by using its username & password by just passing them in request body.
So this will be our protected api. Add this class based view in your views.py
from rest_framework.permissions import IsAuthenticated,AllowAny # <-- Here
from rest_framework.views import APIView
from rest_framework.response import Response
class DemoData(APIView):
permission_classes = (IsAuthenticated,)
def post(self, request):
content = {'data': 'Hello, World!'}
return Response(content)
Now pass a header with the api name as 'Authorization' & value be like something 'Token 5a2b846d267f68be68185944935d1367c885f360'
This is how we implement Token Authentication/Authorization in Django.
For more info, click here to see official documentation.
I recently asked a question about Django Two Factor authentication here...Django Two Factor Authentication. Based on the feedback I received I am trying to deploy it in my project. I have read the basic installation instructions, but I can't quite figure out how to get it to work in my project...
I have installed it via...
pip install django-two-factor-auth
Then I added it to my settings.py file...
INSTALLED_APPS = (
...
'django_otp',
'django_otp.plugins.otp_static',
'django_otp.plugins.otp_totp',
'two_factor',
)
And I have added it to my settings.py file...
from django.core.urlresolvers import reverse_lazy
LOGIN_URL = reverse_lazy('two_factor:login')
# this one is optional
LOGIN_REDIRECT_URL = reverse_lazy('two_factor:profile')
And I have added it to my urls.py file...
urlpatterns = patterns(
'',
url(r'', include('two_factor.urls', 'two_factor')),
...
)
I was using the LoginView from from django.contrib.auth.views via the following import...
from django.contrib.auth.views import LoginView
I since have changed it to subclass LoginView from two_factor as shown below:
from two_factor.views import LoginView
Then I set up a two_factor/_base.html file in my project directory...
But when I enter the initial credentials of username and password, I get the following message...
SuspiciousOperation at /project/login/
ManagementForm data is missing or has been tampered.
I'm not sure if any more detailed instructions are available...but I've followed what was there and can't seem to figure out how to get this up and going...
For the record, I'm trying to figure out how to incorporate the two factor authentication at the time the user logs in, and then they have to enter a pin number as an example. I'm also trying to force the user at registration time to set this up as a mandatory login method. I realize now that the LoginView that I'm using is incorrect. I need to figure out how to get this properly set up when the user initially registers.
Not sure where to go next with this. Thanks in advance for any thoughts.
After a lot of trial and error...I figured out that I needed to update my settings.py file to account for the fake gateways and I needed to incorporate the logging code to turn on the information messages...
Here is the link to the page that I referenced...
https://django-two-factor-auth.readthedocs.io/en/stable/configuration.html
Once I added the code below to my settings.py file...I was able to get 2FA up and running...
TWO_FACTOR_CALL_GATEWAY = 'two_factor.gateways.fake.Fake'
TWO_FACTOR_SMS_GATEWAY = 'two_factor.gateways.fake.Fake'
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
},
},
'loggers': {
'two_factor': {
'handlers': ['console'],
'level': 'INFO',
}
}
}
I have integrated swagger with django rest framework, but the swagger docs does not create a input box to post data for post request.
I am using Function based views with decorator(#api_view)
#api_view(['GET','POST'])
#permission_classes((AllowAny, ))
#renderer_classes([OpenAPIRenderer, SwaggerUIRenderer])
def preferences(request,format=None):
try:
"logic starts here "
in urls.py i have added:
schema_view = get_swagger_view(title='API')
path('', schema_view, name="schema_view"),
in settings.py :
SWAGGER_SETTINGS = {
'USE_SESSION_AUTH': False,
'JSON_EDITOR': True,
'api_version': '0.1',
'enabled_methods': [
'GET',
'POST',
],
'SECURITY_DEFINITIONS': {
"api_key": {
"type": "apiKey",
"name": "Authorization",
"in": "header"
},
},
}
But, when i open the api url i'm getting something like this (in image) where i'm unable to pass the parameters through post
what can be the problem here?is there any other changes to be done ?
When you click on the Try it Out link, you should get an input to fill in the POST data
make sure the class is imported from the generics API, example:
from rest_framework import generics
class Something (generics.GenericAPIView):
serializer_class=SomeSerializer
def post(self,request):
pass
I have a Django app which requires Postgres' fuzzystrmatch extension to be enabled on the database.
Django's unittest framework creates and destroys a new database. I need this new database to have the extension turned on for testing.
I can use './manage.py test --keepdb' to keep the database and then manually turn on the extension, but this is an ineloquent solution.
Any idea how I can enable this extension programmatically?
Create an empty migration and use the CreateExtension operation:
from django.contrib.postgres.operations import CreateExtension
class Migration(migrations.Migration):
...
operations = [
CreateExtension(name='fuzzystrmatch'),
...
]
Relevant docs
Edit:
If that doesn't work, reviewing how Django actually handles those classes internally would be my next suggestion.
In case you've disabled the migrations in the test settings, the migrations will not be run, so you can't use django CreateExtension.
Example:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
"NAME": "test-database",
"USER": "username",
"PASSWORD": "password",
"HOST": "postgresql-host",
"PORT": "5432",
"TEST": {
"MIGRATE": False,
},
},
}
In this case you can manually call SQL code to create the extension.
If you use unitest, you can for example create a custom TestCase class inherited by all your tests like so:
from django.test import TestCase from django.db import connection
class PostgresExtensionTestCase(TestCase):
#classmethod
def setUpClass(cls):
with connection.cursor() as cursor:
cursor.execute("CREATE EXTENSION IF NOT EXISTS unaccent;")
super().setUpClass()
If you use pytest, you can create a fixture in your conftest.py like so (for unaccent in the example):
from django.db import connection
#pytest.fixture(autouse=True)
def activate_postgresql_unaccent():
with connection.cursor() as cursor:
cursor.execute("CREATE EXTENSION IF NOT EXISTS unaccent;")
I have a custom configuration for logs in views.py as below:
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
# Handlers
log_handlers = {
"terminal": logging.StreamHandler(),
"file_debug": logging.FileHandler("/var/log/eshot-api/{name}-{level}.log".format(name=__name__, level="DEBUG"), mode="w"),
"file_error": logging.FileHandler("/var/log/eshot-api/{name}-{level}.log".format(name=__name__, level="ERROR"), mode="w")
}
log_handlers["terminal"].setLevel(logging.INFO)
log_handlers["file_debug"].setLevel(logging.DEBUG)
log_handlers["file_error"].setLevel(logging.ERROR)
# Formatters
log_formatters = {
"terminal": logging.Formatter("[%(name)s]::[%(levelname)s]#[%(asctime)s]: %(message)s"),
"file_debug": logging.Formatter("[%(levelname)s]#[%(asctime)s]: %(message)s"),
"file_error": logging.Formatter("[%(asctime)s]: %(message)s")
}
for k, v in log_formatters.items():
log_handlers[k].setFormatter(v)
I have created a directory as /var/log/eshot-api and given permission as chmod 777 to that directory so that there will be no problem for writing.
I've also created a function as below:
def initial_log(request, method):
logger.debug("{ip} requested {path} with {kwargs} in {method} method".format(ip=ipaddr(request), path=request.get_full_path(), kwargs=str(dict(request.GET)), method=method))
method argument is a string to pass "GET" or "POST" to this function.
And I've put this at the beginning to my all get function of ClassBasedView. However, when I run and refresh a page a couple of time in order to generate some logs and look into my log files, they are empty.
And, I want to mention that this is a development server in my own computer.
Environment
django 1.9.6
ubuntu 14.04
python 3.5.1
Check your settings.py for a LOGGING = {...} setting and make sure that it has disable_existing_loggers set to False:
LOGGING = {
...
'disable_existing_loggers': False,
..
}
Or remove the LOGGING setting completely. And add handlers to the logger:
logger.addHandler(log_handlers["file_debug"])
Also i'de like to advise you to configure LOGGING in your settings.py.
Fully working example
urls.py:
from django.conf.urls import url
from .views import IndexView
urlpatterns = [
url(r'^$', IndexView.as_view()),
]
views.py:
import logging
from django.http import HttpResponse
from django.views.generic import View
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
# Handlers
log_handlers = {
"terminal": logging.StreamHandler(),
"file_debug": logging.FileHandler("/var/log/eshot-api/{name}-{level}.log".format(name=__name__, level="DEBUG"), mode="w"),
"file_error": logging.FileHandler("/var/log/eshot-api/{name}-{level}.log".format(name=__name__, level="ERROR"), mode="w")
}
log_handlers["terminal"].setLevel(logging.INFO)
log_handlers["file_debug"].setLevel(logging.DEBUG)
log_handlers["file_error"].setLevel(logging.ERROR)
# Formatters
log_formatters = {
"terminal": logging.Formatter("[%(name)s]::[%(levelname)s]#[%(asctime)s]: %(message)s"),
"file_debug": logging.Formatter("[%(levelname)s]#[%(asctime)s]: %(message)s"),
"file_error": logging.Formatter("[%(asctime)s]: %(message)s")
}
for k, v in log_formatters.items():
log_handlers[k].setFormatter(v)
logger.addHandler(log_handlers['file_debug'])
class IndexView(View):
def get(self, request):
logger.debug("requested {path} with {kwargs} in method".format(path=request.get_full_path(), kwargs=str(dict(request.GET))))
return HttpResponse('app:index')
settings.py
LOGGING = {
'disable_existing_loggers': False,
}