Câu trả lời:
Không có cách 'xây dựng' để làm điều này. Django sẽ tăng ngoại lệ DoesNotExist mỗi lần. Cách thành ngữ để xử lý vấn đề này trong python là bọc nó trong một thử bắt:
try:
go = SomeModel.objects.get(foo='bar')
except SomeModel.DoesNotExist:
go = None
Những gì tôi đã làm là tạo safe_get
các mô hình lớp con. Quản lý, tạo một mã giống như ở trên và sử dụng trình quản lý đó cho các mô hình của tôi. Bằng cách đó bạn có thể viết : SomeModel.objects.safe_get(foo='bar')
.
SomeModel.objects.filter(foo='bar').first()
điều này trả về trận đấu đầu tiên hoặc Không có gì. Sẽ không thất bại nếu có một vài trường hợp nhưqueryset.get()
filter().first()
tôi nghĩ rằng ngoại lệ là cách để đi.
Vì django 1.6, bạn có thể sử dụng phương thức First () như vậy:
Content.objects.filter(name="baby").first()
get()
đưa ra mộtDoesNotExist
ngoại lệ nếu không tìm thấy một đối tượng cho các tham số đã cho. Ngoại lệ này cũng là một thuộc tính của lớp mô hình. CácDoesNotExist
kế thừa ngoại lệ từdjango.core.exceptions.ObjectDoesNotExist
Bạn có thể bắt ngoại lệ và chỉ định None
đi.
from django.core.exceptions import ObjectDoesNotExist
try:
go = Content.objects.get(name="baby")
except ObjectDoesNotExist:
go = None
Bạn có thể tạo một chức năng chung cho việc này.
def get_or_none(classmodel, **kwargs):
try:
return classmodel.objects.get(**kwargs)
except classmodel.DoesNotExist:
return None
Sử dụng như thế này:
go = get_or_none(Content,name="baby")
go sẽ là Không nếu không có mục nào trùng khớp sẽ trả về mục Nội dung.
Lưu ý: Nó sẽ tăng ngoại lệ ManyObjectsReturned nếu có nhiều mục nhập được trả về cho name = "baby"
Bạn có thể làm theo cách này:
go = Content.objects.filter(name="baby").first()
Bây giờ biến đi có thể là đối tượng bạn muốn hoặc Không có
Tham chiếu: https://docs.djangoproject.com/en/1.8/ref/models/querysets/#django.db.models.query.QuerySet.first
Để làm cho mọi thứ dễ dàng hơn, đây là một đoạn mã tôi đã viết, dựa trên các đầu vào từ các câu trả lời tuyệt vời ở đây:
class MyManager(models.Manager):
def get_or_none(self, **kwargs):
try:
return self.get(**kwargs)
except ObjectDoesNotExist:
return None
Và sau đó trong mô hình của bạn:
class MyModel(models.Model):
objects = MyManager()
Đó là nó. Bây giờ bạn có MyModel.objects.get () cũng như MyModel.objetcs.get_or_none ()
bạn có thể sử dụng exists
với bộ lọc:
Content.objects.filter(name="baby").exists()
#returns False or True depending on if there is anything in the QS
chỉ là một thay thế cho nếu bạn chỉ muốn biết nếu nó tồn tại
exists()
sẽ được sử dụng với if
mệnh đề trước khi tìm nạp đối tượng do đó gây ra một cú đúp cho db. Tôi vẫn sẽ giữ bình luận xung quanh trong trường hợp nó giúp được người khác.
Xử lý các trường hợp ngoại lệ tại các điểm khác nhau trong chế độ xem của bạn có thể thực sự cồng kềnh..Những gì về việc xác định Trình quản lý mô hình tùy chỉnh, trong tệp mô hình, như,
class ContentManager(model.Manager):
def get_nicely(self, **kwargs):
try:
return self.get(kwargs)
except(KeyError, Content.DoesNotExist):
return None
và sau đó đưa nó vào lớp Mô hình nội dung
class Content(model.Model):
...
objects = ContentManager()
Bằng cách này, nó có thể dễ dàng được xử lý trong các khung nhìn tức là
post = Content.objects.get_nicely(pk = 1)
if post:
# Do something
else:
# This post doesn't exist
return self.get(**kwargs)
để làm cho nó hoạt động với tôi. Không nói bất cứ điều gì sai với câu trả lời, chỉ là một mẹo cho bất cứ ai cố gắng sử dụng nó với các phiên bản mới hơn (hoặc với bất cứ điều gì khác khiến nó không hoạt động cho tôi).
Đây là một trong những chức năng gây phiền nhiễu mà bạn có thể không muốn thực hiện lại:
from annoying.functions import get_object_or_None
#...
user = get_object_or_None(Content, name="baby")
get_object_or_None
nhưng thấy rằng nó vẫn tăng MultipleObjectsReturned
nếu có nhiều hơn một đối tượng. Vì vậy, người dùng có thể xem xét xung quanh với một try-except
(mà chính chức năng này đã có try-except
).
Tôi nghĩ rằng nó không phải là ý tưởng tồi để sử dụng get_object_or_404()
from django.shortcuts import get_object_or_404
def my_view(request):
my_object = get_object_or_404(MyModel, pk=1)
Ví dụ này tương đương với:
from django.http import Http404
def my_view(request):
try:
my_object = MyModel.objects.get(pk=1)
except MyModel.DoesNotExist:
raise Http404("No MyModel matches the given query.")
Bạn có thể đọc thêm về get_object_or_404 () trong tài liệu trực tuyến django.
Từ django 1.7 trở đi bạn có thể làm như sau:
class MyQuerySet(models.QuerySet):
def get_or_none(self, **kwargs):
try:
return self.get(**kwargs)
except self.model.DoesNotExist:
return None
class MyBaseModel(models.Model):
objects = MyQuerySet.as_manager()
class MyModel(MyBaseModel):
...
class AnotherMyModel(MyBaseModel):
...
Ưu điểm của "MyQuerySet.as_manager ()" là cả hai điều sau đây sẽ hoạt động:
MyModel.objects.filter(...).get_or_none()
MyModel.objects.get_or_none()
Đây là một biến thể của hàm trợ giúp cho phép bạn tùy ý vượt qua trong một QuerySet
trường hợp, trong trường hợp bạn muốn lấy đối tượng duy nhất (nếu có) từ một bộ truy vấn khác với bộ truy vấn all
đối tượng của mô hình (ví dụ: từ một tập hợp con của các mục con thuộc về một ví dụ cha mẹ):
def get_unique_or_none(model, queryset=None, **kwargs):
"""
Performs the query on the specified `queryset`
(defaulting to the `all` queryset of the `model`'s default manager)
and returns the unique object matching the given
keyword arguments. Returns `None` if no match is found.
Throws a `model.MultipleObjectsReturned` exception
if more than one match is found.
"""
if queryset is None:
queryset = model.objects.all()
try:
return queryset.get(**kwargs)
except model.DoesNotExist:
return None
Điều này có thể được sử dụng theo hai cách, ví dụ:
obj = get_unique_or_none(Model, **kwargs)
như đã thảo luậnobj = get_unique_or_none(Model, parent.children, **kwargs)
Không có ngoại lệ:
if SomeModel.objects.filter(foo='bar').exists():
x = SomeModel.objects.get(foo='bar')
else:
x = None
Sử dụng một ngoại lệ:
try:
x = SomeModel.objects.get(foo='bar')
except SomeModel.DoesNotExist:
x = None
Có một chút tranh cãi về việc khi nào nên sử dụng một ngoại lệ trong python. Một mặt, "xin tha thứ dễ hơn là xin phép". Mặc dù tôi đồng ý với điều này, tôi tin rằng một ngoại lệ nên vẫn còn, ngoại lệ, và "trường hợp lý tưởng" sẽ chạy mà không cần nhấn một.
Chúng ta có thể sử dụng ngoại lệ dựng sẵn Django gắn liền với các mô hình có tên là .DoesNotExist
. Vì vậy, chúng tôi không phải nhập ObjectDoesNotExist
ngoại lệ.
Thay vì làm:
from django.core.exceptions import ObjectDoesNotExist
try:
content = Content.objects.get(name="baby")
except ObjectDoesNotExist:
content = None
Chung ta co thể lam được việc nay:
try:
content = Content.objects.get(name="baby")
except Content.DoesNotExist:
content = None
Đây là một bản sao từ get_object_or_404 của Django ngoại trừ phương thức trả về Không có. Điều này cực kỳ hữu ích khi chúng ta phải sử dụng only()
truy vấn để chỉ truy xuất một số trường nhất định. Phương pháp này có thể chấp nhận một mô hình hoặc một bộ truy vấn.
from django.shortcuts import _get_queryset
def get_object_or_none(klass, *args, **kwargs):
"""
Use get() to return an object, or return None if object
does not exist.
klass may be a Model, Manager, or QuerySet object. All other passed
arguments and keyword arguments are used in the get() query.
Like with QuerySet.get(), MultipleObjectsReturned is raised if more than
one object is found.
"""
queryset = _get_queryset(klass)
if not hasattr(queryset, 'get'):
klass__name = klass.__name__ if isinstance(klass, type) else klass.__class__.__name__
raise ValueError(
"First argument to get_object_or_none() must be a Model, Manager, "
"or QuerySet, not '%s'." % klass__name
)
try:
return queryset.get(*args, **kwargs)
except queryset.model.DoesNotExist:
return None
Có lẽ tốt hơn là bạn sử dụng:
User.objects.filter(username=admin_username).exists()