Correct way to validate GET parameters in django












3















I'm building a social website that uses django templates/dynamic pages (no SPA technology in place).
I have some ajax calls that check the users news feed or new messages.
Example GET web request of those looks as follows:



GET /feeds/check/?last_feed=3&feed_source=all&_=1500749662203 HTTP/1.1


This is how I receive it in the view:



@login_required
@ajax_required
def check(request):
last_feed = request.GET.get('last_feed')
feeds = Feed.get_feeds_after(last_feed)


It all works, but I want to protect it so the function get_feeds_after does not crash when a malicious user sets the GET parameter to last_feed="123malicious4556". Currently it crashes because in the Feed model the function does this:



@staticmethod
def get_feeds_after(feed):
feeds = Feed.objects.filter(parent=None, id__gt=float(feed))
return feeds


and crashes with the error:



ValueError at /feeds/check/
invalid literal for float(): 2fff2


I currently solve this by directly performing checks on the GET variable and handling exception on int() casting:



def check(request):
last_feed = request.GET.get('last_feed')
try:
feed_source = int(request.GET.get('last_feed'))
except ValueError:
return HttpResponse(0)


My question is what is the best django-recommended way to address this?
I know django has special support forms validation. But this does not seem quite right here, as the GET calls are more of an api rather than forms so it seems like a bad idea to define forms for those GET parameters.



Thanks










