В DRF, как я могу сериализовать данные, полученные по рекламному маршруту? - PullRequest
0 голосов
/ 17 июня 2019

У меня есть 3 модели ниже:

#Appointment
class Appointment(models.Model):
    doctor = models.ForeignKey(
        Doctor,
        on_delete=models.CASCADE,
        related_name='doctor_appointment')
    patient = models.ForeignKey(
        Patient,
        on_delete=models.CASCADE,
        related_name='patient_appointment')
    scheduled = models.DateTimeField(auto_now_add=True)

# Doctor
class Doctor(models.Model):
    user_id = models.TextField(unique=True)
    first_name = models.CharField(max_length=100, blank=False)
    last_name = models.CharField(max_length=100, blank=False)

# Patients
class Patient(models.Model):
    user_id = models.TextField(unique=True)
    first_name = models.CharField(max_length=100, blank=False)
    last_name = models.CharField(max_length=100, blank=False)

и их 3 соответствующих сериализатора:

    # Patient Serializer
class PatientSerializer(serializers.ModelSerializer):
    # contract_number = serializers.PrimaryKeyRelatedField(queryset=Contract.objects.all())

    class Meta:
        model = Patient
        fields = '__all__'

    # Doctor Serializer
class DoctorSerializer(serializers.ModelSerializer):
    tariff = serializers.DecimalField(
        source='DoctorTariff.amount',
        max_digits=6,
        decimal_places=2)

    class Meta:
        model = Doctor
        fields = '__all__'



   # Appointment Serializer
class AppointmentSerializer(serializers.ModelSerializer):
    doctor = serializers.CharField(source='Doctor.user_id')
    patient = serializers.CharField(source='Patient.user_id')
    service_provided = serializers.CharField(source='ServiceProvided.service')
    upcoming = serializers.SerializerMethodField()

    class Meta:
        model = Appointment
        fields = '__all__'

Для моей модели Appointment я указал специальный маршрут, который будет показывать предстоящую встречу:

class AppointmentViewSet(viewsets.ModelViewSet):
    queryset = Appointment.objects.all()
    serializer_class = AppointmentSerializer

    @action(detail=False, url_path='upcoming/(?P<user_id>[^/.]+)')
    def upcoming_appointment(self, request, user_id=None):
        try:
            queryset = Appointment.objects.filter(patient__user_id=user_id).\
                select_related('patient', 'doctor').values('scheduled', doctor_first_name=F('doctor__first_name'),
                                                           doctor_last_name=F('doctor__last_name'),
                                                           specialty=F('doctor__specialty'),
                                                           doctor_address=F('doctor__address'))

            #serializer = AppointmentSerializer(queryset, many=True)
            # if serializer.is_valid():

        except Appointment.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)

        # If I use serializer.data instead of queryset I get an error
        return Response(queryset, status=status.HTTP_200_OK) 

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

Вопрос № 1 : Так как при обращении к этой конечной точке я вижу правильный вывод (в формате JSON), мне все еще нужно использовать сериализатор?

Вопрос № 2 : Когда я пытаюсь сериализовать это, используя serializer = AppointmentSerializer(queryset, many=True) и return Response(serializer.data, status=status.HTTP_200_OK), я получаю ошибку ниже:

AttributeError: Получил AttributeError при попытке получить значение для поля doctor на сериализаторе AppointmentSerializer. Поле сериализатора может иметь неправильное имя и не соответствовать ни одному атрибуту или ключу в экземпляре QuerySet. Исходный текст исключения был: объект «QuerySet» не имеет атрибута «Доктор»

Как я могу сериализовать этот пользовательский набор запросов?

1 Ответ

0 голосов
/ 17 июня 2019

Здесь куча проблем.

Во-первых, как я уже говорил вам, вы не должны использовать values.Передайте набор запросов Appointment напрямую в сериализатор.

И, во-вторых, имена ваших источников неверны в полях сериализатора.Оба поля doctor и patient определены в нижнем регистре, поэтому это имя следует использовать в атрибуте источника.

Итак:

class AppointmentSerializer(serializers.ModelSerializer):
    doctor = serializers.CharField(source='doctor.user_id')
    patient = serializers.CharField(source='patient.user_id')
    ...

def upcoming_appointment(self, request, user_id=None):
    try:
        queryset = Appointment.objects.filter(patient__user_id=user_id).\
            select_related('patient', 'doctor')
        serializer = AppointmentSerializer(queryset, many=True)
        ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...