Запрашивайте пользователей Django методом get_username
Я пытаюсь получить объект Django User с определенным именем пользователя. Очевидный способ сделать это такой:
from django.contrib.auth.models import User
bob = User.objects.get(username="Bob")
Но я заметил, что у пользовательских объектов есть метод get_username(), который утверждает, что
вам следует использовать этот метод вместо прямой ссылки на атрибут username.
Это заставляет меня опасаться использования атрибута в запросах.
Есть ли способ запрашивать пользовательские объекты с помощью этого метода, а не с помощью атрибута username? Я ищу более элегантную версию, ориентированную на набор запросов:
bob = [u for u in User.objects.all() if u.get_username() == "Bob"][0]
если такое вообще существует.
Если вы хотите получить экземпляр пользователя из базы данных, предпочтительным способом является использование метода get или get_object_or_404.
User.objects.get(имя пользователя="Bob")
B
Эти два метода служат разным целям: метод get_username() возвращает имя пользователя, который в данный момент вошел в систему. Не следует использовать его для получения записей о случайном пользователе. Также обратите внимание, что этот метод возвращает запись, используемую в качестве USERNAME_FIELD, которая может быть именем пользователя, адресом электронной почты или любым другим уникальным идентификатором, поскольку пользовательская модель Django может быть заменена.
Метод get(), с другой стороны, извлекает запрашиваемый экземпляр модели. Вы можете использовать его, если хотите получить экземпляр пользователя, используя имя пользователя. Убедитесь, что обработано исключение DoesNotExist, если объект не существует, и возвращено несколько объектов, если ваше поле username не уникально:
попробуйте:
User.objects.get(username="Bob")
кроме User.Не существует:
...
кроме нескольких возвращенных объектов:
...
Или вы также можете использовать метод get_object_or_404
Вы не можете использовать get_username() в наборе запросов - это просто метод Python, а не поле базы данных.
Для поиска вы должны выполнить запрос по фактическому имени поля:
bob = User.objects.get(username="Bob")
Если вам действительно нужен подход, основанный на методе, вы можете определить свой собственный метод моделирования или метод менеджера, например:
class CustomUserManager(models.Manager):
def get_by_username(self, username):
return self.get(username=username)
class User(AbstractUser):
objects = CustomUserManager()
тогда вы можете использовать вот так:
bob = User.objects.get_by_username("Bob")
Это заставляет меня опасаться использования атрибута в запросах.
На самом деле вы не используете атрибуты в запросе. Вы используете только атрибуты из класса, которые являются подклассами django.db.models.fields.Field. Таким образом, вы не можете выполнять фильтрацию с помощью произвольного атрибута или метода.
К счастью, если мы посмотрим на исходный код .get_username(…) [GitHub], там будет написано:
def get_username(self): """Return the username for this User.""" return getattr(self, self.USERNAME_FIELD)
это используется, например, если вы хотите использовать поле email вместо username, или при создании пользовательской модели пользователя с другим полем.
Затем мы можем задать запрос с помощью:
from django.contrib.auth.models import User
bob = User.objects.get(**{User.USERNAME_FIELD: 'Bob'})