Я новичок в Django и практикую раздел «Модели» в Django, следуя официальному руководству. Я также создал собственный проект и пытаюсь применить аналогичные концепции.
Это мои модели.py;
from django.db import models
class Experience(models. Model):
o01_position = models.CharField(max_length=50)
o02_year_in = models.DateField(null=True)
o03_year_out = models.DateField(null=True)
o04_project = models.CharField(max_length=100)
o05_company = models.CharField(max_length=50)
o06_location = models.CharField(max_length=50)
def __str__(self):
return self.o01_position}
class Prjdesc(models.Model):
o00_key = models.ForeignKey(
Experience, on_delete=models.CASCADE)
o07_p_desc = models.CharField(max_length=250)
def __str__(self):
return self.o07_p_desc
class Jobdesc(models.Model):
o00_key = models.ForeignKey(Experience, on_delete=models.CASCADE)
o08_job_desc = models.CharField(max_length=250)
def __str__(self):
return self.o08_job_desc
Теперь, когда я запускаю команду ниже в оболочке Python/Django, она работает, как и ожидалось, с соответствующими данными.
>>> x = Experience.objects.get( pk = 2 )
>>> x
<Experience: Head Office Technical Office Manager>
Ниже два также работают, как и ожидалось:
>>> y = Prjdesc.objects.get( pk = 11 )
>>> y
<Prjdesc: Description 1>
>>> x.prjdesc_set.all()
<QuerySet [<Prjdesc: Description 1>, <Prjdesc: Description 2>]>
Однако это выражение ничего не возвращает, хотя должно возвращать соответствующую запись в классе опыта.
>>> y.experience
Traceback (most recent call last):
File "<console>", line 1, in <module>
AttributeError: 'Prjdesc' object has no attribute 'experience'
Не могли бы вы сказать мне, что мне здесь не хватает?
@inquirer Я понял это отлично, и то, что вы написали, также работает, однако я до сих пор не понимаю, как это: Django Tutorial работает. (строка >>> c.question внизу.)
Я также пытаюсь воспроизвести это; c = x.prjdesc_set.create(o07_p_desc='Description 5')
и потом c.experience
но не работает. Спасибо.
@BlueHawk77 Что возвращает c.experience
? Он должен возвращать o01_position
, как вы возвращаетесь в методе __str__()
в модели Experience
.
Как ни странно, он возвращает это; Traceback (most recent call last): File "<console>", line 1, in <module> AttributeError: 'Prjdesc' object has no attribute 'experience'
Это поведение не соответствует поведению, описанному здесь: Django Tutorial (строка >>> c.question внизу.) Я должен что-то упустить
Я только что попробовал, и мой вышеприведенный подход (тот, что в вопросе) y = Prjdesc.objects.get( pk = 11 )
и y.experience
в наборе учебника, и он сработал для модели в учебнике. Я попробовал Choice.objects.get( pk = 1 ).question
и получил ожидаемый результат <Question: What's new?>
Не понимаю, почему здесь не работает.
Если вы обратите внимание:
c = q.choice_set.create(choice_text='Just hacking again', votes=0)
есть вызов через _set. Но не совсем:
q = Question.objects.get(pk=1)
с последующим:
q.choice# which will throw the same error
Используя первичную модель, вы можете получить связанные с ней данные из вторичной модели. Для этого в первичной модели по умолчанию создается специальное свойство (объект) с именем вторичный набор_моделей. В вашем случае, например:
x = Experience.objects.get(pk=1)
x.prjdesc_set.all()
То есть мы получаем все значения вторичной модели с pk=1 первичной (доступ один ко многим).
Если вам нужно получить значение первичной модели из вторичной модели, то как уже было сказано:
Prjdesc.objects.get(id=1).o00_key.o01_position
В данном случае используется get, то есть значение должно быть единицей, если ожидается больше, то следует применять filter.
Я также хотел бы поблагодарить вас за вашу помощь. Как я написал ниже ответа Дубея ниже, в официальной документации было двойное наименование, которое меня смутило. Хороших выходных !
Как вы упомянули в одном из комментариев выше:
Как ни странно, он возвращает это; Трассировка (последний последний вызов): файл «», строка 1, в AttributeError: объект «Prjdesc» не имеет атрибута «опыт».
Вам просто нужно написать c.o00_key
, а не c.experience
, вы перепутали с официальными документами, они дают свое имя поля также как experince
.
Как правило, ForeignKey создается с использованием имени модели в smallcase
при определении поля, а related_name
по умолчанию задает имя модели в качестве префикса и _set
в качестве суффикса, поэтому в вашем случае это будет prjdesc_set
, или вы можете переопределить его, используя ForeignKey.related_name в поле.
С вашими текущими моделями используйте это:
>>> x = Experience.objects.get(pk=2)
>>> x
<Experience: Head Office Technical Office Manager>
>>> c = x.prjdesc_set.create(o07_p_desc='Description 5')
>>> c
<Prjdesc: Description 5>
>>> c.o00_key
>>> c
<Experience: Head Office Technical Office manager>
Примечание. Также лучше использовать f stings в методе __str__(), поэтому в ваших моделях.py:
class Experience(models.Model):
...
...
def __str__(self):
return f"{self.o01_position}"
class Prjdesc(models.Model):
...
...
def __str__(self):
return f"{self.o07_p_desc}"
class Jobdesc(models.Model):
...
...
def __str__(self):
return f"{self.o08_job_desc}"
Большое спасибо за ваше время и ваш ответ. Как вы сказали, меня смутила официальная модель документации, поскольку они назвали таблицу и один столбец одинаковыми. На самом деле это плохая практика, которую им следует стараться не делать, поскольку новичок вроде меня может легко спутать одно с другим. Теперь все ясно. Хорошего дня !!!
@BlueHawk77 BlueHawk77 Да, в справочнике по API документов Django сначала требовалось базовое знание ключевых понятий (я имею в виду темы), которые также упоминаются в документах как Как организована документация?
@BlueHawk77 не только тебя смутили одинаковые имена.
@inquirer Вы имеете в виду, что вы тоже были? ;) Сначала я тоже был, см. комментарий под вопросом.
@SunderamDubey в начале исследования я тоже не мог понять в чем дело).
@inquirer Вы говорите о начале, но я был около 2 дней назад, но потом я вдруг вспомнил, посмотрев на related_name
.
доступ к первичной модели осуществляется через ассоциированное поле из первичной модели: Prjdesc.objects.get(id=1).o00_key.o01_position