Code Monkey home page Code Monkey logo

drf-tracking's Introduction

PROJECT IS DEAD! PLEASE GO TO NEW LOCATION:

Work has moved to a fork to continue on https://github.com/lingster/drf-api-tracking

drf-tracking

build-status-image pypi-version Requirements Status Coverage Status

Overview

drf-tracking provides a Django model and DRF view mixin that work together to log Django Rest Framework requests to the database. You'll get these attributes for every request/response cycle to a view that uses the mixin:

Model field name Description Model field type
user User if authenticated, None if not Foreign Key
requested_at Date-time that the request was made DateTimeField
response_ms Number of milliseconds spent in view code PositiveIntegerField
path Target URI of the request, e.g., "/api/" CharField
view Target VIEW of the request, e.g., "views.api.ApiView" CharField
view_method Target METHOD of the VIEW of the request, e.g., "get" CharField
remote_addr IP address where the request originated (X_FORWARDED_FOR if available, REMOTE_ADDR if not), e.g., "127.0.0.1" GenericIPAddressField
host Originating host of the request, e.g., "example.com" URLField
method HTTP method, e.g., "GET" CharField
query_params Dictionary of request query parameters, as text TextField
data Dictionary of POST data (JSON or form), as text TextField
response JSON response data TextField
status_code HTTP status code, e.g., 200 or 404 PositiveIntegerField

Requirements

  • Django 1.11, 2.0, 2.1, 2.2, 3.0
  • Django REST Framework and Python release supporting the version of Django you are using
Django Python DRF
1.11 2.7, 3.4, 3.5, 3.6 3.5, 3.6, 3.7, 3.8, 3.9
2.0 3.4, 3.5, 3.6, 3.7 3.7, 3.8, 3.9
2.1 3.5, 3.6, 3.7 3.7, 3.8, 3.9
2.2 3.5, 3.6, 3.7 3.7, 3.8, 3.9
3.0 3.5, 3.6, 3.7 3.7, 3.8, 3.9

Installation

Install using pip...

$ pip install drf-tracking

Register with your Django project by adding rest_framework_tracking to the INSTALLED_APPS list in your project's settings.py file. Then run the migrations for the APIRequestLog model:

$ python manage.py migrate

Usage

Add the rest_framework_tracking.mixins.LoggingMixin to any DRF view to create an instance of APIRequestLog every time the view is called.

For instance:

# views.py
from rest_framework import generics
from rest_framework.response import Response
from rest_framework_tracking.mixins import LoggingMixin

class LoggingView(LoggingMixin, generics.GenericAPIView):
    def get(self, request):
        return Response('with logging')

For performance enhancement, explicitly choose methods to be logged using logging_methods attribute:

class LoggingView(LoggingMixin, generics.CreateModelMixin, generics.GenericAPIView):
    logging_methods = ['POST', 'PUT']
    model = ...

Moreover, you could define your own rules by overriding should_log method. If should_log evaluates to True a log is created.

class LoggingView(LoggingMixin, generics.GenericAPIView):
    def should_log(self, request, response):
        """Log only errors"""
        return response.status_code >= 400

At the example above, logging_methods attribute will be ignored. If you want to provide some extra rules on top of the http method filtering you should rewrite the should_log method.

class LoggingView(LoggingMixin, generics.GenericAPIView):
    def should_log(self, request, response):
        """Log only errors with respect on `logging_methods` attributes"""
        should_log_method = super(LoggingView, self).should_log(request, response)
        if not should_log_method:
            return False
        return response.status_code >= 400

A bit simpler.

class LoggingView(LoggingMixin, generics.GenericAPIView):
   def should_log(self, request, response):
       """Log only errors with respect on `logging_methods` attributes"""
       if not request.method in self.logging_methods:
           return False
       return response.status_code >= 400

Finally, you can also apply your customizations by overriding handle_log method. By default, all requests that satisfy should_log method are saved on the database.

