Skip to main content

A framework based on Django that has tried to gather together the tools needed in the process of creating a large project.

Project description

Gando — Django toolkit & conventions for Horin Software Group

PyPI License Gando Logo

Gando is a collection of batteries-included tools, conventions and scaffolding utilities built on top of Django to standardize and accelerate development for the Horin engineering teams. Named after Gando — a small, native crocodile of Sistan and Baluchestan — the project is compact, tough and purpose-built for the local needs of your org.


Quick summary

  • What it is: A small framework of opinionated building blocks for Django projects: base abstract models, useful model fields (image + validators), admin base classes, API response/exception schemas, request helpers, scaffolding management commands (startmodel, startapi, startservice, startinterface, ...), and utilities (image converters/uploaders, string casings, etc).
  • Why: Aligns Horin internal projects around shared error/response shapes, admin patterns, and developer ergonomics—reduces copy/paste and onboarding time.
  • Status: Actively developed and extended; features are added on demand.

Table of contents

  1. Key features
  2. Install
  3. Quickstart (5–10 min)
  4. Core concepts & architecture
  5. Examples (models, admin, API flow)
  6. Management commands / scaffolding
  7. Response & request contract
  8. Important notes, gotchas & recommended fixes
  9. Development, tests & CI
  10. Roadmap & contributing
  11. License & contact

Key features

  • Opinionated base models: AbstractBaseModel, WhiteAbstractBaseModel, AbstractBaseModelFaster (history-enabled, timestamps, availability flag).
  • AvailableManager (named Manager in current code) that filters available=1 by default.
  • Rich image support: ImageField (multi-subfields), ImageProperty descriptor, BlurBase64Field computed preview.
  • Validators & typed model fields: PhoneNumberField, UsernameField, PasswordField, BooleanNumberField.
  • BaseModelAdmin — unified Admin list/filters/readonly behavior and image field rendering.
  • API scaffolding: ResponseSchema, RequestSchema, Base / BaseInterface for method dispatch and unified response format.
  • Scaffolding commands to create repositories, schemas, APIs, interfaces, services and models automatically following the gando conventions.
  • Utilities: string casings, image converter (small blur base64), uploaders, and request/response helpers.

Install

# (recommended: inside virtualenv)
pip install gando

or for local editable development:

git clone https://github.com/navidsoleymani/gando.git
cd gando
pip install -e .

Minimum safe setup.py/pyproject expectations:

  • python_requires='>=3.8'
  • Pin runtime dependencies more conservatively in the future, e.g. Django>=4.2,<5.0, djangorestframework>=3.12.

Quickstart (minimal)

  1. Add to INSTALLED_APPS in settings.py:
INSTALLED_APPS = [
  # ...
  "gando",
  # other apps
]
  1. Use an abstract model:
from gando.models import AbstractBaseModel  # path may vary


class Article(AbstractBaseModel):
  title = models.CharField(max_length=300)
  body = models.TextField()
  1. Use the ImageField helper:
from gando.models import AbstractBaseModel, ImageField


class Product(AbstractBaseModel):
  image = ImageField()
  title = models.CharField(max_length=255)
  1. Admin — reuse the standard admin scaffold:
from django.contrib import admin
from gando.admin import BaseModelAdmin
from .models import Product


@admin.register(Product)
class ProductAdmin(BaseModelAdmin):
  list_display = ['title', 'image']
  1. Create scaffolds (from project root):
python manage.py startmodel -al your_app_label -mn Product
python manage.py startapi   -al your_app_label -an Product
python manage.py startservice -al your_app_label -sn Product
python manage.py startinterface -al your_app_label -in Product

(The flags are: -al/--applabel, -mn/--modelname, -an/--apiname, -sn/--servicename, -in/--interfacename.)

  1. Migrate and run:
python manage.py makemigrations
python manage.py migrate
python manage.py runserver

Core concepts & architecture

Design philosophies (applies across gando):

  • Conventions over configuration — provide sane defaults (timestamps, availability, admin lists) so teams are consistent.
  • Separation of concernsarchitectures contains apis, interfaces, services, models and serializers and enforces a flow: API / Interface -> Service -> Repo/Models -> Serializers -> Response.
  • Unified contracts — server and client share RequestSchema / ResponseSchema shapes to avoid divergence.
  • Scaffold-first — management commands create consistent package/module layout (repo, schemas, apis, services).

Typical request flow:

  1. HTTP request arrives at an API view (generated by scaffolding).
  2. Request parsed into RequestSchema.
  3. BaseInterface or Base dispatches to a method (get, post, etc).
  4. Interface calls a Service that encapsulates business logic.
  5. Service interacts with repo models and returns domain data.
  6. Response wrapped by ResponseSchema and returned.

