Django / Как получить первичный ключ из определенного поля?
Models.py
class scenes(models.Model):
name = models.CharField('Event name', max_length=120)
record_date = models.DateTimeField('Event date')
Допустим, я записал сцену с name="world"
В файле views.py, как я могу запросить pk из поля name?
from .models import scenes
scene = scenes.objects.get('what should I put here to get the pk associated with name World ?')
Когда я вошел :
scene = scenes.objects.get(name='world').pk
Я получил ошибку :
UnboundLocalError: локальная переменная 'scenes' ссылается перед присвоением
Простым способом было бы просто:
# views.py
from .models import scenes
scene = scenes.objects.get(name="world")
scene_id = scene.pk # This contains the pk of the scene object
Django попытается получить уникальный объект с "world" в качестве значения для поля name. С вашим текущим кодом это имеет проблему:
- Ваше поле
nameне являетсяunique, поэтому ваша БД может содержать различныеscenesобъекты с"world"значением для поляname. Это приведет к проблемам при вызовеget. Чтобы решить эту проблему, можно добавитьunique=Trueпри определении поля:
# models.py
class scenes(models.Model):
name = models.CharField('Event name', max_length=120, unique=True)
record_date = models.DateTimeField('Event date')
Это гарантирует, что ваша БД не будет содержать объектов с одинаковыми именами.
Обратите внимание, что если не существует объекта со значением name, равным "world", вы также получите ошибку. В зависимости от контекста, в котором вы это используете, вам следует рассмотреть get_object_or_404 или get_or_create
смотрите здесь: Ярлык поиска pk.
В документации django заявлено, что первичные ключи имеют эквивалент, в данном случае это pk. Поэтому если вы объявили первичный ключ в вашей модели (допустим, мы назвали его code), вы можете получить к нему доступ как code или pk. Это полезно как для применения фильтров (как в ссылке выше), так и для получения конкретного атрибута.
Теперь ваш вопрос в том, как получить связанный первичный ключ из имени события, я покажу вам ниже несколько решений с последствиями того, как вы объявили модель.
A. Использование scenes.objects.get():
Если вы используете этот метод, вы должны принять во внимание две вещи:
- Если поиск существует, он не завершается, возникает
Model.DoesNotExistисключение. - Что поиск возвращает только 1 объект, если найдено более одного объекта, то возникает
Model.MultipleObjectsReturnedисключение:
посмотрите Queryset get() method
Итак, если мы проигнорируем второе, то блок кода будет выглядеть следующим образом
# we have 1 object with the name `world`
try:
scene = scenes.objects.get(name="world")
scene_pk = scene.pk
except scenes.DoesNotExist:
print("The Scene does not Exists")
но второй вы должны использовать Queryset filter() method с другими методами, такими как first() или last()
Поэтому я рекомендую вам переделать модель следующим образом:
class scenes(models.Model):
name = models.CharField('Event name',unique=True, max_length=120)
record_date = models.DateTimeField('Event date')
или использовать SlugField как pk или уникальное поле, если вы не хотите менять id как первичный ключ
class scenes(models.Model):
name = models.CharField('Event name', max_length=120)
slug = models.SlugField(unique=True)
record_date = models.DateTimeField('Event date')
slugfield идеально подходит, если вы хотите использовать название мероприятия в URL.