Как написать запрос Django ORM для обратной связи в отношении один-ко-многим? - PullRequest
0 голосов
/ 21 января 2019

Я использую Django и Python 3.7. У меня есть следующие две модели в моем файле models.py ...

class Article(models.Model):
    created_on = models.DateTimeField(default=datetime.now)
...


class ArticleStat(models.Model):
    article = models.ForeignKey(Article, on_delete=models.CASCADE, )
    elapsed_time_in_seconds = models.IntegerField(default=0, null=False)

Я хотел бы написать запрос Django ORM, в котором я выбираю статьи, которые имеют статистику не менее 5 минут (300 секунд). Однако я не знаю, как ссылаться на объект ArticleStat из объекта Article. Неудивительно, что это

Article.objects.filter(articlestat.elapsed_time_in_seconds.lte==300)

производит

NameError: name 'articlestat' is not defined

ошибка.

Редактировать: В ответ я изменил свою модель ArticleStat на

class ArticleStat(models.Model):
    article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='articlestats')

и затем я запустил приведенный ниже запрос, получив сообщение об ошибке

Article.objects.filter(articlestat_set__elapsed_time_in_seconds__lte==300)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'articlestat_set__elapsed_time_in_seconds__lte' is not defined

Думал, что, возможно, был экземпляр с множественным числом, поэтому я попробовал "s", но получил ошибку ..

Article.objects.filter(articlestats_set__elapsed_time_in_seconds__lte==300)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'articlestats_set__elapsed_time_in_seconds__lte' is not defined

Ответы [ 2 ]

0 голосов
/ 21 января 2019

Основная проблема здесь - NameError для articlestat, поэтому я рассмотрю ее в первую очередь.

Как объяснено в документации django ваше имя обратной связи по умолчанию определено как FOO_set, что в вашем случае означает articlestat_set.

Если модель имеет ForeignKey, экземпляры модели с внешним ключом будет иметь доступ к Manager, который возвращает все экземпляры первая модель. По умолчанию этот Manager называется FOO_set , где FOO - название модели источника в нижнем регистре.

Если вы предпочитаете другое имя, вы можете сделать это, указав related_name в своем определении ForeignKey, например,

class ArticleStat(models.Model):
    article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='articlestats')
    elapsed_time_in_seconds = models.IntegerField(default=0, null=False)

Второй вопрос - как правильно следовать отношениям, который довольно подробно объясняется здесь , поэтому я не буду подробно останавливаться на этом в этом ответе. Суть в том, что вместо оператора . вы хотите использовать __ (двойное подчеркивание). То же самое относится к field lookups, который необходим для сравнения в этом запросе.

После устранения этих проблем ваш запрос должен выглядеть следующим образом:

Article.objects.filter(articlestat_set__elapsed_time_in_seconds__lte=300)

или с пользовательским related_name например related_name='articlestats'

Article.objects.filter(articlestats__elapsed_time_in_seconds__lte=300)
0 голосов
/ 21 января 2019

Попробуйте что-то вроде:

Article.objects.filter(articlestat__elapsed_time_in_seconds__lte=300)

Обратите внимание, что запросы Django работают как ключевые слова (kwargs) (т. Е. Вы можете только передать filter_string=something в функцию фильтра).

Вы передавали выражение, которое python не смог разрешить (т.е. python попытался найти имя переменной articlestat и затем получить ее атрибут elapsed_time_in_seconds и т. Д.)

Взгляните на это подробнее https://docs.djangoproject.com/en/2.1/topics/db/queries/#retrieving-specific-objects-with-filters

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...