Джанго РЕСТ Фрамеворк Сериалисандо модели, у которых есть поля / связи ForeignKey и ManyToManyFields

Вызов этого вопроса ясный начиная с обновления 2, который является нынешним состоянием той же самой, возможно читать заверши, чтобы понимать Ваш контекст, если он желается

:)

У меня есть следующая модель, которую я хочу последовательно преобразовать, чтобы выставлять путь REST

class RehabilitationSession(models.Model):

    patient = models.ForeignKey('userprofiles.PatientProfile', null=True, blank=True,verbose_name='Paciente', related_name='patientprofile')

    slug = models.SlugField(max_length=100, blank=True)

    medical = models.ForeignKey('userprofiles.MedicalProfile', null=True, blank=True,
                            verbose_name='Médico tratante')
    therapist = models.ForeignKey('userprofiles.TherapistProfile', null=True, blank=True, verbose_name='Terapeuta')


    date_session_begin = models.DateTimeField(default=timezone.now(), verbose_name = 'Fecha de inicio')

    upper_extremity = MultiSelectField(
    max_length=255,
    choices=EXTREMITY_CHOICES,
    blank=False,
    verbose_name='Extremidad Superior'
)

    affected_segment = models.ManyToManyField(AffectedSegment,verbose_name='Segmento afectado')
    movement = ChainedManyToManyField(
    Movement, #Modelo encadenado
    chained_field = 'affected_segment',
    chained_model_field = 'corporal_segment_associated',
    verbose_name='Movimiento'
)

    metrics = models.ManyToManyField(Metric, blank=True, verbose_name='Métrica')
    date_session_end = models.DateTimeField(default=timezone.now(), verbose_name = 'Fecha de finalización')
    period = models.CharField(max_length=25,blank=True, verbose_name='Tiempo de duración de la sesión')

    class Meta:
        verbose_name = 'Sesiones de Rehabilitación'

    def __str__(self):
        return "%s" % self.patient

Чтобы последовательно преобразовывать поля, которые являются Foreingkey, я основываюсь на этой документации REST Framework.

Мой файл serializers.py этот:

from .models import RehabilitationSession
from rest_framework import serializers

class RehabilitationSessionSerializer(serializers.HyperlinkedModelSerializer):

patient = serializers.HyperlinkedIdentityField(view_name='patientprofile',)

class Meta:
    model = RehabilitationSession
    fields = ('url','id','patient',
              'date_session_begin','status','upper_extremity',

              'date_session_end', 'period','games','game_levels',
              'iterations','observations',)

Я использую HyperlinkedIdentityField благодаря тому, что моя модель последовательно преобразована HyperlinkedModelSerializer, но у меня не остается ясным, как я должен последовательно преобразовывать это согласно выборам, которые там встречаются. Говорится, что HyperlinkedIdentityField также смоги быть использованным на признаке объекта, и идея состоит в том, чтобы в виде моего api, когда модель останется последовательно преобразованной, мне показал url этого поля, которое является инстанцией модели Патьентпрофиле, а именно реестр пациента.

ОБНОВЛЕНИЕ

Мой главный файл urls.py где я включаю маршруты, чтобы определять urls, он:

from django.conf.urls import url, include #patterns
from django.contrib import admin

from .views import home, home_files

# REST Framework packages
from rest_framework import routers
from userprofiles.views import UserViewSet, GroupViewSet, PatientProfileViewSet
from medical_encounter_information.views import RehabilitationSessionViewSet

router = routers.DefaultRouter()
router.register(r'users', UserViewSet)
router.register(r'groups', GroupViewSet)
router.register(r'rehabilitation-session', RehabilitationSessionViewSet)
router.register(r'patientprofile', PatientProfileViewSet)

urlpatterns = [
    url(r'^admin/', admin.site.urls),

    url(r'^chaining/', include('smart_selects.urls')),

    url(r'^$', home, name='home'),

    url(r'^', include('userprofiles.urls')),
    #Call the userprofiles/urls.py

    url(r'^', include('medical_encounter_information.urls' )),
    #Call the medical_encounter_information/urls.py

    #  which is a regular expression that takes the desired urls and passes as an argument
    # the filename, i.e. robots.txt or humans.txt.
    url(r'^(?P(robots.txt)|(humans.txt))$',
        home_files, name='home-files'),

    #REST Frameworks url's
    # Wire up our API using automatic URL routing.
    # Additionally, we include login URLs for the browsable API.

    url(r'^api/', include(router.urls)),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),

]