class LoggingView(LoggingMixin, generics.GenericAPIView):
    def handle_log(self):
        # Do some stuff before saving.
        super(MockCustomLogHandlerView, self).handle_log()
        # Do some stuff after saving.

Though, you could define your own handling. For example save on an in-memory data structure store, remote logging system etc.

class LoggingView(LoggingMixin, generics.GenericAPIView):

    def handle_log(self):
        cache.set('my_key', self.log, 86400)

Or you could omit save a request to the database. For example,

class LoggingView(LoggingMixin, generics.GenericAPIView):
    def handle_log(self):
        """
        Save only very slow requests. Requests that took more than a second.
        """
        if self.log['response_ms'] > 1000:
            super(MockCustomLogHandlerView, self).handle_log()

Security

By default drf-tracking is hiding the values of those fields {'api', 'token', 'key', 'secret', 'password', 'signature'}. The default list hast been taken from Django itself (https://github.com/django/django/blob/stable/1.11.x/django/contrib/auth/init.py#L50).

You can complet this list with your own list by putting the fields you want to be hidden in the sensitive_fields parameter of your view.

class LoggingView(LoggingMixin, generics.CreateModelMixin, generics.GenericAPIView):
    sensitive_fields = {'my_secret_key', 'my_secret_recipe'}

Testing

Install testing requirements.

$ pip install -r requirements.txt

Run with runtests.

$ ./runtests.py

You can also use the excellent tox testing tool to run the tests against all supported versions of Python and Django. Install tox globally, and then simply run:

$ tox

Documentation

To build the documentation, you'll need to install mkdocs.

$ pip install mkdocs

To preview the documentation:

$ mkdocs serve
Running at: http://127.0.0.1:8000/

To build the documentation:

$ mkdocs build

drf-tracking's People

Contributors

aicioara avatar aschn avatar avelis avatar brett-matthews avatar dependabot[bot] avatar fichie23 avatar frankie567 avatar gbataille avatar gingerjoos avatar itcrab avatar jameshiew avatar jemerick avatar lingster avatar madisvain avatar mayankkapoor avatar missfilly avatar null-none avatar rib3 avatar rnegron avatar tilboerner avatar tomage avatar tselepakis avatar umr55766 avatar vincentstark avatar vycius avatar yrchen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

drf-tracking's Issues

Log custom Headers information

Hi
If possible to log custom headers information? I want to track secret keys which are part of the Post header.

Thanks

Makes only one documentation aka README vs ReadTheDoc

I saw (partially my fault) that the doc on Read the doc the latest changes has not always been put there. I think that having it twice doesn't help to maintain it.

I would suggest we remove one to keep everything up-to-date in only one place.

WDYT

AttributeError: 'Request' object has no attribute 'log' on TestCase

Hello, I have stumbled upon the same thing on my test suite. I'm testing accessing the given resource without authentication.

class DriverReadFailureTests(APITestCase):
    def setUp(self):
        self.client = APIClient()
        self.user = User.objects.create_superuser('admin', '[email protected]', 'admin123')
        self.client.force_login(user=self.user)
        self.token = Token.objects.create(user=self.user)
        self.client.post('/api/drivers/', data=driver_data, format='json')
        self.client.post('/api/drivers/', data=driver_data_second, format='json')
        self.client.logout()

    def test_read_no_auth_driver(self):
        """Try to retrieve json representation of previously added driver.
        """
        response = self.client.get('/api/drivers/')
        self.assertEqual(response.status_code, 401)

Traceback:
Error

Traceback (most recent call last):
  File "/home/bkovacev/sally-projects/ops4/drivers/tests.py", line 316, in test_read_no_auth_driver
    response = self.client.get('/api/drivers/')
  File "/home/bkovacev/envs/ops4-env/local/lib/python2.7/site-packages/rest_framework/test.py", line 282, in get
    response = super(APIClient, self).get(path, data=data, **extra)
  File "/home/bkovacev/envs/ops4-env/local/lib/python2.7/site-packages/rest_framework/test.py", line 208, in get
    return self.generic('GET', path, **r)
  File "/home/bkovacev/envs/ops4-env/local/lib/python2.7/site-packages/django/test/client.py", line 409, in generic
    return self.request(**r)
  File "/home/bkovacev/envs/ops4-env/local/lib/python2.7/site-packages/rest_framework/test.py", line 279, in request
    return super(APIClient, self).request(**kwargs)
  File "/home/bkovacev/envs/ops4-env/local/lib/python2.7/site-packages/rest_framework/test.py", line 231, in request
    request = super(APIRequestFactory, self).request(**kwargs)
  File "/home/bkovacev/envs/ops4-env/local/lib/python2.7/site-packages/django/test/client.py", line 494, in request
    six.reraise(*exc_info)
  File "/home/bkovacev/envs/ops4-env/local/lib/python2.7/site-packages/django/core/handlers/exception.py", line 42, in inner
    response = get_response(request)
  File "/home/bkovacev/envs/ops4-env/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/home/bkovacev/envs/ops4-env/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/bkovacev/envs/ops4-env/local/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
    return view_func(*args, **kwargs)
  File "/home/bkovacev/envs/ops4-env/local/lib/python2.7/site-packages/django/views/generic/base.py", line 68, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/bkovacev/envs/ops4-env/local/lib/python2.7/site-packages/rest_framework/views.py", line 483, in dispatch
    response = self.handle_exception(exc)
  File "/home/bkovacev/envs/ops4-env/local/lib/python2.7/site-packages/rest_framework_tracking/mixins.py", line 80, in handle_exception
    self.request.log.errors = traceback.format_exc()
  File "/home/bkovacev/envs/ops4-env/local/lib/python2.7/site-packages/rest_framework/request.py", line 384, in __getattribute__
    six.reraise(info[0], info[1], info[2].tb_next)
  File "<string>", line 2, in reraise
AttributeError: 'Request' object has no attribute 'log'

How do I approach this?

Log Construction

More of a question, rather than an issue. Why is the majority of the log construction performed in finalize_response() as opposed to initial() ?

Im looking to log the request when an unexpected exception is thrown, having the log constructed in initial() will pack up all the request information.

SyntaxError: invalid token

Exception occurs while presence in request, for example, dates:

    def test_log_params(self):
        self.client.get('/logging', {'p1': 'a', 'another': '2', 'date_field': '1970-01-01'})
        log = APIRequestLog.objects.first()
        self.assertEqual(ast.literal_eval(log.query_params), {
            u'p1': u'a', u'another': u'2', u'date_field': u'1970-01-01'})

Also, why user can not change SENSITIVE_FIELDS by self? Currently, field named, for example, 'is_secretary' leads to broken request handling.

Users not deletable anymore - Change on_delete

Introducing on_delete=models.PROTECT for the ApiRequestLog object in response to #91 makes it impossible to delete users without deleting every single related API request manually beforehand.

Please change the behaviour to on_delete=models.CASCADE, which makes sure that users can be deleted and all related API request logs will be also removed in the process.

Alternatively SET_NULL would also be an option, if you want to keep the request logs intact also after user deletion.

Suggestions for admin.py

I noticed that the APIRequestLogAdmin class allows users to add and edit records. If that's not needed, I would suggest making all of the fields read-only and adding this:

def has_add_permission(self, request):
    return False

If it is needed then could it be a setting so that developers can more easily disable the adding and editing of records? Probably two settings, actually (one for adding and one for editing).

As for deleting, I can see why that hasn't been disabled as people may want to delete records from the admin. This might be another thing to be made into a setting, though, since some developers may want to delete records on a schedule instead and disallow deleting from the admin.

Latest Release doesn't have latest code

  • I have installed latest Release 1.3.1 but it don't have latest code as you have in your master branch.

e.g.,

  1. Earlier you have _clean_data as separate function but now you have moved it to class function and modified it too. Release 1.3.1 still have old code for this function (I have checked source code of Release too)
  2. The actual error I was getting is TypeError: expected string or bytes-like object in line No 137 if SENSITIVE_DATA.search(key):
  3. So when I checked installed Lib code and Master branch code, It was different.
  4. So please update Release code and also check if New code can fix my original error which is mentioned in 2nd point .
  5. Here data is a list of dict()
[   {
       "actor_type": "tets",
       "meeting_with": "Self",
       "first_name": "qwert",
       "last_name": "asdfg",
       "logged_at": "1448113944"
   }
   ]

I want request.data. how to override initial method?

I want request.data too? how to override initial method? i wish to compare data before and after update. so i gone through Log Mixin , in that, you didnt update request.data into tables. so how to override my "def initial()" mixin? to insert request.data too ...

User filtering in admin

This filter
list_filter = ('user', 'path', 'method', 'status_code')
is a bit annoying if you have +1000 users.

and can you add
raw_id_fields = ('user', )
to APIRequestLogAdmin class ?

Migrations conflict

I'm using Django 1.11.7, and using drf-tracing at latest master branch (b753c5e).
When I run python manage.py makemigrations, I got the following conflict error:

CommandError: Conflicting migrations detected; multiple leaf nodes in the migration graph: (0006_auto_20180315_1442, 0006_view_and_view_method_nullable in rest_framework_tracking).
To fix them run 'python manage.py makemigrations --merge'

I can solve it by running python manage.py makemigrations --merge but thats a bit inconvenient when using travis, since I need to run makemigrations every time the build process running. Is there any plan to fix this?

AttributeError: 'FileResponse' object has no attribute 'rendered_content'

Hi,

drf-tracking 1.2.0 crash if you use a DRF APIView that returns a FileResponse.
Could you fix this behaviour?

Thanks,
Simone


Crash report

Environment: development

Request Method: GET
Request URL: http://prm.mydevelopmentenv.com/api/export/files

Django Version: 1.8.18
Python Version: 3.3.5
Installed Applications:
('django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'debug_toolbar',
'django_q',
'rest_framework',
'rest_framework.authtoken',
'rest_framework_tracking',
'maintenancemode',
'prm')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'prm.middleware.SetRemoteAddrMiddleware',
'debug_toolbar.middleware.DebugToolbarMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'maintenancemode.middleware.MaintenanceModeMiddleware')

Traceback:
File "/home/prm/virtualenv/lib/python3.3/site-packages/django/core/handlers/base.py" in get_response
132. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/prm/virtualenv/lib/python3.3/site-packages/django/views/decorators/csrf.py" in wrapped_view
58. return view_func(*args, **kwargs)
File "/home/prm/virtualenv/lib/python3.3/site-packages/django/views/generic/base.py" in view
71. return self.dispatch(request, *args, **kwargs)
File "/home/prm/virtualenv/lib/python3.3/site-packages/rest_framework/views.py" in dispatch
491. self.response = self.finalize_response(request, response, *args, **kwargs)
File "/home/prm/virtualenv/lib/python3.3/site-packages/rest_framework_tracking/mixins.py" in finalize_response
100. self.request.log.response = response.rendered_content

Exception Type: AttributeError at /api/export/files
Exception Value: 'FileResponse' object has no attribute 'rendered_content'

http 500 to be handled

Any http 500 error causes log to have status code not assigned and response ms to 0. It would be nice to see the trace instead.

Show hidden values of token and password?

I am using drf-tracking it is working great but i am getting error on class in which i am using password and tokens to perform operations.

Is there any way to avoid hide token and password values ?

IntegrityError response_ms

Hello all,

I just want to share an issue I had.

There was an exception regarding negative response time. After reading the code a bit I see that you have a justified assumption regarding the response_ms being positive.

The implementation of the duration is straightforward so no surprises there. My solution was to patch the duration calculation to return 0 if the delta is negative.

Something like this:
response_timedelta = now() - self.request.log.requested_at
response_ms = int(response_timedelta.total_seconds() * 1000)
response_ms = max(response_ms, 0)

I wasn't able to reproduce the issue though.
I was wondering if anyone else have seen something similar.

Thanks

Code looks overcommented

This may be none of my business, but I think the huge part of comments in this project doesn't make sense because the code is already obvious. They explain nothing and don’t help. Just a noise. My advice is get rid of them. What do you think?

Like this:
screen shot 2017-12-18 at 16 39 39

Or this:
screen shot 2017-12-18 at 16 37 57

AttributeError: 'Request' object has no attribute 'log'

If there is a problem with parsing the posted JSON to DRF API endpoint, drf-tracking raises this exception and causes Internal Server Error. Reason is that inside LoggingMixin.initial if there is a ParseError thrown on data_dict = request.data.dict() self.request.log is never set, but finalize_response gets called anyway.

Problem is, you never get to see the actual problem (i.e. {"detail":"JSON parse error - Expecting property name enclosed in double quotes: line 7 column 1 (char 111)"}), as the 500 Internal Error masks the problem.

overridden initialize_request raises Exceptions in scenarios where user is not Authenticated

Hi, this module is exactly what I'm looking for, in order to track usage of our APIs. After installing and adding to DRF ViewSets, some scenarios raise Exceptions instead of gracefully handling them.

File "/home/ubuntu/virtualenvs/venv-system/local/lib/python2.7/site-packages/rest_framework/authentication.py", line 185, in authenticate_credentials
    raise exceptions.AuthenticationFailed(_('Invalid token.'))
AuthenticationFailed: Invalid token.

Here I was trying to test if my API returns the correct status code if Token is invalid.

File "/home/ubuntu/virtualenvs/venv-system/local/lib/python2.7/site-packages/rest_framework/authentication.py", line 188, in authenticate_credentials
    raise exceptions.AuthenticationFailed(_('User inactive or deleted.'))
AuthenticationFailed: User inactive or deleted.

Here I was trying to test if my API returns the correct status code if User is inactive/deleted.

I'll try and raise a PR to handle these exceptions.

Can we track django-oauth-toolkit client?

I'm using Django-OAuth-Toolkit to allow client based authorization.

I have set different client for different platforms. Like for Android, a different client is used to generate the access token and for the web, a different client is used to generate the access token.

I want to log which the client is making the request.

django 2 compatible

We have to make this compatible with django 2.
There are various things that are deprecated, such as, is_authenticated is not a function anymore.

Simple way to disable/limit the size of the response stored in the database

Hi,

Thanks for the useful plugin!

Since some of our API responses can be large, the log table is becoming slow to load due to the size of the response column. They are cropped to [204K], (I think due to Django/postgres?), but this is still a lot and means we have to update the column data manually to get sensible performance.

Is there an easy way to turn off or limit the size of the response stored?

Cheers

Sim

Error when use to track any request data with special character

I tried to implement the tracking for the endpoint / views that needed EMAIL field in the request data, and it failing

  File "/.virtualenvs/lib/python2.7/site-packages/rest_framework_tracking/mixins.py", line 72, in initial
    self.request.log.data = self._clean_data(self.request.data)
  File "/.virtualenvs/lib/python2.7/site-packages/rest_framework_tracking/mixins.py", line 142, in _clean_data
    value = ast.literal_eval(value)
  File "/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ast.py", line 49, in literal_eval
    node_or_string = parse(node_or_string, mode='eval')
  File "/usr/local/Cellar/python/2.7.13/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ast.py", line 37, in parse
    return compile(source, filename, mode, PyCF_ONLY_AST)
  File "<unknown>", line 1
    [email protected]
            ^
SyntaxError: invalid syntax

i've already using the dependencies from repo but it still failing

Only last params value is captured if multiple query params are sent with same key

Subject : When multiple query params are passed with same key, only the last query params is captured and rest all are ignored/dropped.

Steps to reproduce :

  1. Install this library in any api view
  2. Make a request to that view with multiple query params of same name/key.
    Example : /api/v1/index/?name=A&name=B&name=C&name=D

Expected behaviour : Query params field should record {"name": ["A", "B", "C"]}

Actual behaviour : Query params field records only last value {"name": "C"}

Does ApiLog contain before Db changes?

Thanks for your contribution first.. its working fine currently i am getting data after request like put, patch was updated one. but I want to have both updated and requested before change. is it possible ?

Transactions breaking on creation if logging.

I am getting an error with logging on write operations.

The DB is PostgreSQL 9.5 and using latest Django Rest Framework.

TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.

Has anyone else run into this issue. I didn't notice anything in the issues.

Tracking response

Great work! I have a similar mixin and have found it useful to also track the actual response. Would that be something useful to add to this project?

404 should be tracked

Responses with status 404 should be logged. Currently, requests to a missing url are not logged.

LogginMixin not gets called with ModelViewSet in Django 2.0.4

Django: 2.0.4, python: 3.5.3

class BookingViewSet(viewset.ModelViewSet, LoggingMixin):
    def get_queryset(self):
     return Booking.objects.all()

    def get_serializer_class(self):
     return BookingSerializer

After making multiple calls to this api viewset, no records added in API REQUEST LOGS.

Toggle logging of certain fields

Is there currently a way to enable/disable (toggling) logging of certain fields? For example, if I didn't want to capture the logging of response field. Would that be possible currently? TIA.

Fail for Bulk Create

In venv/lib/python3.5/site-packages/rest_framework_tracking/mixins.py", line 134, in _clean_data

if SENSITIVE_DATA.search(key):

TypeError: expected string or bytes-like object

  class MyBulkCreate(LoggingMixin, generics.CreateAPIView):

      def create(self, request, *args, **kwargs):

         serializer = serializers.FooBarSerializer(data=data, context=context, many=True)

my post data is a json as following:

[{"foo": "200" ,"bar": "A", "fufu":"1"},{"foo": "200" ,"bar": "B", "fufu":"1"}]

When i pass the data through Mixin and it crashed already. I have to skip using the tracking function for all bulk_create api.

Will there any solutions for now?

[STOPPED] Elastic search compatibility

I'm currently working on a possibility to store data either in the database or in a elastic search cluster.

If you have idea or input regarding this feature, please share your thoughts here.

A valid _____ is required error due to _clean_data function

The field is a float field. All other float fields work.

I can see how this would cause errors on

'capitalized_cost' (my field)
'keyless_entry'
'user_signature_jpg_url'

While I do not mind changing the name to cap_cost I'd still much rather not do it.

One possible suggestion for this fix is to add a '_' prefix / suffix.
because most of the times it will be:
'stripe_api_key'
'stripe_token'
'paypal_signature'

So change the regex line to (_api)|(api_)|(_token)|(token_)|(_key)|(key_)|(_secret)|(secret_)|(_password)|(password_)|(_signature)|(signature_)

And this has to be in the documentation.

def _clean_data(data):
    """
    Clean a dictionary of data of potentially sensitive info before
    sending to the database.
    Function based on the "_clean_credentials" function of django
    (django/django/contrib/auth/__init__.py)
    """
    SENSITIVE_DATA = re.compile('api|token|key|secret|password|signature', re.I)
    CLEANSED_SUBSTITUTE = '********************'
    for key in data:
        if SENSITIVE_DATA.search(key):
            data[key] = CLEANSED_SUBSTITUTE
    
    return data

Track status code

Add a status_code field to the model, mixin, and admin list filter.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.