Skip to main content
Archived

This project has been archived by its maintainers, and is no longer receiving any updates.

DGeQ

PyPI Version Python 3.6+ Django 2.0+, 3.0+ License MIT Python package Documentation Status codecov CodeFactor

DGeQ (Django Generic Query) is a package that allows the construction of complex GET query on any Model. It implements a query string syntax allowing filtering, join, annotation, aggregation and more.

Even though this package is primarily intended for the creation of public API, allowing to set new endpoints with only few lines of code, it could also be used to communicate with other services or a front-end framework.

The documentation can be found on readthedocs.

Features

  • You can choose which field of which Model can be queried.

  • Natively support the follow types : int, float, string, boolean, date and None

  • Natively support most of Django's lookup function : (i)exact, (i)contains, (i)startswith , (i)endswith, gt(e) and lt(e).

  • Supports spanning relationship lookup.

  • Support commands such as Joins, Aggregations and Annotations.

  • The syntax allows choosing which field the result should contain, avoiding over-fetching.

  • Highly customizable : Allow the creation of new type, lookup function and commands. Parts of the query string syntax can also be customized.

You can find more about the syntax, and the possibility it offers here.

Requirements

  • python >= 3.6.0
  • django >= 2.0.0
  • dateutil >= 2.8.0

Test it Online!

You can test DGeQ there if you want : https://dgeq.qcoumes.com/.

Quick Example

Let's show what DGeQ can do using the following models:

# models.py

class Continent(models.Model):
    name = models.CharField(max_length=255, unique=True)
    
class Region(models.Model):
    name = models.CharField(max_length=255, unique=True)
    continent = models.ForeignKey(Continent, on_delete=models.CASCADE, related_name="regions")

class Country(models.Model):
    name = models.CharField(max_length=255, unique=True)
    area = models.BigIntegerField()
    population = models.BigIntegerField()
    region = models.ForeignKey(Region, on_delete=models.CASCADE, related_name="countries")

class River(models.Model):
    name = models.CharField(max_length=255, unique=True)
    discharge = models.IntegerField(null=True)
    length = models.IntegerField()
    countries = models.ManyToManyField(Country, related_name="rivers")
# views.py

@require_GET
def continent(request: HttpRequest):
    q = dgeq.GenericQuery(models.Continent, request.GET)
    return JsonResponse(q.evaluate())

@require_GET
def region(request: HttpRequest):
    q = dgeq.GenericQuery(models.Region, request.GET)
    return JsonResponse(q.evaluate())

@require_GET
def country(request: HttpRequest):
    q = dgeq.GenericQuery(models.Country, request.GET)
    return JsonResponse(q.evaluate())

@require_GET
def river(request: HttpRequest):
    q = dgeq.GenericQuery(models.River, request.GET)
    return JsonResponse(q.evaluate())

In the following examples, the used URL pattern is [model]/?[query]. For instance, if we want to query the continent Africa : continent/?name=Africa.

  • Name of all the rivers in China : river/?countries.name=China&c:show=name
{
  "status": true,
    "rows":[
        { "name":"Wu" },
        { "name":"Huai River" },
        { "name":"Yellow River" },
        { "name":"Red (Asia)" },
        { "name":"Ghaghara" },
        { "name":"Salween" },
        { "name":"Indus" },
        { "name":"Amur" },
        { "name":"Ob" },
        { "name":"Irrawaddy River" }
    ]
}
  • Name, population and area of country in Asia finishing with stan, sorted by area :
    country/?region.continent.name=Asia&name=$stan&c:hide=id,region,rivers&c:sort=area
{
  "status":true,
  "rows":[
    {
      "area":142600,
      "population":8880300,
      "name":"Tajikistan"
    },
    {
      "area":199949,
      "population":6189700,
      "name":"Kyrgyzstan"
    },
    {
      "area":448969,
      "population":31959800,
      "name":"Uzbekistan"
    },
    {
      "area":488100,
      "population":5757700,
      "name":"Turkmenistan"
    },
    {
      "area":652864,
      "population":36296100,
      "name":"Afghanistan"
    },
    {
      "area":796095,
      "population":207906200,
      "name":"Pakistan"
    },
    {
      "area":2724902,
      "population":18080000,
      "name":"Kazakhstan"
    }
  ]
}
  • Join the two lengthiest rivers of France :
    country/?name=France&c:join=field=rivers|limit=2|sort=-length|hide=countries
{
  "status": true,
  "rows": [
    {
      "name": "France",
      "area": 551500,
      "population": 64842500,
      "id": 75,
      "region": 20,
      "rivers": [
        {"name": "Rhine", "discharge": 2330, "length": 1233, "id": 43},
        {"name": "Loire", "discharge": 840, "length": 1012, "id": 22}
      ]
    }
  ]
}
  • Sum and Avg of the length of every river in Europe :
    river/?countries.region.continent.name=Europe&c:aggregate=field=length|to=sum_length|func=sum,field=length|to=avg_length|func=avg&c:evaluate=0
{
  "status": true,
  "sum_length": 145943,
  "avg_length": 1871.0641025641025
}

CHANGELOG

0.4.0

  • Updated github workflows.

0.4.0

Breaking changes.

  • Rewritten most of the project.
  • A more complete documentation.

0.3.7

  • Default and max c:limit can now be defined in settings.py through DGEQ_DEFAULT_LIMIT and DGEQ_MAX_LIMIT.
  • Dotted path to models can now be used for DGEQ_PRIVATE_FIELDS.

0.3.7

  • user argument is now mandatory only when use_permission=True in utils.serialize

0.3.6

  • user argument is now mandatory only when use_permission=True

0.3.5

  • Fix an error occurring when a ForeignField is None
  • User's password are private by default

0.3.4

  • Fix an exception when no related_name is given on a related field

0.3.3

  • Reverse field's name are now correctly fetched

0.3.2

  • Joins now correctly account for nullable foreign key

0.3.1

  • Minor fix

0.3.0

  • Instead of calling commands in a specific order, each field/value pair of the query string call the commands with a regex matching the field. The main consequence of this change is that query argument's order now matter.

  • Added c:distinct command as well as distinct argument for for c:join. A new function called dcount (to make distinct count) has been added for c:aggregate and c:annotate.

0.2.1

  • Added serialize() method to serialize a model instance in the same format as a GenericQuery's row.

0.2.0

  • Now can allow only specific field for each Model, or can use django's permission system

0.1.1 & 0.1.2

  • Added missing MANIFEST.in

0.1.0

  • Initial release

Metadata

Release files for dgeq 0.4.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for dgeq 0.4.1
File Size Uploaded Provenance Actions
dgeq-0.4.1.tar.gz 26.8 kB Without provenance Details for dgeq-0.4.1.tar.gz

Release files / dgeq-0.4.1.tar.gz

Download URL dgeq-0.4.1.tar.gz
Size 26.8 kB
Tags Source
SHA-256 checksum
How to use checksums
6ed333301ecbe72db1f38e672067cc8360743786cc32ab5bf2efb93c4d4b55f1
BLAKE2b-256 checksum
How to use checksums
1ec10825c06772f443e37fde5fcd5a8172cebd7421e854de55acbd224fb7d018
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/51.1.2 requests-toolbelt/0.9.1 tqdm/4.56.0 CPython/3.8.7

Security for dgeq 0.4.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page