Skip to main content

Django admin client

Project description

Django Admin client

Installation

pip install django-admin-client

Usage

3 main usages:

  1. Convenient HTTP GET and POST methods
  2. Dynamic Django Admin python client
  3. Generating specific Django Admin python client

1. Convenient HTTP GET and POST methods

DjangoAdminBase will do auto login, session management, and auto csrf token inclusion and auto error detection

from django_admin_client import DjangoAdminBase

basic_client = DjangoAdminBase('http://127.0.0.1:9000/admin', 'superuser', 'why-dont-tell-mom?')

# auto login:
basic_client.get_with_auto_login('/')
# <Response [200]>

# response is just our favorite and well-known response from 'requests' library
type(basic_client.get_with_auto_login('/'))
# requests.models.Response

# auto login (if not yet logged in or session expired),
# csrf token included in POST request automatically,
# errors in response html form detected and provided
basic_client.post_with_csrf_and_auto_login(
    '/auth/user/add/',
    {'username': 'test', 'password1': '123', 'password2': '123'}
)
#{'response': <Response [200]>,
# 'errors': [<div class="form-row errors field-password2">
#  <ul class="errorlist"><li>This password is too short. It must contain at least 8 characters.</li><li>This password is too common.</li><li>This password is entirely numeric.</li></ul>
#  <div>
#  <label class="required" for="id_password2">Password confirmation:</label>
#  <input id="id_password2" name="password2" required="" type="password"/>
#  <div class="help">Enter the same password as before, for verification.</div>
#  </div>
#  </div>]}

basic_client.post_with_csrf_and_auto_login(
    '/auth/user/add/',
    {'username': 'test', 'password1': 'isthislongenough', 'password2': 'isthislongenough'}
)
# {'response': <Response [200]>, 'errors': []}

2. Dynamic Django Admin python client

DjangoAdminBase can also do introspection on Django Admin site and generate specification.

In [1]: spec = basic_client.generate_spec()
In [2]: import json
In [3]: json.dumps(spec, indent=2)
Out[3]:
{
  "models": {
    "groups": {
      "id": "groups",
      "app": "auth",
      "name": "group",
      "fields": {
        "name": {
          "name": "name",
          "required": true,
          "default_value": ""
        },
        "permissions": {
          "name": "permissions",
          "required": false,
          "default_value": ""
        }
      }
    },
    "users": {
      "id": "users",
      "app": "auth",
      "name": "user",
      "fields": {
        "username": {
          "name": "username",
          "required": true,
          "default_value": ""
        },
        "password1": {
          "name": "password1",
          "required": true,
          "default_value": ""
        },
        "password2": {
          "name": "password2",
          "required": true,
          "default_value": ""
        }
      }
    }
  }
}

This specification can then be fed to DjangoAdminDynamic class to get dynamic admin python client.

from django_admin_client import DjangoAdminBase, DjangoAdminDynamic
basic_client = DjangoAdminBase('http://127.0.0.1:9000/admin', 'superuser', 'why-dont-tell-mom?')
spec = basic_client.generate_spec()
dynamic_client = DjangoAdminDynamic(spec=spec, client=basic_client)
dynamic_client.users.all()
# {'response': <Response [200]>, 'ids': ['1', '2']}

At the moment you can add objects with <model-name>.add(item: dict):

dynamic_client.users.add({})
#{'id': None,
# 'created': False,
# 'errors': [<div class="form-row errors field-username">
#  <ul class="errorlist"><li>This field is required.</li></ul>
#  <div>
#  <label class="required" for="id_username">Username:</label>
#  <input autofocus="" class="vTextField" id="id_username" maxlength="150" name="username" required="" type="text"/>
#  <div class="help">Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.</div>
#  </div>
#  </div>, <div class="form-row errors field-password1">
#  <ul class="errorlist"><li>This field is required.</li></ul>
#  <div>
#  <label class="required" for="id_password1">Password:</label>
#  <input id="id_password1" name="password1" required="" type="password"/>
#  <div class="help"><ul><li>Your password can't be too similar to your other personal information.</li><li>Your password must contain at least 8 characters.</li><li>Your password can't be a commonly used password.</li><li>Your password can't be entirely numeric.</li></ul></div>
#  </div>
#  </div>, <div class="form-row errors field-password2">
#  <ul class="errorlist"><li>This field is required.</li></ul>
#  <div>
#  <label class="required" for="id_password2">Password confirmation:</label>
#  <input id="id_password2" name="password2" required="" type="password"/>
#  <div class="help">Enter the same password as before, for verification.</div>
#  </div>
#  </div>],
# 'response': <Response [200]>}

