Skip to content

Commit

Permalink
fixup
Browse files Browse the repository at this point in the history
  • Loading branch information
eshaan7 committed May 19, 2021
1 parent 3c25e8a commit ca87a23
Show file tree
Hide file tree
Showing 12 changed files with 176 additions and 133 deletions.
16 changes: 1 addition & 15 deletions durin/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,6 @@
from durin import models


class ClientSettingsInlineAdmin(admin.StackedInline):
"""
Django's StackedInline for :class:`ClientSettings` model.
"""

model = models.ClientSettings

list_select_related = True
extra = 1


@admin.register(models.AuthToken)
class AuthTokenAdmin(admin.ModelAdmin):
"""Django's ModelAdmin for AuthToken.\n
Expand Down Expand Up @@ -76,12 +65,9 @@ class ClientAdmin(admin.ModelAdmin):
Django's ModelAdmin for :class:`Client` model.
"""

inlines = [
ClientSettingsInlineAdmin,
]

list_display = (
"id",
"name",
"token_ttl",
"throttle_rate",
)
54 changes: 54 additions & 0 deletions durin/migrations/0002_client_throttlerate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Generated by Django 3.2.3 on 2021-05-19 08:25

import datetime

from django.db import migrations, models

import durin.throttling


class Migration(migrations.Migration):

dependencies = [
("durin", "0001_initial"),
]

operations = [
migrations.AddField(
model_name="client",
name="throttle_rate",
field=models.CharField(
blank=True,
default="",
help_text="Follows the same format as DRF's throttle rates.\n Format: <em>'number_of_requests/period'</em>\n where period should be one of: ('s', 'm', 'h', 'd').\n Example: '100/h' implies 100 requests each hour.\n ",
max_length=64,
validators=[
durin.throttling.UserClientRateThrottle.validate_client_throttle_rate
],
verbose_name="Throttle rate for requests authed with this client",
),
),
migrations.AlterField(
model_name="authtoken",
name="id",
field=models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
migrations.AlterField(
model_name="client",
name="id",
field=models.BigAutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
migrations.AlterField(
model_name="client",
name="token_ttl",
field=models.DurationField(
default=datetime.timedelta(days=1),
help_text="\n Token Time To Live (TTL) in timedelta. Format: <code>DAYS HH:MM:SS</code>.\n ",
verbose_name="Token Time To Live (TTL)",
),
),
]
76 changes: 0 additions & 76 deletions durin/migrations/002_clientsettings.py

This file was deleted.

42 changes: 7 additions & 35 deletions durin/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import binascii
from os import urandom
from typing import Union

import humanize
from django.conf import settings
Expand All @@ -24,6 +23,9 @@ def _create_token_string() -> str:
class Client(models.Model):
"""
Identifier to represent any API client/browser that consumes your RESTful API.
See ``example_project.models.ClientSettings``
if you wish to extend this model per your convenience.
"""

#: A unique identification name for the client.
Expand All @@ -48,46 +50,15 @@ class Client(models.Model):
),
)

def __str__(self):
td = humanize.naturaldelta(self.token_ttl)
return "({0}, {1})".format(self.name, td)

@property
def throttle_rate(self) -> Union[str, None]:
if hasattr(self, "settings"):
return self.settings.throttle_rate
else:
return None


class ClientSettings(models.Model):
"""
It is recommended to subclass this model (and not :py:class:`~Client`)
if you wish to add extra fields for storing any
configuration or settings against ``Client`` instances.
Reverse lookup: ``Client.settings``.
.. versionadded:: 0.2
"""

#: `OneToOneField
#: <https://docs.djangoproject.com/en/3.2/topics/db/examples/one_to_one/>`__
#: with :py:class:`~Client` with ``on_delete=models.CASCADE``.
client = models.OneToOneField(
Client,
blank=False,
related_name="settings",
on_delete=models.CASCADE,
)