Когда я пробую соглашаться на url моего api rest вышеупомянутой модели, я получаю следующее сообщение в моей консоли:

    File "/home/bgarcial/.virtualenvs/neurorehabilitation_projects_dev/lib/python3.4/site-packages/rest_framework/relations.py", line 355, in to_representation
    raise ImproperlyConfigured(msg % self.view_name)
django.core.exceptions.ImproperlyConfigured: Could not resolve URL for hyperlinked relationship using view name "patientprofile". You may have failed to include the related model in your API, or incorrectly configured the `lookup_field` attribute on this field.
[08/Mar/2016 16:05:45] "GET /api/rehabilitation-session/ HTTP/1.1" 500 165647

И в моем браузере это:

introducir la descripción de la imagen aquí

Как я могу последовательно преобразовывать поле ForeignKey? Я им благодарен за Вашу помощь.

ОБНОВЛЕНИЕ 2

Я захотел попытаться используя укрытые связи, как они предложили мне в этом post, ввиду того, что также было бы хорошим иметь в serialización моей модели в этом случае сеанс реабилитации, поля, свойственные пациенту этого сеанса, врача этого сеанса и терапевта этого сеанса и не Ваших соответствующих urls, которые я уношу в данные о самих них, для эффектов usabilidad, и представляю себе для чтения какого-то третьего приложения, хотя я представляю себе также то, что из-за url возможно соглашаться также на стоимость и ключи json каждого url: правда?

Ну, в этом моменте, у меня есть они так:

introducir la descripción de la imagen aquí

Мне хотелось бы мочь организовывать мои данные о следующем способе:

{
    "url": "http://localhost:8000/api/rehabilitation-session/9/",
    "id": 9,
    "patient": [
        {'id' : 1, 'full_name' : 'Andres Enfermizo',
         'diagnostic' : 'Diabetes', 'time_of_evolution' : '3 months'
        },      
    "medical": [
        {'id' : 1, 'full_name' : 'Doctor House',
         'specialty' : 'Epidemiologist', 'xperience' : '23 years'
        } ,
    ]
    "therapist": [
        {'id' : 1, 'full_name' : 'Christian',
         'specialty' : 'Legs', 'xperience' : '13 years'
        } ,
    ]
    "affected_segment": [
        {'id' : 1, 'affected_segment' : 'shoulder',
         'damage' : '30%', 'time_of_retrieve' : '10 months'
        } ,

    ],
} 

Тогда согласно документации: Nested Relationships или включенный Custom relational fields мог бы служить?

Я это сделал продолжая путеводитель для Нестед Релатионсипс этой формы, пока только для случая показывания укрытым способом данных пациента в serializacion сеанса реабилитации:

Последовательно преобразовывая модель PatientProfile:

class PatientProfileSerializer(serializers.ModelSerializer):
    class Meta:
        model = PatientProfile
        fields = ('url','id','user','full_name','time_of_evolution','diagnostic','marital_status','educational_level','partner_full_name','partner_relationship','partner_phone','partner_gender',
                  'care_provider',)

Вид PatientProfileViewset который выставит последовательно преобразованная модель

class PatientProfileViewSet(viewsets.ModelViewSet):
    queryset = PatientProfile.objects.all()
    serializer_class = PatientProfileSerializer

Сейчас я последовательно преобразовываю мою модель RehabilitationSession:

class RehabilitationSessionSerializer(serializers.ModelSerializer):
    patient = PatientProfileSerializer(many=True, read_only=True)
    class Meta:
        model = RehabilitationSession
        fields = ('url','id','patient',
                  #'affected_segment',
                  'date_session_begin','status','upper_extremity',

                  'date_session_end', 'period','games','game_levels',
                  'iterations','observations',)

Вид RehabilitationSessionViewSet который выставит последовательно преобразованная модель

class RehabilitationSessionViewSet(viewsets.ModelViewSet):
    queryset = RehabilitationSession.objects.all()
    serializer_class = RehabilitationSessionSerializer

И это мои router's для каждой модели, последовательно преобразованной, чтобы их соглашаться из-за url в браузере. Они находятся в моем главном urls.py:

from django.conf.urls import url, include #patterns
from django.contrib import admin

from .views import home, home_files

# REST Framework packages
from rest_framework import routers
from userprofiles.views import (UserViewSet, GroupViewSet, PatientProfileViewSet,)

from medical_encounter_information.views import (RehabilitationSessionViewSet,)


router = routers.DefaultRouter()
router.register(r'users', UserViewSet)
router.register(r'groups', GroupViewSet)
router.register(r'rehabilitation-session', RehabilitationSessionViewSet)
router.register(r'patientprofile', PatientProfileViewSet)

urlpatterns = [
    url(r'^admin/', admin.site.urls),

    ...
    url(r'^api/', include(router.urls)),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),

]

