Chụp các tham số url trong request.GET


458

Tôi hiện đang xác định các biểu thức chính quy để ghi lại các tham số trong một url, như được mô tả trong hướng dẫn. Làm cách nào để truy cập các tham số từ url như một phần của HttpRequestđối tượng? My HttpRequest.GEThiện trả lại một QueryDictđối tượng trống .

Tôi muốn học cách làm điều này mà không cần thư viện để tôi có thể hiểu Django hơn.

Câu trả lời:


661

Khi url giống như :domain/search/?q=haha , thì bạn sẽ sử dụngrequest.GET.get('q', '') .

qlà tham số bạn muốn và ''là giá trị mặc định nếu qkhông tìm thấy.

Tuy nhiên, nếu bạn chỉ định cấu hình của bạnURLconf , thì các ảnh chụp của bạn regexđược truyền cho hàm dưới dạng đối số (hoặc đối số được đặt tên).

Nhu la:

(r'^user/(?P<username>\w{0,50})/$', views.profile_page,),

Sau đó, trong bạn, views.pybạn sẽ có

def profile_page(request, username):
    # Rest of the method

10
Có phải '? Param =' là cách duy nhất Django nhận ra các tham số? Có cách nào để sử dụng URLconf với HTTP.GET không? Tôi muốn làm / param / 2.
sutee

3
Kiểm tra phần thứ hai của phản hồi của tôi liên quan đến việc nắm bắt URL và regex của bạn.
camflan

2
Không vấn đề gì. sử dụng request.GET nếu bạn gửi biểu mẫu bằng GET, sử dụng request.POST nếu bạn gửi biểu mẫu bằng POST và nếu bạn chỉ muốn định cấu hình URL để có các phần thay đổi, thì đó là đối số URLconf / view.
camflan

10
Những gì về quan điểm dựa trên lớp học?
Người dùng

8
cho các chế độ xem dựa trên lớp bạn có thể sử dụngself.kwargs['parameter']
Royendgel Silberie

336

Để làm rõ lời giải thích của camflan, giả sử bạn có

  • quy tắc url(regex=r'^user/(?P<username>\w{1,50})/$', view='views.profile_page')
  • một yêu cầu đến cho http://domain/user/thaiyoshi/?message=Hi

Quy tắc bộ điều phối URL sẽ bắt các phần của đường dẫn URL (tại đây "user/thaiyoshi/") và chuyển chúng đến chức năng xem cùng với đối tượng yêu cầu.

Chuỗi truy vấn (ở đây message=Hi) được phân tích cú pháp và các tham số được lưu trữ dưới dạng QueryDicttrong request.GET. Không có kết quả khớp hoặc xử lý nào cho các tham số HTTP GET được thực hiện.

Hàm xem này sẽ sử dụng cả hai phần được trích xuất từ ​​đường dẫn URL và tham số truy vấn:

def profile_page(request, username=None):
    user = User.objects.get(username=username)
    message = request.GET.get('message')

Là một lưu ý phụ, bạn sẽ tìm thấy phương thức yêu cầu (trong trường hợp này "GET"và đối với các biểu mẫu đã gửi thường "POST") trong request.method. Trong một số trường hợp, thật hữu ích để kiểm tra xem nó có khớp với những gì bạn mong đợi không.

Cập nhật: Khi quyết định nên sử dụng đường dẫn URL hoặc các tham số truy vấn để truyền thông tin, những điều sau đây có thể giúp:

  • sử dụng đường dẫn URL để xác định tài nguyên duy nhất, ví dụ: /blog/post/15/(không /blog/posts/?id=15)
  • sử dụng các tham số truy vấn để thay đổi cách hiển thị tài nguyên, ví dụ /blog/post/15/?show_comments=1hoặc/blog/posts/2008/?sort_by=date&direction=desc
  • để tạo URL thân thiện với con người, tránh sử dụng số ID và sử dụng ví dụ: ngày, danh mục và / hoặc sên: /blog/post/2008/09/30/django-urls/

17
Đây là một câu trả lời thực sự tốt bằng văn bản. Nó chắc chắn đã giúp tôi hiểu Django tốt hơn một chút.
Đánh dấu

2
làm thế nào chúng ta có thể nhận được tất cả các giá trị tham số mà không đề cập đến tên
Numah

@numerah request.GET là một từ điển Python. Bạn có thể ví dụ lặp qua request.GET.items ().
akaihola

câu trả lời hoàn hảo.
Jay Geeth

1
bất kỳ lý do tại sao nó được ưa thích để làm theo các thói quen được viết trong bản cập nhật? (khi nào nên sử dụng đường dẫn URL so với thông số GET)
m0etaz

55

Sử dụng NHẬN

request.GET["id"]

Sử dụng POST

request.POST["id"]

27
Trong khi điều này hoạt động cho các khóa hiện có, câu trả lời của camflan và akaihola đã sử dụng .get () để tránh KeyErrortrường hợp ngoại lệ trong trường hợp thiếu khóa. Sẽ là khôn ngoan khi làm như vậy (ví dụ request.POST.get('id', '')).
differlysuperiorman