dynamic_client.users.add({'username': 'fromdynamic', 'password1': 'qwertyuio!', 'password2': 'qwertyuio!'})
# {'id': '3', 'created': True, 'errors': [], 'response': <Response [200]>}

Get all object ids with <model-name>.all():

dynamic_client.users.all()
# {'ids': ['3', '1', '2'], 'response': <Response [200]>}

Search object id with <model-name>.find(query: str):

dynamic_client.users.find('fromdynamic')
# {'id': '3', 'response': <Response [200]>}

Get object fields with <model-name>.get(object_id: str):

>>> dynamic_client.users.get('3')
{'response': <Response [200]>,
 'details': {'username': 'fromdynamic',
  'password': '<N/A>',
  'first_name': '',
  'last_name': '',
  'email': '',
  'is_active': '',
  'is_staff': '',
  'is_superuser': '',
  'groups': [],
  'user_permissions': [],
  'last_login_0': '',
  'last_login_1': '',
  'date_joined_0': '2019-03-06',
  'date_joined_1': '13:00:00'}}

Change object with <model-name>.change(object_id: str, fields: dict):

In [1]: dynamic_client.users.change('3', {'is_superuser': '1'})
Out[1]:
{'success': False, 'errors': [<div class="form-row errors field-username">
  <ul class="errorlist"><li>This field is required.</li></ul>
  <div>
  <label class="required" for="id_username">Username:</label>
  <input class="vTextField" id="id_username" maxlength="150" name="username" required="" type="text"/>
  <div class="help">Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.</div>
  </div>
  </div>, <div class="form-row errors field-date_joined">
  <ul class="errorlist"><li>This field is required.</li></ul>
  <div>
  <label class="required" for="id_date_joined_0">Date joined:</label>
  <p class="datetime">
    Date: <input class="vDateField" id="id_date_joined_0" name="date_joined_0" required="" size="10" type="text"/>
  <br/>
    Time: <input class="vTimeField" id="id_date_joined_1" name="date_joined_1" required="" size="8" type="text"/>
  </p><input id="initial-id_date_joined_0" name="initial-date_joined_0" type="hidden"/>
  <input id="initial-id_date_joined_1" name="initial-date_joined_1" type="hidden"/>
  </div>
  </div>], 'response': <Response [200]>}

In [2]: dynamic_client.users.change('3',
   ...: {'username': 'fromdynamic',
   ...:   'is_active': '1',
   ...:   'is_staff': '1',
   ...:   'is_superuser': '1',
   ...:   'date_joined_0': '2019-03-06', 'date_joined_1': '13:00'})
Out[2]: {'success': True, 'errors': [], 'response': <Response [200]>}

In [3]: dynamic_client.users.get('3')
Out[3]:
{'response': <Response [200]>,
 'details': {'username': 'fromdynamic',
  'password': '<N/A>',
  'first_name': '',
  'last_name': '',
  'email': '',
  'is_active': '1',
  'is_staff': '1',
  'is_superuser': '1',
  'groups': [],
  'user_permissions': [],
  'last_login_0': '',
  'last_login_1': '',
  'date_joined_0': '2019-03-06',
  'date_joined_1': '13:00:00'}}

And delete the object with <model-name>.delete(object_id: str):

dynamic_client.users.delete('3')
# {'response': <Response [200]>, 'success': True}

dynamic_client.users.all()
# {'response': <Response [200]>, 'ids': ['1', '2']}

