Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Rest Framework, passing attributes in the url

So I have this 2 models:

class ProductQualityMonitor(models.Model):

    product_name = models.CharField(..)
    area = models.CharField(...))
    timeslot = models.DateTimeField(...)

    def get_measured_parameters(self):
        (...)

class QualityParameter(models.Model):
    PARAMETER_CHOICES = (
        (MEAN, MEAN),
        (MEDIAN, MEDIAN),
        (MAXIMUM, MAXIMUM),
        (MINIMUM, MINIMUM),
    )

    name = models.CharField(max_length=50, choices=PARAMETER_CHOICES)
    value = models.FloatField()
    product = models.ForeignKey(ProductQualityMonitor,
                                related_name="parameters")

I need to get some aggregate stats about the quality parameters. I have a method that receives some attributes, like the date range, and aggregates the stats ten by ten for each parameter, and at the end returns a json object with all the aggregate stats.

My doubt is: can I call this method, passing the parameters that the method needs in the url, and see the results? And, if i can, how do I do it?

Sorry if my explanation is a little messy, I am new in Django.

like image 678
Sara Tomaz Avatar asked Oct 07 '15 14:10

Sara Tomaz


1 Answers

Two ways I did to pass attributes from URL for Django REST framework:

1. From URL path

Sample URL: http://127.0.0.1:8000/myurl/passthisstringfrompath

In urls.py (with the assumption that the attribute is a string):

urlpatterns = [
    path('myurl/<str:myattribute1>/', MyRestApiView.as_view()),
]

In views.py:

class MyRestApiView(APIView):
    def get(self, request, *args, **kwargs):
        if kwargs.get("myattribute1", None) is not None:
            print("the passed attribute:", kwargs["myattribute1"]) # this should print "passthisstringfrompath"
        return Response()
    def post(self):
        pass

The parameter *args and **kwargs are the Python way of passing undefined number of list (*args) and dict (**kwargs) objects, something like Args... in C++, more info here. This is used because in class based views, URL parameters are fetched from this kwargs, more info here.

2. From URL query parameters

Sample URL: http://127.0.0.1:8000/myurl/?myattribute1=passthisstringfromparam

In urls.py:

urlpatterns = [
    path('myurl/', MyRestApiView.as_view()),
]

In views.py:

class MyRestApiView(APIView):
    def get(self, request):
        if request.GET.get("myattribute1", None) is not None:
            print("the passed attribute:", request.GET["myattribute1"]) # this should print "passthisstringfromparam"
        return Response()
    def post(self):
        pass

Or better yet just use "query_params" as advised in documentation for Django under https://www.django-rest-framework.org/api-guide/requests/ by literally substituting all instances of "request.GET" to "request.query_params" and then everything else the same.

Additional info

Of course you can combine both ways above to support URLs that are a combination of both such as: http://127.0.0.1:8000/myurl/passthisstring/?mynextattribute=thenthissecond&mylastattribute=andthenthislast

Where:

  • kwargs["myattribute1"] = "passthisstring"
  • request.query_params["mynextattribute"] = "thenthissecond"
  • request.query_params["mylastattribute"] = "andthenthislast"

Beware of the order of urlpatterns to not mix one with another, always put more specific ones at front of the list:

urlpatterns = [
    path('myurl/<str:myattribute1>/', MyRestApiView.as_view()),
    path('myurl/', MyRestApiView.as_view()),
]

Or better yet, you could also simplify this urlpatterns into a single pattern which takes into account the case when the input attribute is optional:

urlpatterns = [
    re_path('myurl/(?:(?P<myattribute1>\w+)/?)?', MyRestApiView.as_view()),
]

Just beware of the trailing slash / at the end so that the following URLs would lead to the same resource:

  • http://127.0.0.1:8000/myurl/passthisstring
  • http://127.0.0.1:8000/myurl/passthisstring/
like image 105
Niel Godfrey Ponciano Avatar answered Oct 12 '22 12:10

Niel Godfrey Ponciano