Сериализаторы Django REST — передача значения при создании нового объекта

#django #django-rest-framework #django-views #django-serializer

#django #django-rest-framework #django-представления #django-сериализатор

Вопрос:

У меня возникают проблемы с передачей аргумента при создании объекта с помощью сериализаторов Django REST.

models.py

 class Project(models.Model):
    name = models.CharField(max_length=200, unique=False)
    description = models.TextField()
...

class Hypothesis(models.Model):
    hypothesis = models.CharField(max_length=200, unique=False)
    project = models.ManyToManyField(Project)
    test_conducted = models.ManyToManyField('Interview', through='HypothesesFeedback') 
...
 

serializers.py

 class ProjectSerializer(serializers.ModelSerializer):

    class Meta:
        model = Project
        fields = ['name','description','company_name']

    def __init__(self, *args, **kwargs):
        super(ProjectSerializer, self).__init__(*args, **kwargs)

class HypothesisSerializer(serializers.ModelSerializer):

    class Meta:
        model = Hypothesis
        fields = ['hypothesis','area','details', 'project']

    def get_alternate_name(self, obj):
        project = self.context["project_id"]
 

views.py

 class ProjectRestCreate(LoginRequiredMixin, generics.ListCreateAPIView):
    queryset = Project.objects.all()
    serializer_class = ProjectSerializer

...

class HypothesisRestCreate(LoginRequiredMixin, generics.ListCreateAPIView):
    queryset = Hypothesis.objects.all()
    serializer_class = HypothesisSerializer

    def get_serializer_context(self):
        context = super().get_serializer_context()
        context["project_id"] = 8 #self.kwargs['project_id']
        return context
...
 

В настоящее время я не могу использовать идентификатор проекта по умолчанию при создании нового объекта для гипотезы класса. В приведенном выше примере я жестко кодирую значение только для целей тестирования, но мне нужно достичь того, что когда я создаю новую гипотезу, начиная с заданной страницы проекта, проект заполняется автоматически, а не пользователю приходится выбирать его вручную.

Используя Django, а не Django REST, я смог бы добиться этого, используя приведенный ниже код:

 class HypothesisCreate(generic.CreateView):
    model = Hypothesis
    form_class = HypothesisForm
    template_name = 'new_hypothesis.html'

    def form_valid(self, form):
        obj = form.save()
        project = form.data['project']
        p = Project.objects.filter(id=project)
        obj.project.set(p)

        return super(HypothesisCreate, self).form_valid(form)

    def get_context_data(self, **kwargs):
        context = super(HypothesisCreate, self).get_context_data(**kwargs)
        context['p_id'] = self.kwargs['project']

        return context

    def get_success_url(self, **kwargs):

        return reverse('project_detail', kwargs={'pk': self.kwargs['project']})
 

Есть идеи о том, как достичь того же с помощью сериализаторов Django REST?

EDIT #1

models.py

 class Project(models.Model):
    name = models.CharField(max_length=200, unique=False)
    description = models.TextField()
...

class Hypothesis(models.Model):
    hypothesis = models.CharField(max_length=200, unique=False)
    project = models.ForeignKey(Project, on_delete= models.CASCADE)
    test_conducted = models.ManyToManyField('Interview', through='HypothesesFeedback') 
...
 

using Django rather than Django REST, I achieve the defaulting of the project when creating a new hypothesis, using get_context_data:

 VIEW:

class HypothesisCreate(generic.CreateView):
    model = Hypothesis
    form_class = HypothesisForm
    template_name = 'new_hypothesis.html'

    def form_valid(self, form):
        obj = form.save()
        project = form.data['project']
        p = Project.objects.filter(id=project)
        obj.project.set(p)

        return super(HypothesisCreate, self).form_valid(form)

    def get_context_data(self, **kwargs):
        context = super(HypothesisCreate, self).get_context_data(**kwargs)
        context['p_id'] = self.kwargs['project']

        return context

    def get_success_url(self, **kwargs):

        return reverse('project_detail', kwargs={'pk': self.kwargs['project']})

FORM:

class HypothesisForm(ModelForm):

    class Meta:
        model = Hypothesis
        fields = ['hypothesis','area','details']

    def __init__(self, *args, **kwargs):
        
        super(HypothesisForm, self).__init__(*args, **kwargs)
        self.fields["project"] = forms.CharField(widget=forms.HiddenInput())
 

Я попытался сделать то же самое с сериализатором, но безуспешно.

 VIEW:

class HypothesisRestCreate(LoginRequiredMixin, generics.ListCreateAPIView):
    queryset = Hypothesis.objects.all()
    serializer_class = HypothesisSerializer

    def get_serializer_context(self):
        context = super().get_serializer_context()
        context["project_id"] = 8 #self.kwargs['project_id']
        return context



SERIALIZER:

class ProjectSerializer(serializers.ModelSerializer):

    class Meta:
        model = Project
        fields = ['name','description','company_name']

    def __init__(self, *args, **kwargs):
        super(ProjectSerializer, self).__init__(*args, **kwargs)

class HypothesisSerializer(serializers.ModelSerializer):

    class Meta:
        model = Hypothesis
        fields = ['hypothesis','area','details', 'project'] #

    def get_alternate_name(self, obj):
        project = self.context["project_id"]

 

есть идеи, что мне делать по-другому?

Комментарии:

1. почему ManyToManyField ? каждая гипотеза может иметь несколько проектов, но дозировать любую проектную работу по многим гипотезам?

2. для каждого проекта существует множество гипотез, которые необходимо проверить. На самом деле, предполагается, что каждая гипотеза связана только с одним проектом

3. затем используйте Foraignkey вместо этого.

4. вы правы, спасибо за подсказку! Знаете ли вы также, как передать идентификатор проекта в качестве параметра в сериализаторе, чтобы при создании новой гипотезы из проекта N значение N автоматически присваивалось системой, а не пользователю приходилось выбирать его вручную?

5. задайте этот конкретный вопрос подробно с измененным кодом и укажите вашу точную проблему. поместите его ссылку здесь.

Ответ №1:

Измените HypothesisRestCreate следующим образом

 class HypothesisRestCreate(LoginRequiredMixin, generics.ListCreateAPIView):
    queryset = Hypothesis.objects.all()
    serializer_class = HypothesisSerializer

    def create(self, request, *args, **kwargs):
        request.data['project'] = self.kwargs['project_id']
        return super(HypothesisRestCreate, self).create(request, *args, **kwargs)

    # def get_serializer_context(self): -- dont need for this purpose
 

и HypothesisSerializer как показано ниже

 class HypothesisSerializer(serializers.ModelSerializer):

    class Meta:
        model = Hypothesis
        fields = ['hypothesis','area','details', 'project']

    # def get_alternate_name(self, obj):  --dont need for this purpose