Как построить запрос с несколькими отношениями manyTomany - Django
Я действительно не понимаю всех способов построения правильного запроса.
В коде, над которым я работаю, есть следующие модели. Я не могу изменить модели.
Модели/Последующие:
class FollowUp(BaseModel):
name = models.CharField(max_length=256)
questions = models.ManyToManyField(Question, blank=True, )
Модели/Обследование:
class Survey(BaseModel): name = models.CharField(max_length=256)
followup = models.ManyToManyField(
FollowUp, blank=True, help_text='questionnaires')
user = models.ManyToManyField(User, blank=True, through='SurveyStatus')
models/SurveyStatus:
class SurveyStatus(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
survey = models.ForeignKey(Survey, on_delete=models.CASCADE)
survey_status = models.CharField(max_length=10,
blank=True,
null=True,
choices=STATUS_SURVEY_CHOICES,
)
models/UserSurvey:
class UserSurvey(BaseModel):
user = models.ForeignKey(User, null=True, blank=True,
on_delete=models.DO_NOTHING)
followups = models.ManyToManyField(FollowUp, blank=True)
surveys = models.ManyToManyField(Survey, blank=True)
questions = models.ManyToManyField(Question, blank=True)
@classmethod
def create(cls, user_id):
user = User.objects.filter(pk=user_id).first()
cu_quest = cls(user=user)
cu_quest.save()
cu_quest._get_all_active_surveys
cu_quest._get_all_followups()
cu_quest._get_all_questions()
return cu_quest
def _get_all_questions(self):
[[self.questions.add(ques) for ques in qstnr.questions.all()]
for qstnr in self.followups.all()]
return
def _get_all_followups(self):
queryset = FollowUp.objects.filter(survey__user=self.user).filter(survey__user__surveystatus_survey_status='active')
# queryset = self._get_all_active_surveys()
[self.followups.add(quest) for quest in queryset]
return
@property
def _get_all_active_surveys(self):
queryset = Survey.objects.filter(user=self.user,
surveystatus__survey_status='active')
[self.surveys.add(quest) for quest in queryset]
return
Теперь мои вопросы:
- мое представление отправляет на создание модели UserSurvey, чтобы создать опросник. Мне нужно получить все вопросы последующих опросов со статусом survey_status = 'active' для пользователя (того, кто нажимает на кнопку)... Я пробовал несколько вещей:
- Я написал функцию _get_all_active_surveys() и там я получаю все опросы, которые имеют статус survey_status = 'active', а затем функция _get_all_followups() должна вызвать ее, чтобы использовать результат для создания собственного опроса. У меня есть проблема, говорящая мне, что .
список не является вызываемым объектом.
Я попытался написать непосредственно правильный запрос в _get_all_followups() с
queryset = FollowUp.objects.filter(survey__user=self.user).filter(survey__user__surveystatus_survey_status='active')
но мне не удается управлять всеми M2M отношениями. Я написал запрос выше, но проблема также
Связанное поле получило недействительный поиск: surveystatus_survey_status
я читал, что имя_родственника может помочь в построении обратного запроса, но я не понимаю, почему?
я впервые вижу return empty и то, что он должен возвращать выше. Почему такая нотация?
Если у вас есть четкие объяснения (больше, чем в документе), я буду очень признателен.
Спасибо
Достаточно много вопросов, чтобы ответить на них, я собрал их в список:
Ваш
_get_all_active_surveys
имеет декоратор@property
, но ни один из двух других методов его не имеет? На самом деле это не свойство, поэтому я бы удалил его.Вы используете list comprehension для добавления объектов queryset в поле m2m, это излишне, поскольку на самом деле вам не нужен объект list, и его можно переписать, например, как
.self.surveys.add(*queryset)
Вы можете использовать выражения фильтрации через запятую как
.filter(expression1, expression2)
, а не как.filter(expression1).filter(expression2)
.Вы пропустили знак подчеркивания в
surveystatus_survey_status
, он должен бытьsurveystatus__survey_status
.Связанное имя - это просто другой способ обратного доступа к отношениям, он не меняет того, как отношения существуют - по умолчанию Django будет делать что-то вроде
.ModelA.modelb_set.all()
- вы можете сделатьreverse_name="my_model_bs"
и затемModelA.my_model_bs.all()