share|improve this question



























    3















    I'm building a social website that uses django templates/dynamic pages (no SPA technology in place).
    I have some ajax calls that check the users news feed or new messages.
    Example GET web request of those looks as follows:



    GET /feeds/check/?last_feed=3&feed_source=all&_=1500749662203 HTTP/1.1


    This is how I receive it in the view:



    @login_required
    @ajax_required
    def check(request):
    last_feed = request.GET.get('last_feed')
    feeds = Feed.get_feeds_after(last_feed)


    It all works, but I want to protect it so the function get_feeds_after does not crash when a malicious user sets the GET parameter to last_feed="123malicious4556". Currently it crashes because in the Feed model the function does this:



    @staticmethod
    def get_feeds_after(feed):
    feeds = Feed.objects.filter(parent=None, id__gt=float(feed))
    return feeds


    and crashes with the error:



    ValueError at /feeds/check/
    invalid literal for float(): 2fff2


    I currently solve this by directly performing checks on the GET variable and handling exception on int() casting:



    def check(request):
    last_feed = request.GET.get('last_feed')
    try:
    feed_source = int(request.GET.get('last_feed'))
    except ValueError:
    return HttpResponse(0)


    My question is what is the best django-recommended way to address this?
    I know django has special support forms validation. But this does not seem quite right here, as the GET calls are more of an api rather than forms so it seems like a bad idea to define forms for those GET parameters.



    Thanks










    share|improve this question

























      3












      3








      3


      3






      I'm building a social website that uses django templates/dynamic pages (no SPA technology in place).
      I have some ajax calls that check the users news feed or new messages.
      Example GET web request of those looks as follows:



      GET /feeds/check/?last_feed=3&feed_source=all&_=1500749662203 HTTP/1.1


      This is how I receive it in the view:



      @login_required
      @ajax_required
      def check(request):
      last_feed = request.GET.get('last_feed')
      feeds = Feed.get_feeds_after(last_feed)


      It all works, but I want to protect it so the function get_feeds_after does not crash when a malicious user sets the GET parameter to last_feed="123malicious4556". Currently it crashes because in the Feed model the function does this:



      @staticmethod
      def get_feeds_after(feed):
      feeds = Feed.objects.filter(parent=None, id__gt=float(feed))
      return feeds


      and crashes with the error:



      ValueError at /feeds/check/
      invalid literal for float(): 2fff2


      I currently solve this by directly performing checks on the GET variable and handling exception on int() casting:



      def check(request):
      last_feed = request.GET.get('last_feed')
      try:
      feed_source = int(request.GET.get('last_feed'))
      except ValueError:
      return HttpResponse(0)


      My question is what is the best django-recommended way to address this?
      I know django has special support forms validation. But this does not seem quite right here, as the GET calls are more of an api rather than forms so it seems like a bad idea to define forms for those GET parameters.



      Thanks










      share|improve this question














      I'm building a social website that uses django templates/dynamic pages (no SPA technology in place).
      I have some ajax calls that check the users news feed or new messages.
      Example GET web request of those looks as follows:



      GET /feeds/check/?last_feed=3&feed_source=all&_=1500749662203 HTTP/1.1


      This is how I receive it in the view:



      @login_required
      @ajax_required
      def check(request):
      last_feed = request.GET.get('last_feed')
      feeds = Feed.get_feeds_after(last_feed)


      It all works, but I want to protect it so the function get_feeds_after does not crash when a malicious user sets the GET parameter to last_feed="123malicious4556". Currently it crashes because in the Feed model the function does this:



      @staticmethod
      def get_feeds_after(feed):
      feeds = Feed.objects.filter(parent=None, id__gt=float(feed))
      return feeds


      and crashes with the error:



      ValueError at /feeds/check/
      invalid literal for float(): 2fff2


      I currently solve this by directly performing checks on the GET variable and handling exception on int() casting:



      def check(request):
      last_feed = request.GET.get('last_feed')
      try:
      feed_source = int(request.GET.get('last_feed'))
      except ValueError:
      return HttpResponse(0)


      My question is what is the best django-recommended way to address this?
      I know django has special support forms validation. But this does not seem quite right here, as the GET calls are more of an api rather than forms so it seems like a bad idea to define forms for those GET parameters.



      Thanks







      python django






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jul 22 '17 at 19:07









      Loop BackLoop Back

      161




      161
























          1 Answer
          1






          active

          oldest

          votes


















          0














          All you actually need are the form fields which do all basic validation for you.
          If you need custom validation you can write your own validator or even better your own custom form field.



          To use the field alone without the form you can do like that for example:



          evalType = forms.CharField().clean(request.GET.get('eval-type'))


          Because calling this way is not very human friendly I prefer to write a function to deal with it:



          def cleanParam(params, paramName, FieldType, *args, **kwargs):
          field = FieldType(*args, **kwargs)
          cleaned = field.clean(params.get(paramName))
          return cleaned


          Which we use this way:



          evalType = cleanParam(request.GET, 'eval-type', forms.CharField)


          This will save you a form class. But I don't think it's very ugly to create a django form for that. A bit too much for the problem but no great concern IMHO.



          The advantage of having a form is that you declare the fields you expect in your api call and can check all at once then see the result of is_valid().



          I hope this helps.






          share|improve this answer

























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f45258208%2fcorrect-way-to-validate-get-parameters-in-django%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            0














            All you actually need are the form fields which do all basic validation for you.
            If you need custom validation you can write your own validator or even better your own custom form field.



            To use the field alone without the form you can do like that for example:



            evalType = forms.CharField().clean(request.GET.get('eval-type'))


            Because calling this way is not very human friendly I prefer to write a function to deal with it:



            def cleanParam(params, paramName, FieldType, *args, **kwargs):
            field = FieldType(*args, **kwargs)
            cleaned = field.clean(params.get(paramName))
            return cleaned


            Which we use this way:



            evalType = cleanParam(request.GET, 'eval-type', forms.CharField)


            This will save you a form class. But I don't think it's very ugly to create a django form for that. A bit too much for the problem but no great concern IMHO.



            The advantage of having a form is that you declare the fields you expect in your api call and can check all at once then see the result of is_valid().



            I hope this helps.






            share|improve this answer






























              0














              All you actually need are the form fields which do all basic validation for you.
              If you need custom validation you can write your own validator or even better your own custom form field.



              To use the field alone without the form you can do like that for example:



              evalType = forms.CharField().clean(request.GET.get('eval-type'))


              Because calling this way is not very human friendly I prefer to write a function to deal with it:



              def cleanParam(params, paramName, FieldType, *args, **kwargs):
              field = FieldType(*args, **kwargs)
              cleaned = field.clean(params.get(paramName))
              return cleaned


              Which we use this way:



              evalType = cleanParam(request.GET, 'eval-type', forms.CharField)


              This will save you a form class. But I don't think it's very ugly to create a django form for that. A bit too much for the problem but no great concern IMHO.



              The advantage of having a form is that you declare the fields you expect in your api call and can check all at once then see the result of is_valid().



              I hope this helps.






              share|improve this answer




























                0












                0








                0







                All you actually need are the form fields which do all basic validation for you.
                If you need custom validation you can write your own validator or even better your own custom form field.



                To use the field alone without the form you can do like that for example:



                evalType = forms.CharField().clean(request.GET.get('eval-type'))


                Because calling this way is not very human friendly I prefer to write a function to deal with it:



                def cleanParam(params, paramName, FieldType, *args, **kwargs):
                field = FieldType(*args, **kwargs)
                cleaned = field.clean(params.get(paramName))
                return cleaned


                Which we use this way:



                evalType = cleanParam(request.GET, 'eval-type', forms.CharField)


                This will save you a form class. But I don't think it's very ugly to create a django form for that. A bit too much for the problem but no great concern IMHO.



                The advantage of having a form is that you declare the fields you expect in your api call and can check all at once then see the result of is_valid().



                I hope this helps.






                share|improve this answer















                All you actually need are the form fields which do all basic validation for you.
                If you need custom validation you can write your own validator or even better your own custom form field.



                To use the field alone without the form you can do like that for example:



                evalType = forms.CharField().clean(request.GET.get('eval-type'))


                Because calling this way is not very human friendly I prefer to write a function to deal with it:



                def cleanParam(params, paramName, FieldType, *args, **kwargs):
                field = FieldType(*args, **kwargs)
                cleaned = field.clean(params.get(paramName))
                return cleaned


                Which we use this way:



                evalType = cleanParam(request.GET, 'eval-type', forms.CharField)


                This will save you a form class. But I don't think it's very ugly to create a django form for that. A bit too much for the problem but no great concern IMHO.



                The advantage of having a form is that you declare the fields you expect in your api call and can check all at once then see the result of is_valid().



                I hope this helps.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Nov 22 '18 at 18:13

























                answered Nov 22 '18 at 17:57









                Eric ChiesseEric Chiesse

                1555




                1555






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f45258208%2fcorrect-way-to-validate-get-parameters-in-django%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Wiesbaden

                    Marschland

                    Dieringhausen