25
def some_view(request, *args, **kwargs):
    if kwargs.get('q', None):
        # Do something here ..

21

Đối với các tình huống mà bạn chỉ có requestđối tượng bạn có thể sử dụngrequest.parser_context['kwargs']['your_param']


2
Chính xác những gì tôi cần. Cảm ơn.
dùng4052054

20

Tôi muốn thêm một số tùy chọn của mình ở đây. Ai đó sẽ tự hỏi làm thế nào để thiết lập đường dẫn trong urls.py, chẳng hạn như

domain/search/?q=CA

để chúng ta có thể gọi truy vấn.

Thực tế là KHÔNG cần thiết phải đặt tuyến đường như vậy trong urls.py. Những gì bạn cần đặt chỉ là tuyến đường trong urls.py

urlpatterns = [
    path('domain/search/', views.CityListView.as_view()),
]

và khi bạn nhập vào http: // servername: port / miền / tìm kiếm / q = CA . Phần truy vấn '? Q = CA' sẽ được tự động dành riêng trong bảng băm mà bạn có thể tham khảo

request.GET.get('q', None).

Dưới đây là một ví dụ (lượt xem)

class CityListView(generics.ListAPIView):
    serializer_class = CityNameSerializer

    def get_queryset(self):
        if self.request.method == 'GET':
            queryset = City.objects.all()
            state_name = self.request.GET.get('q', None)
            if state_name is not None:
                queryset = queryset.filter(state__name=state_name)
            return queryset

Ngoài ra, khi bạn viết chuỗi truy vấn bằng Url

http://servername:port/domain/search/?q=CA

Không gói chuỗi truy vấn trong dấu ngoặc kép, vd

http://servername:port/domain/search/?q="CA"

Xin chào Eric! Tôi mới đến Django. Bạn có thể làm sáng tỏ hơn về "queryset = queryset.filter (state__name = state_name)". Dấu gạch dưới kép ở trạng thái nào có nghĩa là gì.
Subbu

1
Ở đây "trạng thái" là một bảng và "tên" là một tệp trong bảng này. Trong bộ lọc của Django, state__name sẽ tham chiếu giá trị của trường "tên" trong bảng "trạng thái".
Eric Andrew

cái này làm việc so với những cái khác
Sibish

17

Tôi muốn chia sẻ một mẹo có thể giúp bạn tiết kiệm thời gian.
Nếu bạn có kế hoạch sử dụng một cái gì đó như thế này trong urls.pytập tin của bạn :

url(r'^(?P<username>\w+)/$', views.profile_page,),

Về cơ bản có nghĩa là www.example.com/<username>. Hãy chắc chắn đặt nó ở cuối các mục nhập URL của bạn, bởi vì nếu không, nó có thể gây ra xung đột với các mục nhập URL bên dưới, tức là việc truy cập một trong số chúng sẽ gây ra lỗi cho bạn: User matching query does not exist.

Tôi vừa tự trải nghiệm; hy vọng nó giúp!


2
Ngoài ra, trong trường hợp này, bạn có thể muốn kiểm tra xem tên người dùng không va chạm với các đối tượng url khác.
DrKaoliN

13

Bạn có hai cách phổ biến để làm điều đó trong trường hợp url của bạn trông như thế:

https://domain/method/?a=x&b=y

v1:

Nếu khóa cụ thể là bắt buộc, bạn có thể sử dụng:

key_a = request.GET['a']

Điều này sẽ trả về một giá trị là a nếu khóa tồn tại và Ngoại lệ nếu không.

v2:

Nếu khóa của bạn là tùy chọn:

request.GET.get('a')

Bạn có thể thử mà không có bất kỳ đối số này sẽ không sụp đổ. Vì vậy, bạn có thể gói nó với try: except:và trở lại HttpResponseBadRequest()trong ví dụ. Đây là một cách đơn giản để làm cho mã của bạn bớt phức tạp hơn mà không cần sử dụng xử lý Ngoại lệ đặc biệt.


Làm thế nào tôi có thể phát hiện param truy vấn từ mẫu?
Akin Hwan

8

Đây không phải là chính xác những gì bạn yêu cầu, nhưng đoạn này là hữu ích cho việc quản lý query_stringstrong templates.


5

Các truy vấn này hiện đang được thực hiện theo hai cách. Nếu bạn muốn truy cập các tham số truy vấn (GET), bạn có thể truy vấn như sau:

http://myserver:port/resource/?status=1
request.query_params.get('status', None) => 1

Nếu bạn muốn truy cập các tham số được truyền bởi POST, bạn cần truy cập theo cách này:

request.data.get('role', None)

Truy cập từ điển (QueryDict) bằng 'get ()', bạn có thể đặt giá trị mặc định. Trong các trường hợp trên, nếu 'trạng thái' hoặc 'vai trò' không được thông báo, các giá trị là Không có.


0

Đây là một giải pháp thay thế khác có thể được thực hiện:

trong cấu hình url. :

urlpatterns = [path('runreport/<str:queryparams>', views.get)]

trong các quan điểm:

list2 = queryparams.split("&")
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.