Examples — Model → Service → API → Response

Model:

from gando.models import AbstractBaseModel, ImageField


class Banner(AbstractBaseModel):
  title = models.CharField(max_length=200)
  image = ImageField()

Service (conceptual):

from gando.architectures.services import BaseService


class BannerService(BaseService):
  def get_banner(self, banner_id):
    banner = Banner.objects.filter(id=banner_id).first()
    if not banner:
      return {"error": "not_found"}, 404
    return {"banner": BannerSchema.from_orm(banner).dict()}, 200

API / Interface (conceptual):

from gando.architectures.apis import BaseAPI  # or BaseInterface


class BannerAPI(BaseAPI):
  def get(self, request, banner_id):
    data, status = BannerService().get_banner(banner_id)
    return ResponseSchema(success=(status == 200), status_code=status, data=data)

Client-side Response wrapperBaseResponseSchema expects the JSON shape used across gando.


Management commands / scaffolding (details)

Gando provides a set of management commands that scaffold folders and files in the target app:

  • startmodel -al <app_label> -mn <modelname> Creates repo/models/__<ModelName>.py, updates repo/models/__init__.py, app-level models.py, admin.py entries, repo/schemas/models/__<modelname>.py, and URL includes.

  • startapi -al <app_label> -an <apiname> Creates repo/apis/__<ApiName>.py with a base API class.

  • startservice -al <app_label> -sn <servicename> Creates service module templates and schema folders.

  • startinterface -al <app_label> -in <interfacename> Creates interface templates under repo/interfaces.

Note: commands rely on settings.BASE_DIR and the app folder structure; run them from the project root.


Response & request contract

Gando standardizes API payloads. A canonical successful response includes:

{
  "success": true,
  "status_code": 200,
  "has_warning": false,
  "exception_status": false,
  "monitor": {},
  "messenger": [],
  "many": false,
  "data": {
    /* object or list depending on many */
  },
  "development_messages": {}
}

ResponseSchema (server) and BaseResponseSchema (client helpers) map to the same shape. Use these everywhere to keep client & server consistent, reduce parsing errors and simplify error handling.


Important notes, gotchas & recommended fixes

I reviewed the code you supplied deeply. Below are concrete findings and recommendations to make Gando safer, more robust and production-friendly.

1. Manager naming & available field

  • Issue: Generic name Manager. It's better to name AvailableManager or ActiveManager.
  • Recommendation: Consider using BooleanField if available is binary; if you anticipate more states, keep integer but rename to status/availability_state with an Enum.

2. QueryDictSerializer problems

  • __image_field_name_parser uses a equal variable that is not correctly reset per loop — this creates incorrect prefix matching.
  • __updater function is fragile and can lose values or produce inconsistent structures for nested merges.
  • __media_url uses a bare except: — this hides unrelated errors.

Fix suggestions (high level):

  • Replace prefix comparison logic with str.startswith(prefix).
  • Implement a robust deep_merge(a, b) for dictionaries where b values override or are appended appropriately.
  • Use getattr(settings, "MEDIA_URL", "") instead of try/except.

Short fixed sketch (extract):

# safer prefix check
def __image_field_name_parser(self, field_name):
  for img in self.image_fields_name:
    if field_name.startswith(img + "_"):
      return [img, field_name[len(img) + 1:]]
  return [field_name]


# safer media url
from django.conf import settings


@property
def __media_url(self):
  return getattr(settings, 'MEDIA_URL', '')

(I can provide a full refactor patch if you want — it will be longer but makes the serializer robust.)

3. BlurBase64Field.pre_save and remote storage

  • Issue: small_blur_base64(_src.file.name) assumes a local filename and direct filesystem access. If you use remote storages (S3, GCS) this will fail.
  • Recommendation: Read file content via Django storage API:
from django.core.files.storage import default_storage

if _src:
  try:
    with default_storage.open(_src.name, 'rb') as fh:
      blur = small_blur_base64(fh.read())  # accept bytes in small_blur_base64
      setattr(model_instance, self.attname, blur)
  except Exception:
    # handle/log but don't silence unexpected exceptions
    raise

Also consider moving small_blur_base64 processing off the request thread to a background job (Celery) or compute it once on upload.

4. Bare except: usage

  • There are several except: usages that silence all exceptions. Replace with targeted exception types, or at least log and re-raise unexpected ones.

5. BaseModelAdmin behavior & names

  • list_display setter uses id_, available_ names which are fine, but keep docstrings and explicit list_display examples in README.
  • Document image_fields_name_list usage in admin to ensure image fieldsets are created.

6. Management commands argument handling

  • The command handlers expect kwargs dict and set self.app_label = kwargs. The setter then reads kwargs.get('applabel'). This works but is unusual — be explicit in docs that flags are named -al/--applabel etc. Also check behavior when flags are missing: the code raises CommandError as expected.

