从更新 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,就是PatientProfile模型的一个实例,即患者的记录。
更新
我包含确定网址的路线的主要文件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'^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<filename>(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')),
]
当我尝试访问所述模型的其余 API 的 url 时,我在控制台中收到以下消息:
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
在我的浏览器中:
如何序列化 ForeignKey 字段?我感谢您的帮助。
更新 2
我想尝试使用这篇文章中建议的嵌套关系,因为在我的模型的序列化中也有好处,在这种情况下是康复会话,该会话的患者字段,该会话的医生和该会话的治疗师,而不是他们各自的 url 将我带到他们的数据,出于可用性目的,我想阅读一些第三方应用程序,尽管我也认为值和键也可以通过 url 访问每个网址的json对吗?
好吧,现在,我有这样的:
我希望能够按如下方式组织我的数据:
{
"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'
} ,
],
}
那么根据文档,嵌套关系甚至自定义关系字段会起作用吗?
我已经按照嵌套关系指南以这种方式完成了它,现在仅适用于在康复会话的序列化中以嵌套方式显示患者数据的情况:
序列化模型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
这些是我的每个序列化模型的路由器,可以通过浏览器中的 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')),
]
输入网址http://localhost:8000/api/rehabilitation-session/时收到此消息
任何指导将不胜感激。:)
最后,在获取嵌套在我的 api 生成的 JSON 文档中的响应中的数据的情况下
django-rest-framework
,我选择了以下解决方案:我从头开始描述已经完成的工作,所以我将首先展示我最初定义的模型是什么,我如何序列化它们,如何生成视图或端点,最后如何
router's
建立路由 ()暴露他们类型URLConf
这些是我定义的模型
1.
PatientProfile
模型,定义userprofiles/models.py
2.model
MedicalProfile
定义在userprofiles/models.py
3.
TherapistProfile
定义在userprofiles/models.py
序列化
我以这种方式对这些模型进行了序列化:
userprofiles/serializers.py
Las vistas que exponen como
endpoints
los modelos serializados anteriores estan dadas enuserprofiles/views.py
de esta forma:Presento el modelo
RehabilitationSessions
localizado en medical_encounter_information/models.py el cual tiene tres llaves foráneas a los anteriores perfiles de usuariosPatientProfile
,MedicalProfile
yTherapistProfile
La serialización de los campos de la clase
RehabilitationSession
esta dada por la claseRehabilitationSessionSerializer
localizada enmedical_encounter_information/serializers.py
Es aqui en donde tenia mis dudas acerca de como realizar la serializacion y para lo cual estaba consultando un poco acerca de como se manejan las relaciones en Django REST Framework.
Encontré en la documentación como trabajar la serialización de manera anidada sin la necesidad de recurrir a clases extras del tipo Serializer Relationships.
La clave está en adicionar un campo llamado
depth
el cual permite de manera recursiva n niveles de profundidad (no se realmente hasta que número determinado de niveles) para poder serializar los subdocumentos JSON que tengamos, en este caso los que traía cadaForeignKey
de cada perfil de usuario necesitado en una sesión de rehabilitación (PatientProfile
,MedicalProfile
,TherapistProfile
)Aquí dice lo siguiente:
Entonces mi clase
RehabilitationSessionSerializer
queda asi:La vista
ViewSet
que expone esta serialización esta dada de esta forma enmedical_encounter_information/views.py
Mis rutas/routers en urls.py para el acceso a los modelos expuestos via rest framework son:
Es entonces que cuando consulto este API en mi navegador, el modelo
RehabilitationSession
que posee las tres claves foráneas a los modelosPatientProfile
,MedicalProfile
yTherapistProfile
; al ser serializado me queda desplegado de la siguiente manera con los documentos de los respectivos perfiles de usuario mencionados, anidados:Es así como pude tener una serialización de varios modelos en una misma vista por asi decirlo.
POr supuesto existen varias clases como las de Serialization relationships que permiten manejar las relaciones entre modelos en django rest framework acorde a lo que necesitemos, si es una url, si es un string, si es un campo de tipo slug o si es un campo tipo PrimaryKey o si es anidado como lo que necesitaba
我还发现了这个字段的嵌套或递归序列化示例,但这次它是相同的模型,有趣且非常必要,对于网络上一个非常常见的示例,即评论和对这些相同评论的响应。
我还要非常感谢您的想法和指导,它们对我找到解决方案很有用:D
使用嵌套关系
例如:
其中来自Album模型的曲目是Track模型的外键。
小心嵌套关系,它们对你的 API 来说是一个性能杀手,我在这篇文章中谈到它:http: //miguelgomez.io/python/optimizador-django-rest-framework/
另一方面,我会使用该类
MethodSerializers
来使序列化程序尽可能地自定义。一切顺利。