3. Generating specific Django Admin python client

DjangoAdminDynamic is quite useful for quick terminal sessions.

Auto-completion for DjangoAdminDynamic clients is provided in python interpreter when hitting <tab> because attributes of a client are introspected at run time with dir built-in python funciton.

But writing source code with DjangoAdminDynamic is not that pleasant because there's no way for IDE to know what attributes will object have at run time.

For this purpose generate-package command is provided with django-admin-package.

Example

$ generate-package
Base url (including /admin): http://localhost:9000/admin
Superuser username: superuser
Superuser password:
Site name: fresh project
Path to package (default: /tmp): .
Version (default: 1.0):
Generated package in ./freshproject-admin-client

Generated project structure:

$ tree freshproject-admin-client
freshproject-admin-client
├── freshproject_admin_client
│   ├── client.py
│   ├── __init__.py
│   └── spec.json
├── README.md
└── setup.py

1 directory, 5 files

You can version control generated package, install it, upload to PyPI.

Example usage of a generated client:

$ ipython
Python 3.6.7 (default, Nov  9 2018, 21:20:52)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.3.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: from freshproject_admin_client import FreshProjectDjangoAdminClient

In [2]: client = FreshProjectDjangoAdminClient('http://localhost:9000/admin', 'superuser', 'why-dont-tell-mom?')

In [3]: client.auth.users.all()
Out[3]: {'response': <Response [200]>, 'ids': ['4', '1', '2']}

In [4]: client.auth.users.add()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-213c8509773c> in <module>
----> 1 client.auth.users.add()

TypeError: add() missing 3 required positional arguments: 'username', 'password1', and 'password2'

In [5]: client.auth.users.add('from_freshproject_client', '123qweASD)_+', '123qweASD)_+')
Out[5]: {'response': <Response [200]>, 'id': '5', 'created': True}

In [6]: client.auth.users.get('5')
Out[6]:
{'response': <Response [200]>,
 'details': {'username': 'from_freshproject_client',
  'password': '<N/A>',
  'first_name': '',
  'last_name': '',
  'email': '',
  'is_active': '',
  'is_staff': '',
  'is_superuser': '',
  'groups': [],
  'user_permissions': [],
  'last_login': '',
  'date_joined': '2019-03-05'}}

In [7]: client.auth.users.find('from_freshproject_client')
Out[7]: {'response': <Response [200]>, 'id': '5'}

In [8]: client.auth.users.delete('5')
Out[8]: {'response': <Response [200]>, 'success': True}

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django-admin-client-0.2.4.tar.gz (12.6 kB view details)

Uploaded Source

Built Distribution

django_admin_client-0.2.4-py3-none-any.whl (11.5 kB view details)

Uploaded Python 3

File details

Details for the file django-admin-client-0.2.4.tar.gz.

File metadata

  • Download URL: django-admin-client-0.2.4.tar.gz
  • Upload date:
  • Size: 12.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.6.7

File hashes

Hashes for django-admin-client-0.2.4.tar.gz
Algorithm Hash digest
SHA256 c9212591176fb9047c731173020063725382ddbfa18476a92a36a585a0e4a73f
MD5 5af3f9613b34b3881b525ec8d0b51a26
BLAKE2b-256 bf91c8023d201cd4585cd2eb9bad6ba1493ae496b2e6f05eeb82ebceba65eefe

See more details on using hashes here.

File details

Details for the file django_admin_client-0.2.4-py3-none-any.whl.

File metadata

  • Download URL: django_admin_client-0.2.4-py3-none-any.whl
  • Upload date:
  • Size: 11.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.6.7

File hashes

Hashes for django_admin_client-0.2.4-py3-none-any.whl
Algorithm Hash digest
SHA256 7e16c5b3a2c097b2c8af7470814830fc76661b23760ca94617420b3659156d25
MD5 d1863e9cf93aa6374e6202142d3e998f
BLAKE2b-256 0e617a1cb33195ca93af09985a8e0778f2cd707737c9d2b428940e2b7f0e9079

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page