2013-01-04 22 views
6

Simple đủ ví dụ - Tôi có một chút mã Django rằng bắt đầu với một queryset ...Tại thời điểm những gì được ngoại lệ huy động khi sử dụng ORM Django

queryset = MyModel.objects.all() 

Sau đó nó thực hiện lọc khác nhau, tùy thuộc vào một số cấu hình tùy chọn ...

if something: 
    queryset = self.queryset.filter(foo=some_foo) 

if another_thing: 
    queryset = self.queryset.filter(bar=some_bar) 

Và cuối cùng nó thực hiện các tra cứu ...

try: 
    obj = queryset.get() 
except ObjectDoesNotExist: 
    raise ValidationError('Does not exist') 

Bây giờ, hãy nguyên nhân của cách linh hoạt mà bộ lọc cần phải xảy ra, có thể là các biến số some_foo hoặc some_bar có thể không đúng loại (ví dụ: chúng tôi có thể kết thúc bằng một chuỗi rỗng cố gắng lọc theo trường số nguyên.) vì vậy, mã này có thể kết thúc bằng cách tăng TypeError hoặc ValueError.

Điều đó tốt và tôi có thể xử lý trường hợp một cách phù hợp, nhưng điều không rõ ràng đối với tôi từ hợp đồng ORM, là tại điểm nào tôi có thể mong đợi các ngoại lệ đó được nêu ra.

  • nó sẽ xảy ra trên báo cáo kết quả .filter()? ...
  • ... hoặc trên báo cáo kết quả .get()? ...
  • ... hoặc là trong underspecified, và tôi xử lý nó như thể xảy ra trên một trong hai? (Ví dụ: có lẽ tùy thuộc vào việc thực hiện phụ trợ cơ sở dữ liệu?)
+0

có thể tôi đang thiếu điều gì đó nhưng tôi cần phải hỏi: tại sao bạn gọi điện thoại nhận được trên queryset? filter() và get() có các mục đích khác nhau và cả hai đều thực hiện một truy vấn. và bộ lọc() là truy vấn đầu tiên -> lỗi Loại/Giá trị sẽ được tăng lên trong quá trình lọc. bạn sẽ không đạt được get() –

+0

Lưu ý: Được rồi, tôi có thể thấy trong trường hợp cụ thể này có vẻ như được nêu lên bởi câu lệnh '.get()' (đó là những gì tôi mong đợi) nhưng không rõ liệu tôi có thể an toàn không dựa vào hành vi này để nhất quán. –

+0

@SamueleMattiuzzo Các câu lệnh lọc có thể bị xâu chuỗi. '.get()' cuối cùng là bit thực hiện tra cứu một đối tượng đơn lẻ, được cung cấp truy vấn. –

Trả lời

1

Để trả lời câu hỏi ban đầu, một FieldErrorValueError được nuôi trên các cuộc gọi để lọc, khi một queryset mới được xây dựng:

>>> a = Account.objects.all() 
>>> a = a.filter(id=3) 
>>> a = a.filter(no_exist=3) 
<snip> 
FieldError: Cannot resolve keyword 'no_exist' into field. Choices are: active, created_on, group, id, ... 

>>> a = Account.objects.all() 
>>> a = a.filter(id='abc') 
ValueError: invalid literal for int() with base 10: 'abc' 

Tôi cũng sẽ thêm rằng mẫu này có vẻ gây hiểu lầm cho tôi, trong đó filter thường được sử dụng để trả lại danh sách/có thể lặp lại của các mô hình, thay vì một như với get. Để làm rõ và xử lý dễ dàng hơn trong những trường hợp ngoại lệ, tôi muốn đề nghị mô hình này:

kwargs = {} 
if something: 
    kwargs['foo'] = some_foo 
if another_thing: 
    kwargs['bar'] = some_bar 

# handle if kwargs is empty 
try: 
    obj = MyModel.objects.get(**kwargs) 
except (FieldError, ValueError, ObjectDoesNotExist): 
    raise ValidationError('Does not exist') 

Lợi ích gia tăng khác là, IIRC, công việc của queryset nhân bản là tương đối đắt tiền, vì vậy bạn bỏ qua chi phí đó, trong khi đồng đồng thời làm cho mã sạch hơn. Quay trở lại câu hỏi của bạn, với mô hình này không có câu hỏi mà trường hợp ngoại lệ sẽ được nâng lên.

+0

Mẫu 'kwargs' có lẽ đẹp hơn. Ngoại lệ 'FieldError' (tên trường không chính xác) là một trường hợp hơi khác với' TypeError' (loại không chính xác được cung cấp cho bộ lọc). Điều này dường như xảy ra ngay lập tức, nhưng sau đó dường như xảy ra khi tra cứu thực sự được thực hiện. Tuy nhiên, tôi sẽ chấp nhận câu trả lời như tôi nghĩ rằng mô hình kwarg là đúng cách để đối phó với sự mơ hồ. –

Các vấn đề liên quan