web-dev-qa-db-ja.com

Django.core.urlresolvers reverse()呼び出しにクエリ文字列を含める

名前付きURLを逆にして、それにクエリ文字列を含めようとしています。基本的に、ログイン関数を変更しましたが、その中で_?next=_を送信したいと思います。

これが私が今やっていることです:reverse(name) + "?next=" + reverse(redirect)

これが私がやりたいことです:reverse(name, kwargs = { 'next':reverse(redirect) } )

ログインページのURL(例として)は次のようになります。

url(r'^login/', custom_login, name = 'login'),

それで、どうすればこの全体を変更(または呼び出し)して、連結することなく次のものを含めることができますか?それはせいぜい不確かな解決策のように感じます。

41
Brian Hicks

あなたはあなたのメソッドが正しいので、URL confsでGETパラメータをキャプチャすることはできません。

私は一般的に文字列フォーマットを好みますが、それは同じことです。
"%s?next=%s" % (reverse(name), reverse(redirect))

http://docs.djangoproject.com/en/dev/topics/http/urls/#what-the-urlconf-searches-against

URLconfは、通常のPython文字列として要求されたURLを検索します。これには、GETまたはPOSTパラメータ、またはドメイン名は含まれません。

47

私は質問で尋ねられたような私の独自のユーティリティ関数を作成しました:

from Django.utils.http import urlencode

def my_reverse(viewname, kwargs=None, query_kwargs=None):
    """
    Custom reverse to add a query string after the url
    Example usage:
    url = my_reverse('my_test_url', kwargs={'pk': object.id}, query_kwargs={'next': reverse('home')})
    """
    url = reverse(viewname, kwargs=kwargs)

    if query_kwargs:
        return u'%s?%s' % (url, urlencode(query_kwargs))

    return url
24
Daniel Backman

このAPIを公開するには、Djangoのreverseメソッドをラップする方が良いと思います。これを行うための簡単なコードを以下に示します。

from Django.core.urlresolvers import reverse as Django_reverse

def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None, current_app=None):
    """
    Wrapper of Django.core.urlresolvers.reverse that attaches arguments in kwargs as query string parameters
    """
    if kwargs:
        return '%s?%s' % (Django_reverse(viewname, urlconf, args, None, prefix, current_app), \
                        '&'.join(['%s=%s' % (k,v) for k,v in kwargs.items()]))
    else:
        return Django_reverse(viewname, urlconf, args, kwargs, prefix, current_app)

このコードをDjangoにのみ依存するユーティリティまたは一般的なアプリに挿入し、Django.core.urlresolvers.reverseをインポートする代わりに、myproject.myutils.urlresolvers.reverseをインポートするだけです。

7
Alan Illing

私は同じ質問で困っていて、これを見つけました link 。どうやら、あなたのソリューションはまったく悪い設計ではありません。チケットの議論によるとDjangoはこの機能を提供しません。

rlobject または furl を使用できます。

もう1つの方法は、独自の関数を使用して、よりクリーンな方法でこれを行うことです。これは議論で述べられたものです

from Django.utils.http import urlencode
from Django.core.urlresolvers import reverse as original_reverse

def reverse(*args, **kwargs):
    get = kwargs.pop('get', {})
    url = original_reverse(*args, **kwargs)

    if get:
        url += '?' + urlencode(get)

    return url

質問の場合、次のように使用できます

from [myfunctions] import reverse
...
reverse('login', get={next: reverse(redirect)})

クエリをオプションのままにするには、Djangoの逆関数を、クエリを処理する独自の関数でラップして、逆関数の他の適切な処理を可能にします。

適切なリクエストの作成-query_kwargsはオプションなので、送信する必要はありません

# from a views in views.py
def sendingView(request, truckID, fleetSlug):
  #in the GET or POST
  return HttpResponseRedirect(reverse('subAppName:urlViewName', 
                                      kwargs={'anyPassedKawrgs':goHere,…},
                                      query_kwargs={'queries': goHere}
                                      ))

# from a template in specificTemplate.html
<a class="nav-link" href="{% url 'subAppName:urlViewName' kwarg1=kwarg1 kwarg2=kwarg2 … query_kwargs={'dict':here} %}">Link</a>

#from a model in models.py
class Truck(models.Model):
  name = models.CharField(…)
  def get_absolute_wi_url(self):
    return reverse('subAppName:urlViewName', kwargs={'kwarg1':kwarg1,'kwarg2':kwarg2})

utils.pyファイル(に基づいて docs )(1.11以降?)

-myMainApp
  -apps
  -static
  ...
  -utils
    -__init__.py
    -utils.py

from Django.core.urlresolvers import reverse as Django_reverse

def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None, query_kwargs=None):
  """
  Wrapper of Django.core.urlresolvers.reverse that attaches arguments in kwargs as query string parameters
  """
  if query_kwargs:
    return '%s?%s' % (Django_reverse(viewname, urlconf, args, kwargs, current_app), \
                    '&'.join(['%s=%s' % (k,v) for k,v in query_kwargs.items()]))
  else:
    return Django_reverse(viewname, urlconf, args, kwargs, current_app)

URL conf urls.py

app_name = 'subAppName'
urlpatterns = [
  url(r'^(?P<kawrg1>[a-zA-Z0-9]+)/(?P<kawrg2>[a-zA-Z0-9]+)/path/to/here/$', views.urlViewFunctionName, name='urlViewName'),

そしてクエリにアクセスする

#in a view
def urlViewFunctionName(request, kwarg1, kwarg2):   
  if request.GET.get('submittedData'):
    submittedQuery = request.GET.get('submittedData')
else:
  submittedQuery = None
return render(request, 'trucks/weeklyInspectionSuccess.html', {
  'truck': truck,
  'submittedQuery': submittedQuery
})

#in a template
<div class="container">  
  Success for {{kwarg1}}
  {{submittedQuery}}
</div>
1
chris Frisina