#: Throttle rate for requests authed with this client.
#:
#: **Format**: ``number_of_requests/period``
#: where period should be one of: *('s', 'm', 'h', 'd')*.
#: (same format as DRF's throttle rates)
#:
#: **Example**: ``100/h`` implies 100 requests each hour.
#:
#: .. versionadded:: 0.2
throttle_rate = models.CharField(
max_length=64,
default="",
Expand All @@ -104,7 +75,8 @@ class ClientSettings(models.Model):
)

def __str__(self):
return "(rate: '{0}')".format(self.throttle_rate)
td = humanize.naturaldelta(self.token_ttl)
return "({0}, {1})".format(self.name, td)


class AuthTokenManager(models.Manager):
Expand Down
7 changes: 3 additions & 4 deletions durin/throttling.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""
Durin provides a throttling class which make use of the
:class:`durin.models.Client` and :class:`durin.models.ClientSettings`
models it offers.
:class:`durin.models.Client` model it offers.
Usage is the same way as other
`DRF throttling classes <https://django-rest-framework.org/api-guide/throttling/>`__.
Expand All @@ -20,7 +19,7 @@
default ``scope`` for the :class:`UserClientRateThrottle` class.
The rate defined here serves as the default rate incase the
``throttle_rate`` field on :class:`durin.models.ClientSettings` is ``null``.
``throttle_rate`` field on :class:`durin.models.Client` is ``null``.
"""

from django.core.exceptions import ValidationError as DjValidationError
Expand Down Expand Up @@ -88,7 +87,7 @@ def _get_user_client_ident(self, request) -> str:
def validate_client_throttle_rate(rate):
"""
Used for validating the :attr:`throttle_rate` field
on :class:`durin.models.ClientSettings`.
on :class:`durin.models.Client`.
*For internal use only.*
"""
Expand Down
38 changes: 38 additions & 0 deletions example_project/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from django.contrib import admin

from durin.models import Client

from .models import ClientSettings


class ClientSettingsInlineAdmin(admin.StackedInline):
"""
Django's StackedInline for :class:`ClientSettings` model.
"""

model = ClientSettings

list_select_related = True
extra = 1


class ClientAdmin(admin.ModelAdmin):
"""
Django's ModelAdmin for :class:`Client` model.
"""

inlines = [
ClientSettingsInlineAdmin,
]

list_display = (
"id",
"name",
"token_ttl",
"throttle_rate",
)


# Unregister default admin view
admin.site.unregister(Client)
admin.site.register(Client, ClientAdmin)
39 changes: 39 additions & 0 deletions example_project/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Generated by Django 3.2.3 on 2021-05-19 08:31

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = [
("durin", "0002_client_throttlerate"),
]

operations = [
migrations.CreateModel(
name="ClientSettings",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("description", models.TextField()),
(
"client",
models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
related_name="settings",
to="durin.client",
),
),
],
),
]
Empty file.
27 changes: 27 additions & 0 deletions example_project/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from django.db import models


class ClientSettings(models.Model):
"""
It is recommended to create a model like this
(and not subclass :py:class:`durin.models.Client`)
if you wish to add extra fields for storing any
configuration or settings against ``Client`` instances.
Reverse lookup: ``Client.settings``.
"""

#: `OneToOneField
#: <https://docs.djangoproject.com/en/3.2/topics/db/examples/one_to_one/>`__
#: with :py:class:`~Client` with ``on_delete=models.CASCADE``.
client = models.OneToOneField(
"durin.Client",
blank=False,
related_name="settings",
on_delete=models.CASCADE,
)

description = models.TextField()

def __str__(self):
return "ClientSettings(<{0}>)".format(self.client.name)
6 changes: 5 additions & 1 deletion example_project/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@
DEBUG = True
ALLOWED_HOSTS = []
INSTALLED_APPS = (
# default
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
# extra
"memoize",
"rest_framework",
"durin",
"django_nose",
# project apps
"durin",
"example_project",
)

DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
Expand Down
Loading

0 comments on commit ca87a23

Please sign in to comment.