Package: dgeq
DGeQDGeQ (DjangoGenericQuery) is a package that allows the construction of complexGETquery on anyModel. It implements aquery stringsyntaxallowing 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 onreadthedocs.FeaturesYou can choose which field of whichModelcan be queried.Natively support the follow types :int,float,string,boolean,dateandNoneNatively support most of Django's lookup function :(i)exact,(i)contains,(i)startswith,(i)endswith,gt(e)andlt(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 thequery stringsyntax can also be customized.You can find more about the syntax, and the possibility it offershere.Requirementspython >= 3.6.0django >= 2.0.0dateutil >= 2.8.0Test it Online!You can testDGeQthere if you want :https://dgeq.qcoumes.com/.Quick ExampleLet's show whatDGeQcan do using the following models:# models.pyclassContinent(models.Model):name=models.CharField(max_length=255,unique=True)classRegion(models.Model):name=models.CharField(max_length=255,unique=True)continent=models.ForeignKey(Continent,on_delete=models.CASCADE,related_name="regions")classCountry(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")classRiver(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_GETdefcontinent(request:HttpRequest):q=dgeq.GenericQuery(models.Continent,request.GET)returnJsonResponse(q.evaluate())@require_GETdefregion(request:HttpRequest):q=dgeq.GenericQuery(models.Region,request.GET)returnJsonResponse(q.evaluate())@require_GETdefcountry(request:HttpRequest):q=dgeq.GenericQuery(models.Country,request.GET)returnJsonResponse(q.evaluate())@require_GETdefriver(request:HttpRequest):q=dgeq.GenericQuery(models.River,request.GET)returnJsonResponse(q.evaluate())In the following examples, the used URL pattern is[model]/?[query]. For instance, if we want to
query the continentAfrica: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 withstan, 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}CHANGELOG0.4.0Updated github workflows.0.4.0Breaking changes.Rewritten most of the project.A more complete documentation.0.3.7Default and maxc:limitcan now be defined insettings.pythroughDGEQ_DEFAULT_LIMITandDGEQ_MAX_LIMIT.Dotted path to models can now be used forDGEQ_PRIVATE_FIELDS.0.3.7userargument is now mandatory only whenuse_permission=Trueinutils.serialize0.3.6userargument is now mandatory only whenuse_permission=True0.3.5Fix an error occurring when aForeignFieldis NoneUser's password are private by default0.3.4Fix an exception when norelated_nameis given on a related field0.3.3Reverse field's name are now correctly fetched0.3.2Joins now correctly account for nullable foreign key0.3.1Minor fix0.3.0Instead 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.Addedc:distinctcommand as well asdistinctargument for forc:join. A
new function calleddcount(to make distinct count) has been added forc:aggregateandc:annotate.0.2.1Addedserialize()method to serialize a model instance in the same format
as aGenericQuery's row.0.2.0Now can allow only specific field for each Model, or can use django's permission system0.1.1 & 0.1.2Added missing MANIFEST.in0.1.0Initial release