Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6f7d14fdb2 | |||
| 941ec8fdaf | |||
| 51ec07261d | |||
| a9cdf6d561 | |||
| a64ce95e3c | |||
| c9147a5746 |
Generated
+1
@@ -8,6 +8,7 @@
|
|||||||
<option name="manageScript" value="manage.py" />
|
<option name="manageScript" value="manage.py" />
|
||||||
<option name="environment" value="<map/>" />
|
<option name="environment" value="<map/>" />
|
||||||
<option name="doNotUseTestRunner" value="false" />
|
<option name="doNotUseTestRunner" value="false" />
|
||||||
|
<option name="trackFilePattern" value="migrations" />
|
||||||
</configuration>
|
</configuration>
|
||||||
</facet>
|
</facet>
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
@@ -3,6 +3,22 @@ Changelog
|
|||||||
#########
|
#########
|
||||||
|
|
||||||
|
|
||||||
|
*********
|
||||||
|
**1.6.1**
|
||||||
|
*********
|
||||||
|
|
||||||
|
*Release date: Apr 01, 2018*
|
||||||
|
|
||||||
|
- **ADDED:** added ``SUPPORTED_SUBMIT_METHODS`` ``swagger-ui`` setting
|
||||||
|
|
||||||
|
*********
|
||||||
|
**1.6.0**
|
||||||
|
*********
|
||||||
|
|
||||||
|
*Release date: Mar 24, 2018*
|
||||||
|
|
||||||
|
- **IMPROVED:** ``OAUTH2_REDIRECT_URL`` will now default to the built in ``oauth2-redirect.html`` file
|
||||||
|
|
||||||
*********
|
*********
|
||||||
**1.5.1**
|
**1.5.1**
|
||||||
*********
|
*********
|
||||||
|
|||||||
+1
-1
@@ -273,7 +273,7 @@ def role_github_user(name, rawtext, text, lineno, inliner, options=None, content
|
|||||||
options = options or {}
|
options = options or {}
|
||||||
content = content or []
|
content = content or []
|
||||||
|
|
||||||
if not re.match(r"^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}$", text):
|
if not re.match(r"^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}$", text, re.IGNORECASE):
|
||||||
return sphinx_err(inliner, lineno, rawtext, '"%s" is not a valid GitHub username.' % text)
|
return sphinx_err(inliner, lineno, rawtext, '"%s" is not a valid GitHub username.' % text)
|
||||||
|
|
||||||
ref = gh_user_uri.format(text)
|
ref = gh_user_uri.format(text)
|
||||||
|
|||||||
@@ -63,3 +63,37 @@ settings described below were added as a result of discussion in issue :issue:`5
|
|||||||
The settings of interest can be found on the :ref:`settings page <oauth2-settings>`. Configuration options are similar
|
The settings of interest can be found on the :ref:`settings page <oauth2-settings>`. Configuration options are similar
|
||||||
to most OAuth client setups like web or mobile applications. Reading the relevant ``swagger-ui`` docmentation linked
|
to most OAuth client setups like web or mobile applications. Reading the relevant ``swagger-ui`` docmentation linked
|
||||||
will also probably help.
|
will also probably help.
|
||||||
|
|
||||||
|
|
||||||
|
Example
|
||||||
|
^^^^^^^
|
||||||
|
|
||||||
|
A very simple working configuration was provided by :ghuser:`Vigrond`, originally at
|
||||||
|
`https://github.com/Vigrond/django_oauth2_example <https://github.com/Vigrond/django_oauth2_example>`_.
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
SWAGGER_SETTINGS = {
|
||||||
|
'USE_SESSION_AUTH': False,
|
||||||
|
'SECURITY_DEFINITIONS': {
|
||||||
|
'Your App API - Swagger': {
|
||||||
|
'type': 'oauth2',
|
||||||
|
'authorizationUrl': '/yourapp/o/authorize',
|
||||||
|
'tokenUrl': '/yourapp/o/token/',
|
||||||
|
'flow": "accessCode',
|
||||||
|
'scopes': {
|
||||||
|
'read:groups': 'read groups',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'OAUTH2_CONFIG': {
|
||||||
|
'clientId': 'yourAppClientId',
|
||||||
|
'clientSecret': 'yourAppClientSecret',
|
||||||
|
'appName': 'your application name'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
If the OAuth2 provider requires you to provide the full absolute redirect URL, the default value for most
|
||||||
|
``staticfiles`` configurations will be ``<origin>/static/drf-yasg/swagger-ui-dist/oauth2-redirect.html``. If this is
|
||||||
|
not suitable for some reason, you can override the ``OAUTH2_REDIRECT_URL`` setting as appropriate.
|
||||||
|
|||||||
+13
-1
@@ -259,7 +259,10 @@ Controls how many levels are expaned by default when showing nested models.
|
|||||||
OAUTH2_REDIRECT_URL
|
OAUTH2_REDIRECT_URL
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Used when OAuth2 authenitcation of API requests via swagger-ui is desired.
|
Used when OAuth2 authenitcation of API requests via swagger-ui is desired. If ``None`` is passed, the
|
||||||
|
``oauth2RedirectUrl`` parameter will be set to ``{% static 'drf-yasg/swagger-ui-dist/oauth2-redirect.html' %}``. This
|
||||||
|
is the default `https://github.com/swagger-api/swagger-ui/blob/master/dist/oauth2-redirect.html <oauth2-redirect>`_
|
||||||
|
file provided by ``swagger-ui``.
|
||||||
|
|
||||||
**Default**: :python:`None` |br|
|
**Default**: :python:`None` |br|
|
||||||
*Maps to parameter*: ``oauth2RedirectUrl``
|
*Maps to parameter*: ``oauth2RedirectUrl``
|
||||||
@@ -273,6 +276,15 @@ to the ``SwaggerUIBundle#initOAuth`` method, and must be a dictionary. See
|
|||||||
|
|
||||||
**Default**: :python:`{}`
|
**Default**: :python:`{}`
|
||||||
|
|
||||||
|
SUPPORTED_SUBMIT_METHODS
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
List of HTTP methods that have the Try it out feature enabled. An empty array disables Try it out for all operations.
|
||||||
|
This does not filter the operations from the display.
|
||||||
|
|
||||||
|
**Default**: :python:`['get','put','post','delete','options','head','patch','trace']` |br|
|
||||||
|
*Maps to parameter*: ``supportedSubmitMethods``
|
||||||
|
|
||||||
******************
|
******************
|
||||||
``REDOC_SETTINGS``
|
``REDOC_SETTINGS``
|
||||||
******************
|
******************
|
||||||
|
|||||||
@@ -46,6 +46,16 @@ SWAGGER_DEFAULTS = {
|
|||||||
'DEFAULT_MODEL_DEPTH': 3,
|
'DEFAULT_MODEL_DEPTH': 3,
|
||||||
'OAUTH2_REDIRECT_URL': None,
|
'OAUTH2_REDIRECT_URL': None,
|
||||||
'OAUTH2_CONFIG': {},
|
'OAUTH2_CONFIG': {},
|
||||||
|
'SUPPORTED_SUBMIT_METHODS': [
|
||||||
|
'get',
|
||||||
|
'put',
|
||||||
|
'post',
|
||||||
|
'delete',
|
||||||
|
'options',
|
||||||
|
'head',
|
||||||
|
'patch',
|
||||||
|
'trace'
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
REDOC_DEFAULTS = {
|
REDOC_DEFAULTS = {
|
||||||
|
|||||||
@@ -425,7 +425,7 @@ class Schema(SwaggerDict):
|
|||||||
:param str format: value format, see OpenAPI spec
|
:param str format: value format, see OpenAPI spec
|
||||||
:param list enum: restrict possible values
|
:param list enum: restrict possible values
|
||||||
:param str pattern: pattern if type is ``string``
|
:param str pattern: pattern if type is ``string``
|
||||||
:param list[.Schema,.SchemaRef] properties: object properties; required if `type` is ``object``
|
:param dict[str,(.Schema,.SchemaRef)] properties: object properties; required if `type` is ``object``
|
||||||
:param bool,.Schema,.SchemaRef additional_properties: allow wildcard properties not listed in `properties`
|
:param bool,.Schema,.SchemaRef additional_properties: allow wildcard properties not listed in `properties`
|
||||||
:param list[str] required: list of requried property names
|
:param list[str] required: list of requried property names
|
||||||
:param .Schema,.SchemaRef items: type of array items, only valid if `type` is ``array``
|
:param .Schema,.SchemaRef items: type of array items, only valid if `type` is ``array``
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ class _UIRenderer(BaseRenderer):
|
|||||||
'defaultModelExpandDepth': swagger_settings.DEFAULT_MODEL_DEPTH,
|
'defaultModelExpandDepth': swagger_settings.DEFAULT_MODEL_DEPTH,
|
||||||
'defaultModelsExpandDepth': swagger_settings.DEFAULT_MODEL_DEPTH,
|
'defaultModelsExpandDepth': swagger_settings.DEFAULT_MODEL_DEPTH,
|
||||||
'oauth2RedirectUrl': swagger_settings.OAUTH2_REDIRECT_URL,
|
'oauth2RedirectUrl': swagger_settings.OAUTH2_REDIRECT_URL,
|
||||||
|
'supportedSubmitMethods': swagger_settings.SUPPORTED_SUBMIT_METHODS,
|
||||||
}
|
}
|
||||||
data = {k: v for k, v in data.items() if v is not None}
|
data = {k: v for k, v in data.items() if v is not None}
|
||||||
if swagger_settings.VALIDATOR_URL != '':
|
if swagger_settings.VALIDATOR_URL != '':
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ function initSwaggerUi() {
|
|||||||
],
|
],
|
||||||
layout: "StandaloneLayout",
|
layout: "StandaloneLayout",
|
||||||
filter: true,
|
filter: true,
|
||||||
requestInterceptor: function(request) {
|
requestInterceptor: function (request) {
|
||||||
var headers = request.headers || {};
|
var headers = request.headers || {};
|
||||||
var csrftoken = document.querySelector("[name=csrfmiddlewaretoken]");
|
var csrftoken = document.querySelector("[name=csrfmiddlewaretoken]");
|
||||||
if (csrftoken) {
|
if (csrftoken) {
|
||||||
@@ -49,8 +49,15 @@ function initSwaggerUi() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var swaggerSettings = JSON.parse(document.getElementById('swagger-settings').innerHTML);
|
var swaggerSettings = JSON.parse(document.getElementById('swagger-settings').innerHTML);
|
||||||
console.log(swaggerSettings);
|
if (!('oauth2RedirectUrl' in swaggerSettings)) {
|
||||||
|
var oauth2RedirectUrl = document.getElementById('oauth2-redirect-url');
|
||||||
|
if (oauth2RedirectUrl) {
|
||||||
|
swaggerSettings['oauth2RedirectUrl'] = oauth2RedirectUrl.href;
|
||||||
|
oauth2RedirectUrl.parentNode.removeChild(oauth2RedirectUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(swaggerSettings);
|
||||||
for (var p in swaggerSettings) {
|
for (var p in swaggerSettings) {
|
||||||
if (swaggerSettings.hasOwnProperty(p)) {
|
if (swaggerSettings.hasOwnProperty(p)) {
|
||||||
swaggerConfig[p] = swaggerSettings[p];
|
swaggerConfig[p] = swaggerSettings[p];
|
||||||
|
|||||||
@@ -67,6 +67,8 @@
|
|||||||
<script src="{% static 'drf-yasg/insQ.min.js' %}"></script>
|
<script src="{% static 'drf-yasg/insQ.min.js' %}"></script>
|
||||||
<script src="{% static 'drf-yasg/swagger-ui-init.js' %}"></script>
|
<script src="{% static 'drf-yasg/swagger-ui-init.js' %}"></script>
|
||||||
|
|
||||||
|
<a id="oauth2-redirect-url" href="{% static 'drf-yasg/swagger-ui-dist/oauth2-redirect.html' %}" class="hidden"></a>
|
||||||
|
|
||||||
<div id="django-session-auth" class="hidden">
|
<div id="django-session-auth" class="hidden">
|
||||||
{% if USE_SESSION_AUTH %}
|
{% if USE_SESSION_AUTH %}
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
# Generated by Django 2.0 on 2017-12-23 09:07
|
# Generated by Django 2.0.1 on 2018-03-18 18:32
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
@@ -23,8 +24,28 @@ class Migration(migrations.Migration):
|
|||||||
('slug', models.SlugField(blank=True, help_text='slug model help_text', unique=True)),
|
('slug', models.SlugField(blank=True, help_text='slug model help_text', unique=True)),
|
||||||
('date_created', models.DateTimeField(auto_now_add=True)),
|
('date_created', models.DateTimeField(auto_now_add=True)),
|
||||||
('date_modified', models.DateTimeField(auto_now=True)),
|
('date_modified', models.DateTimeField(auto_now=True)),
|
||||||
|
('article_type', models.PositiveSmallIntegerField(choices=[(1, 'first'), (2, 'second'), (3, 'third'), (7, 'seven'), (8, 'eight')], help_text='IntegerField declared on model with choices=(...) and exposed via ModelSerializer', null=True)),
|
||||||
('cover', models.ImageField(blank=True, upload_to='article/original/')),
|
('cover', models.ImageField(blank=True, upload_to='article/original/')),
|
||||||
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='articles', to=settings.AUTH_USER_MODEL)),
|
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='articles', to=settings.AUTH_USER_MODEL)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ArticleGroup',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)),
|
||||||
|
('title', models.CharField(help_text='title model help_text', max_length=255, unique=True)),
|
||||||
|
('slug', models.SlugField(blank=True, help_text='slug model help_text', unique=True)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='article',
|
||||||
|
name='group',
|
||||||
|
field=models.ForeignKey(blank=True, default=None, on_delete=django.db.models.deletion.PROTECT, related_name='articles_as_main', to='articles.ArticleGroup'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='article',
|
||||||
|
name='original_group',
|
||||||
|
field=models.ForeignKey(blank=True, default=None, on_delete=django.db.models.deletion.PROTECT, related_name='articles_as_original', to='articles.ArticleGroup'),
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
# Generated by Django 2.0.1 on 2018-02-26 18:32
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('articles', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='article',
|
|
||||||
name='article_type',
|
|
||||||
field=models.PositiveSmallIntegerField(choices=[(1, 'first'), (2, 'second'), (3, 'third'), (7, 'seven'), (8, 'eight')], help_text='IntegerField declared on model with choices=(...) and exposed via ModelSerializer', null=True),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.11.11 on 2018-03-10 01:42
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
import uuid
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('articles', '0002_article_article_type'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='ArticleGroup',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('uuid', models.UUIDField(default=uuid.uuid4, editable=False, unique=True)),
|
|
||||||
('title', models.CharField(help_text='title model help_text', max_length=255, unique=True)),
|
|
||||||
('slug', models.SlugField(blank=True, help_text='slug model help_text', unique=True)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='article',
|
|
||||||
name='group',
|
|
||||||
field=models.ForeignKey(blank=True, default=None, on_delete=django.db.models.deletion.PROTECT, related_name='articles_as_main', to='articles.ArticleGroup'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='article',
|
|
||||||
name='original_group',
|
|
||||||
field=models.ForeignKey(blank=True, default=None, on_delete=django.db.models.deletion.PROTECT, related_name='articles_as_original', to='articles.ArticleGroup'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# Generated by Django 2.0.1 on 2018-03-18 18:32
|
||||||
# Generated by Django 1.11.10 on 2018-03-18 16:22
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
@@ -26,7 +24,7 @@ class Migration(migrations.Migration):
|
|||||||
name='Person',
|
name='Person',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('Identity', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='person', to='people.Identity')),
|
('identity', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='person', to='people.Identity')),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Generated by Django 1.11.10 on 2018-03-18 17:04
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('people', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='person',
|
|
||||||
name='Identity',
|
|
||||||
field=models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='person', to='people.Identity'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
@@ -7,5 +7,4 @@ class Identity(models.Model):
|
|||||||
|
|
||||||
|
|
||||||
class Person(models.Model):
|
class Person(models.Model):
|
||||||
Identity = models.OneToOneField(Identity, related_name='person',
|
identity = models.OneToOneField(Identity, related_name='person', on_delete=models.PROTECT)
|
||||||
on_delete=models.PROTECT)
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class IdentitySerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
|
|
||||||
class PersonSerializer(serializers.ModelSerializer):
|
class PersonSerializer(serializers.ModelSerializer):
|
||||||
identity = IdentitySerializer(read_only=True)
|
identity = IdentitySerializer()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Person
|
model = Person
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Generated by Django 2.0 on 2017-12-23 09:07
|
# Generated by Django 2.0.1 on 2018-03-18 18:32
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# Generated by Django 2.0.1 on 2018-03-18 18:32
|
||||||
# Generated by Django 1.11 on 2018-02-21 23:26
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
import django.db.models.deletion
|
import django.db.models.deletion
|
||||||
|
|||||||
@@ -732,10 +732,9 @@ definitions:
|
|||||||
title: LastName
|
title: LastName
|
||||||
type: string
|
type: string
|
||||||
maxLength: 30
|
maxLength: 30
|
||||||
readOnly: true
|
|
||||||
Person:
|
Person:
|
||||||
required:
|
required:
|
||||||
- Identity
|
- identity
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
id:
|
id:
|
||||||
@@ -744,9 +743,6 @@ definitions:
|
|||||||
readOnly: true
|
readOnly: true
|
||||||
identity:
|
identity:
|
||||||
$ref: '#/definitions/Identity'
|
$ref: '#/definitions/Identity'
|
||||||
Identity:
|
|
||||||
title: Identity
|
|
||||||
type: integer
|
|
||||||
Project:
|
Project:
|
||||||
required:
|
required:
|
||||||
- projectName
|
- projectName
|
||||||
|
|||||||
@@ -66,4 +66,4 @@ known_third_party =
|
|||||||
coreapi,coreschema,datadiff,dj_database_url,django,django_filters,djangorestframework_camel_case,flex,gunicorn,
|
coreapi,coreschema,datadiff,dj_database_url,django,django_filters,djangorestframework_camel_case,flex,gunicorn,
|
||||||
inflection,pygments,pytest,rest_framework,ruamel,setuptools_scm,swagger_spec_validator,uritemplate,user_agents,
|
inflection,pygments,pytest,rest_framework,ruamel,setuptools_scm,swagger_spec_validator,uritemplate,user_agents,
|
||||||
whitenoise
|
whitenoise
|
||||||
known_first_party = drf_yasg,testproj,articles,snippets,users,urlconfs
|
known_first_party = drf_yasg,testproj,articles,people,snippets,todo,users,urlconfs
|
||||||
|
|||||||
Reference in New Issue
Block a user