code: def qurl(parser, token):
      
      bits = token.split_contents()
      if len(bits) < 2:
          raise TemplateSyntaxError(
              '"{0}" takes at least one argument (url)'.format(bits[0]))
  
      if bits.count('|') > 1:
          raise TemplateSyntaxError(
              '"{0}" may take only one separator'.format(bits[0]))
  
      if bits.count('|'):
          # A url expression was passed, needs reversing
          url = _get_url_node(parser, bits[:bits.index('|')])
          bits = bits[bits.index('|')+1:]
      else:
          # A url was passed directly
          url = parser.compile_filter(bits[1])
          bits = bits[2:]
  
      asvar = None
      if len(bits) >= 2 and bits[-2] == 'as':
          asvar = bits[-1]
          bits = bits[:-2]
  
      qs = []
      if len(bits):
          kwarg_re = re.compile(r"(\w+)(\-=|\+=|=|\-\-)(.*)")
          for bit in bits:
              match = kwarg_re.match(bit)
              if not match:
                  raise TemplateSyntaxError("Malformed arguments to url tag")
              name, op, value = match.groups()
              qs.append((name, op, parser.compile_filter(value),))
  
      return QURLNode(url, qs, asvar)
docs: Append, remove or replace query string parameters (preserve order)
  
          {% qurl url [param]* [as <var_name>] %}
  
          {% qurl 'reverse_name' [reverse_params] | [param]* [as <var_name>] %}
  
      param:
              name=value: replace all values of name by one value
              name=None: remove all values of name
              name+=value: append a new value for name
              name-=value: remove the value of name with the value
  
      Example::
  
          {% qurl '/search?page=1&color=blue&color=green'
                   order='name' page=None color+='red' color-='green' %}
          Output: /search?color=blue&order=name&color=red
  
          {% qurl request.get_full_path order='name' %}