7. History size & retention

  • HistoricalRecords on many models can balloon DB size. Add guidance for history pruning or retention policies.

8. Packaging / dependencies

  • In setup.py you currently list unpinned dependencies: prefer minimum versions and ranges for stability, e.g. Django>=4.2,<5.0, djangorestframework>=3.12,<4.0.

Development, tests & CI

Recommended development stack for the repo:

  • Formatter & linters: Black, isort, flake8
  • Type checks: mypy (use strictness progressively)
  • Testing: pytest + pytest-django
  • Coverage: coveralls or codecov; aim for > 80% initially.
  • Pre-commit hooks: pre-commit for formatting and sanity checks.
  • Docs: Sphinx with sphinx-autodoc + READTHEDOCS pipeline
  • CI: GitHub Actions (lint → tests → packaging → publish on tags)

Example .github/workflows/ci.yml stages:

  1. Install dependencies (pinned).
  2. Run black --check, isort --check, flake8.
  3. Run tests with pytest.
  4. Publish wheel on tag.

Roadmap (suggested)

  • v0.1.x: Stabilize current APIs, fix QueryDictSerializer, address image storage, add tests & docs.
  • v0.2.x: Add optional DRF/async adaptors, Celery tasks for image processing, plugin hooks.
  • v1.0.0: Public stable release with SemVer, complete docs, examples project and migration guides.

Use Semantic Versioning (MAJOR.MINOR.PATCH) and maintain a CHANGELOG.md following Keep a Changelog.


Contributing

  1. Fork the repo and create a feature branch.
  2. Run tests locally.
  3. Format code with black and check flake8.
  4. Open PR describing the change and tests.
  5. Maintainers will review and merge after CI passes.

Please include unit tests for behavior changes and update docs when public APIs change.


License & contact

Gando is released under the MIT License. See LICENSE for details. Author: Hydra (navidsoleymani@ymail.com) — repository: https://github.com/navidsoleymani/gando.git.


Appendix — Short patch examples

1) Safer __media_url:

from django.conf import settings


@property
def __media_url(self):
  return getattr(settings, 'MEDIA_URL', '')

2) Simpler image prefix parser:

def __image_field_name_parser(self, field_name):
  # return [prefix, suffix] if field_name starts with any image prefix
  for img in self.image_fields_name:
    prefix = f'{img}_'
    if field_name.startswith(prefix):
      return [img, field_name[len(prefix):]]
  return [field_name]

3) Example deep_merge (dict merge):

def deep_merge(a, b):
  if not isinstance(a, dict) or not isinstance(b, dict):
    return b
  out = dict(a)
  for k, v in b.items():
    if k in out and isinstance(out[k], dict) and isinstance(v, dict):
      out[k] = deep_merge(out[k], v)
    elif k in out and isinstance(out[k], list) and isinstance(v, list):
      out[k] = out[k] + v
    else:
      out[k] = v
  return out

Final note

You already have a strong, well-structured foundation. With a few fixes (robust serializer merging, safe storage access, explicit exception handling) and solid test coverage, Gando will be a great, reliable toolkit for Horin projects.

If you want, I can now:

  • produce a full, polished README.md file ready to replace the one in your repo (I can drop it into the canmore canvas or paste it here), or
  • prepare a PR-style patch with the exact code changes for the QueryDictSerializer, BlurBase64Field.pre_save, and other issues I flagged.

Which of those do you want me to do next?

Project details


Release history Release notifications | RSS feed

Download files

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

Source Distribution

gando-2.0.0.tar.gz (69.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gando-2.0.0-py3-none-any.whl (97.9 kB view details)

Uploaded Python 3

File details

Details for the file gando-2.0.0.tar.gz.

File metadata

  • Download URL: gando-2.0.0.tar.gz
  • Upload date:
  • Size: 69.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for gando-2.0.0.tar.gz
Algorithm Hash digest
SHA256 b16c172ea33c41ccc745b29850f1f83370e41dd35c938cb5dafc3befc3620cc1
MD5 03a1f6bbba84a23b515fc5157a2c3c66
BLAKE2b-256 118267d7b36c7883233992d89aa081f1440f70f770f61a75f118d930b0a42de7

See more details on using hashes here.

File details

Details for the file gando-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: gando-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 97.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for gando-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6c9ccba134c99d7ff081329d28258ea1aa54035a6ca5b630edaea8339e358030
MD5 99e7bd52b8b628f7269f504618b6b8c9
BLAKE2b-256 959aea1bc4ec37757c8f8c0f9c26a41e85c564129bffa5b6a94bf3e302ef0f75

See more details on using hashes here.

Supported by

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