Я получаю это сообщение в момент ввождения url в компьютер http://localhost:8000/api/rehabilitation-session/

introducir la descripción de la imagen aquí

Любая ориентация будет высоко благодарной.:)

4
задан 09.03.2016, 00:01
3 ответа

В конце концов, для случая получения укрытым способом данных в моем ответе в (них) документировал (s) JSON's, которого мой api производит с django-rest-framework, я выбрал следующее решение:

Я снова возьму с начала, чтобы давать описание реализованного, с которого я начну из-за того, что покажу, которые являются моими определенными моделями оригинально, как serializé, как производятся совещания или endpoints и в конце концов, как устанавливаются маршруты (router's) чтобы выставлять тип URLConf

Это мои определенные модели

1.PatientProfile model, определенный userprofiles/models.py

class PatientProfile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    full_name = models.CharField(max_length=64)
    time_of_evolution = models.CharField(max_length=64, blank=False)
    diagnostic = models.TextField(blank=True)

    class Meta:
        verbose_name='Usuarios con perfil de pacientes'

    def __str__(self):
        return '%s %s' % (self.user.first_name, self.user.last_name)

2.MedicalProfile model определенный в userprofiles/models.py

class MedicalProfile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    full_name = models.CharField(max_length=64)
    specialty = models.CharField(max_length=64)

    class Meta:
        verbose_name='Usuarios con perfil de médicos'

    def __str__(self):
        return '%s %s' % (self.user.first_name, self.user.last_name)

3.TherapistProfile определенный в userprofiles/models.py

class TherapistProfile(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    full_name = models.CharField(max_length=64)
    specialty = models.CharField(max_length=64)

    class Meta:
        verbose_name='Usuarios con perfil de terapeutas'

    def __str__(self):
        return '%s %s' % (self.user.first_name, self.user.last_name)

Последовательно преобразовывая

У меня есть serialización этих моделей, таким образом, в userprofiles/serializers.py

from .models import PatientProfile, MedicalProfile, TherapistProfile
from rest_framework import serializers

class PatientProfileSerializer(serializers.HyperlinkedModelSerializer):
        class Meta:
            model = PatientProfile
            fields = ('url','id','user','full_name','time_of_evolution','diagnostic','marital_status','educational_level','partner_full_name','partner_relationship','partner_phone','partner_gender',
                      'care_provider',)

class MedicalProfileSerializer(serializers.HyperlinkedModelSerializer):
        class Meta:
            model = MedicalProfile
            fields = ('url','id','user','full_name','specialty')

class TherapistProfileSerializer(serializers.HyperlinkedModelSerializer):
        class Meta:
            model = TherapistProfile
            fields = ('url','id','user','full_name','specialty')

Совещания, которые они выставляют как endpoints предыдущие последовательно преобразованные модели даны в userprofiles/views.py таким образом:

from .models import PatientProfile, MedicalProfile, TherapistProfile
from rest_framework import viewsets
from .serializers import (PatientProfileSerializer, MedicalProfileSerializer, TherapistProfileSerializer,)

class PatientProfileViewSet(viewsets.ModelViewSet):
    queryset = PatientProfile.objects.all()
    serializer_class = PatientProfileSerializer

class MedicalProfileViewSet(viewsets.ModelViewSet):
    queryset = MedicalProfile.objects.all()
    serializer_class = MedicalProfileSerializer

class TherapistProfileViewSet(viewsets.ModelViewSet):
    queryset = TherapistProfile.objects.all()
    serializer_class = TherapistProfileSerializer

Я представляю модель RehabilitationSessions обнаруженный в medical_encounter_information/models.py, который имеет три чужеземных ключа по отношению к предыдущим профилям пользователей PatientProfile , MedicalProfile и TherapistProfile

from django.db import models
from smart_selects.db_fields import ChainedManyToManyField
from django.utils import timezone

from multiselectfield import MultiSelectField

class RehabilitationSession(models.Model):

    EXTREMITY_CHOICES = (
        ('Extremidad superior derecha', 'Superior Derecha'),
        ('Extremidad superior izquierda', 'Superior Izquierda'),
    )

    # Primer campo con ForeignKey relationship 
    patient = models.ForeignKey('userprofiles.PatientProfile',      null=True, blank=True,                                verbose_name='Paciente', related_name='patientprofile')

    # Segundo campo con ForeignKey relationship 
    medical = models.ForeignKey('userprofiles.MedicalProfile', null=True, blank=True,
                                verbose_name='Médico tratante', related_name='medicalprofile')

    # Tercer campo con ForeignKey relationship
    therapist = models.ForeignKey('userprofiles.TherapistProfile', null=True, blank=True,
                               verbose_name='Terapeuta')


    date_session_begin = models.DateTimeField(default=timezone.now(), verbose_name = 'Fecha de inicio')

    upper_extremity = MultiSelectField(
        max_length=255,
        choices=EXTREMITY_CHOICES,
        blank=False,
        verbose_name='Extremidad Superior'
    )

    affected_segment = models.ManyToManyField(AffectedSegment,verbose_name='Segmento afectado', related_name='affectedsegment')
    movement = ChainedManyToManyField(
        Movement, #Modelo encadenado
        chained_field = 'affected_segment',
        chained_model_field = 'corporal_segment_associated',
        verbose_name='Movimiento'
    )

    metrics = models.ManyToManyField(Metric, blank=True, verbose_name='Métrica')
    date_session_end = models.DateTimeField(default=timezone.now(), verbose_name = 'Fecha de finalización')
    period = models.CharField(max_length=25,blank=True, verbose_name='Tiempo de duración de la sesión')

    observations = models.TextField(blank=False, verbose_name='Observaciones')

    class Meta:
        verbose_name = 'Sesiones de Rehabilitación'

    def __str__(self):
        return "%s" % self.patient

serialización полей класса RehabilitationSession будь дана классом RehabilitationSessionSerializer обнаруженная в medical_encounter_information/serializers.py

Именно здесь у него были мои сомнения относительно, как реализовывать serializacion и для, что консультировалось немного относительно, как справляются связи в Джанго REST Framework.

Я нашел в документации, как работал serialización способа, укрытый без необходимости прибегать к дополнительным классам типа Сериалисер Релатионсипс.

Ключ состоит в том, чтобы добавлять так называемое поле depth который позволяет перекурсивным способом n уровни глубины (не действительно до тех пор, пока определенное число уровней), чтобы мочь последовательно преобразовывать субдокументы JSON, которые у нас есть, в этом случае те, которых он приносил каждый ForeignKey каждого профиля пользователя, нуждаемого в сеансе реабилитации (PatientProfile,MedicalProfile, TherapistProfile)

Здесь он говорит следующее:

The depth option should be set to an integer оцените that indicates the depth of relationships that should be traversed before reverting to в flat representation.

If you want to customize the way the serialization is подарил yoгll need to определи the field yourself.

Тогда мой класс RehabilitationSessionSerializer это остается так:

from .models import (RehabilitationSession,) 
from rest_framework import serializers
class RehabilitationSessionSerializer(serializers.ModelSerializer):

    class Meta:
        model = RehabilitationSession
        fields = ('url','id','patient','medical','therapist','affected_segment','movement','metrics','date_session_begin',
                  'status','slug', 'date_session_end','period','games','game_levels',
                  'iterations','observations',)
        #read_only_fields = ('patient','medical','therapist',)
        depth=1

Вид ViewSet который выставляет этот serialización, дан, таким образом, в medical_encounter_information/views.py

from .models import RehabilitationSession
from rest_framework import viewsets
from .serializers import (RehabilitationSessionSerializer,)

class RehabilitationSessionViewSet(viewsets.ModelViewSet):
    queryset = RehabilitationSession.objects.all()
    serializer_class = RehabilitationSessionSerializer

Мои rutas/routers в urls.py для доступа к выставленным моделям путь rest framework:

from rest_framework import routers
from userprofiles.views import PatientProfileViewSet,                 MedicalProfileViewSet, TherapistProfileViewSet

from medical_encounter_information.views import (RehabilitationSessionViewSet, AffectedSegmentViewSet, MovementViewSet,
                                                 MetricViewSet,)

# Routers provide an easy way of automatically determining the URL conf.
# Because we're using viewsets instead of views, we can automatically
# generate the URL conf for our API, by simply registering the viewsets with a router class.
router = routers.DefaultRouter()
router.register(r'rehabilitationsession', RehabilitationSessionViewSet)
router.register(r'patientprofile', PatientProfileViewSet)
router.register(r'medicalprofile', MedicalProfileViewSet)
router.register(r'therapistprofile', TherapistProfileViewSet)
router.register(r'affectedsegment', AffectedSegmentViewSet)
router.register(r'movement', MovementViewSet)
router.register(r'metrics', MetricViewSet)



urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^chaining/', include('smart_selects.urls')),
    url(r'^$', home, name='home'),

    url(r'^', include('userprofiles.urls')),
    #Call the userprofiles/urls.py

    url(r'^', include('medical_encounter_information.urls' )),
    #Call the medical_encounter_information/urls.py

    #REST Frameworks url's
    # Wire up our API using automatic URL routing.
    # Additionally, we include login URLs for the browsable API.

    url(r'^api/', include(router.urls)),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
    # Including default login and logout views for use with the browsable API.
    # That's optional, but useful if your API requires authentication and you want to use the browsable API.
    # Note that the URL path can be whatever you want, but you must include 'rest_framework.urls' with the 'rest_framework' namespace.
    # You may leave out the namespace in Django 1.9+, and REST framework will set it for you.
]

Именно тогда, когда я консультирую этот API в моем браузере, модели RehabilitationSession что обладает тремя чужеземными ключами в моделей PatientProfile, MedicalProfile и TherapistProfile; будучи последовательно преобразован он у меня остается развернутым следующего способа с документами соответствующих упомянутых, укрытых профилей пользователя:

introducir la descripción de la imagen aquí

Он также как и у меня мог быть serialización нескольких моделей в том же виде из-за того, что так это говорил.

Конечно существуют несколько классов как, например, классы Serialization relationships, который позволяет манипулировать связями между моделями в django rest framework, согласно которому нам было нужно, url ли это, string ли это, поле ли типа это slug, или если это поле тип PrimaryKey, или если он укрыт, как которое он нуждался

Также я нашел этот пример укрытого или перекурсивного serialización для полей, но в этом случае говорится о той же модели, интересной и очень необходимой, для очень общего примера в Вебе, который является Вебом комментариев и ответов в эти же самые комментарии.

Я хочу дать им также большое спасибо из-за идей и ориентаций, они я были полезными, чтобы искать мое решение :D

1
ответ дан 24.11.2019, 14:45

Используй Нестед Релатионс

Например:

class TrackSerializer(serializers.ModelSerializer):
    class Meta:
        model = Track
        fields = ('order', 'title', 'duration')

class AlbumSerializer(serializers.ModelSerializer):
    tracks = TrackSerializer(many=True, read_only=True)

    class Meta:
        model = Album
        fields = ('album_name', 'artist', 'tracks')

где tracks моделей Альбум это чужеземный ключ в модель Тракк.

1
ответ дан 24.11.2019, 14:45
  • 1
    prob и # 233; с Нестед Релатионсипс, поскольку ты рекомендовал меня, но у меня выходит эта ошибка File "/home/bgarcial/.virtualenvs/neurorehabilitation_projects_dev/lib/python3.4/site-packages/rest_framework/serializers.py" in to_representation 614. self.child.to_representation(item) for item in iterable Exception Type: TypeError at /api/rehabilitation-session/ Exception Value: 'PatientProfile' object is not iterable – bgarcial 08.03.2016, 21:40
  • 2
    Ты можешь помещать c и # 243; я говорю? – DJeanCar 08.03.2016, 22:47
  • 3
    я поместил секунду actualizaci и # 243; n вызов ** ACTUALIZACI и # 211; N 2 **, где я выдвигаю новую тревогу согласно serializaci и # 243; n данных об укрытом способе, который выдвигал DJeanCar aqu и # 237;. Любая помощь я им благодарен много.:) – bgarcial 09.03.2016, 00:04

Заботившийся с укрытыми связями, это kill выступление для твоего API, я говорю об этом в этом post: http://miguelgomez.io/python/optimizando-django-rest-framework/

С другой стороны, он использовал бы класс MethodSerializers чтобы создавать serializadores само персонализированный.

Приветствие.

1
ответ дан 24.11.2019, 14:45
  • 1
    МИГЕЛЬ, большое спасибо, интересный подход, и если, я принимаю, что transaccionalidad и conversi и # 243; n данных о формате, что har и # 225; DRF, вещь на уровне результата осложняется. Направлять и # 233; в счете твой recomendaci и # 243; n, чтобы улучшать мой API таким образом.: D – bgarcial 01.09.2016, 16:58