From 928bea8121391cabde673a31de302825cc80cf12 Mon Sep 17 00:00:00 2001 From: Diane Trout Date: Tue, 12 May 2015 12:14:05 -0700 Subject: [PATCH] initial attempt to use django restframework --- experiments/serializers.py | 61 ++++++++++++++ .../experiments/flowcell_detail.html | 4 +- .../experiments/flowcell_header.html | 24 +++--- experiments/urls.py | 36 +++++--- experiments/views.py | 84 +++++++++++++++++-- htsworkflow/settings/base.py | 7 ++ .../templates/samples/species_list.html | 30 +++++++ htsworkflow/urls.py | 33 ++++---- samples/serializers.py | 30 +++++++ samples/urls.py | 31 ++++--- samples/views.py | 80 ++++++++++++++---- 11 files changed, 347 insertions(+), 73 deletions(-) create mode 100644 experiments/serializers.py create mode 100644 htsworkflow/templates/samples/species_list.html create mode 100644 samples/serializers.py diff --git a/experiments/serializers.py b/experiments/serializers.py new file mode 100644 index 0000000..6166640 --- /dev/null +++ b/experiments/serializers.py @@ -0,0 +1,61 @@ +from rest_framework import serializers + +from .models import ( + ClusterStation, + Lane, + FlowCell, + Sequencer, +) + + +class ClusterStationSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = ClusterStation + + +class LaneSerializer(serializers.HyperlinkedModelSerializer): + flowcell = serializers.HyperlinkedRelatedField( + lookup_field='flowcell_id', + view_name='flowcell-detail') + + library = serializers.HyperlinkedRelatedField( + view_name='library-detail') + + class Meta: + model = Lane + fields = ( + 'url', + 'lane_number', + 'library', + 'pM', + 'cluster_estimate', + 'status', + 'comment') + + +class FlowCellSerializer(serializers.HyperlinkedModelSerializer): + url = serializers.HyperlinkedIdentityField( + lookup_field='flowcell_id', + view_name='flowcell-detail') + + class Meta: + model = FlowCell + depth = 2 + fields = ( + 'url', + 'flowcell_id', + 'run_date', + 'paired_end', +# 'flowcell_type', + 'read_length', + 'control_lane', + 'cluster_station', + 'sequencer', + 'notes', + 'lane_set', + ) + +class SequencerSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = Sequencer + fields = ('url', 'name', 'instrument_name', 'serial_number', 'model') diff --git a/experiments/templates/experiments/flowcell_detail.html b/experiments/templates/experiments/flowcell_detail.html index 64da7e2..f2317bd 100644 --- a/experiments/templates/experiments/flowcell_detail.html +++ b/experiments/templates/experiments/flowcell_detail.html @@ -26,10 +26,10 @@ - {% for lane in lanes %} + {% for lane in lane_set %} - + {{lane.lane_number}} diff --git a/experiments/templates/experiments/flowcell_header.html b/experiments/templates/experiments/flowcell_header.html index f0cb470..3964192 100644 --- a/experiments/templates/experiments/flowcell_header.html +++ b/experiments/templates/experiments/flowcell_header.html @@ -2,23 +2,23 @@

About this Flowcell

Flowcell: - {{flowcell.flowcell_id}}{% if user.is_staff %}Edit{% endif%} + {{flowcell_id}}{% if user.is_staff %}Edit{% endif%}
+ about="{{ sequencer.url }}"> Instrument: - {{ flowcell.sequencer.name }} - {% if flowcell.sequencer.instrument_name %} - ({{ flowcell.sequencer.instrument_name}}) + {{ sequencer.name }} + {% if sequencer.instrument_name %} + ({{ sequencer.instrument_name}}) {% endif %}
Instrument Model: - {{flowcell.sequencer.model}} + {{sequencer.model}}
- {% for datarun in flowcell.datarun_set.all %} + {% for datarun in datarun_set.all %} Image Analysis: {{datarun.image_software}} {{datarun.image_version}}
@@ -30,14 +30,14 @@ {{datarun.alignment_version}}
{% endfor %} Run Date: - {{ flowcell.run_date }}
+ {{ run_date }}
Type: - {{flowcell.flowcell_type}}
+ {{flowcell_type}}
Read Length: - {{flowcell.read_length}}
+ {{read_length}}
Control Lane: - {{flowcell.control_lane}}
+ {{control_lane}}
Notes: -
{{flowcell.notes}}
+
{{notes}}
diff --git a/experiments/urls.py b/experiments/urls.py index 0b1722e..4492909 100644 --- a/experiments/urls.py +++ b/experiments/urls.py @@ -2,13 +2,29 @@ from __future__ import unicode_literals from django.conf.urls import patterns -urlpatterns = patterns('', - (r'^$', 'experiments.views.index'), - #(r'^liblist$', 'htsworkflow.frontend.experiments.views.test_Libs'), - #(r'^(?P.+)/$', 'gaworkflow.frontend.experiments.views.detail'), - (r'^config/(?P.+)/json$', 'experiments.experiments.flowcell_json'), - (r'^lanes_for/(?P.+)/json$', 'experiments.experiments.lanes_for_json'), - (r'^file/(?P.+)/?$', 'experiments.views.read_result_file'), - (r'^started/(?P.+)/$', 'experiments.views.startedEmail'), - (r'^finished/(?P.+)/$', 'experiments.views.finishedEmail'), -) +from rest_framework import routers + +from .views import ( + ClusterStationViewSet, + LaneViewSet, + FlowCellViewSet, + SequencerViewSet, + ) + +#urlpatterns = patterns('', +# (r'^$', 'experiments.views.index'), +# #(r'^liblist$', 'htsworkflow.frontend.experiments.views.test_Libs'), +# #(r'^(?P.+)/$', 'gaworkflow.frontend.experiments.views.detail'), +# (r'^config/(?P.+)/json$', 'experiments.experiments.flowcell_json'), +# (r'^lanes_for/(?P.+)/json$', 'experiments.experiments.lanes_for_json'), +# (r'^file/(?P.+)/?$', 'experiments.views.read_result_file'), +# (r'^started/(?P.+)/$', 'experiments.views.startedEmail'), +# (r'^finished/(?P.+)/$', 'experiments.views.finishedEmail'), +#) + +router = routers.DefaultRouter() +router.register(r'cluster_station', ClusterStationViewSet) +router.register(r'lane', LaneViewSet) +router.register(r'flowcell', FlowCellViewSet) +router.register(r'sequencer', SequencerViewSet) +urlpatterns = router.urls diff --git a/experiments/views.py b/experiments/views.py index 521e89f..9b1c8a1 100644 --- a/experiments/views.py +++ b/experiments/views.py @@ -16,10 +16,21 @@ from django.template import RequestContext from django.template.loader import get_template from .models import DataRun, DataFile, FlowCell, Lane, Sequencer +from rest_framework import viewsets +from rest_framework.response import Response +from rest_framework.renderers import (TemplateHTMLRenderer, + JSONRenderer, + BrowsableAPIRenderer) + from .admin import LaneOptions from .experiments import estimateFlowcellDuration, estimateFlowcellTimeRemaining, roundToDays, \ getUsersForFlowcell, \ makeEmailLaneMap +from .serializers import ( + ClusterStationSerializer, + SequencerSerializer, + LaneSerializer, + FlowCellSerializer) from samples.changelist import HTSChangeList from samples.models import HTSUser @@ -132,6 +143,72 @@ def finishedEmail(request, pk): return HttpResponse("I've got nothing.") + +class ClusterStationViewSet(viewsets.ReadOnlyModelViewSet): + renderer_classes = (TemplateHTMLRenderer, + BrowsableAPIRenderer, + JSONRenderer) + queryset = ClusterStation.objects.all() + serializer_class = ClusterStationSerializer + # template_name = 'experiments/cluster_station.html' + +from pprint import pprint +class FlowCellViewSet(viewsets.ReadOnlyModelViewSet): + renderer_classes = (TemplateHTMLRenderer, + BrowsableAPIRenderer, + JSONRenderer) + queryset = FlowCell.objects.all() + lookup_field = 'flowcell_id' + serializer_class = FlowCellSerializer + template_name = 'experiments/flowcell_detail.html' + + def retrieve(self, request, *args, **kwargs): + fc = get_object_or_404(self.queryset, flowcell_id = kwargs['flowcell_id']) + context = kwargs.copy() + context['request'] = request + serializer = FlowCellSerializer( + fc, + context=context, + ) + pprint(serializer.data) + return Response(serializer.data) + + #def retrieve(self, request, flowcell_id=None, format=None): + # queryset = FlowCell.objects.all() + # fc = get_object_or_404(queryset, flowcell_id=flowcell_id) + # serializer = FlowCellSerializer( + # fc, + # context={ + # 'request': request, + # 'format': format, + # } + # ) + # return Response( + # serializer.data, + # ) + + #def list(self, *args, **kwargs): + # template_name = 'experiments/flowcell_index.html' + # return super(FlowCellViewSet, self).list(*args, **kwargs) + +class LaneViewSet(viewsets.ReadOnlyModelViewSet): + renderer_classes = (TemplateHTMLRenderer, + BrowsableAPIRenderer, + JSONRenderer) + queryset = Lane.objects.all() + serializer_class = LaneSerializer + template_name = 'experiments/flowcell_lane_detail.html' + + + +class SequencerViewSet(viewsets.ReadOnlyModelViewSet): + renderer_classes = (TemplateHTMLRenderer, + BrowsableAPIRenderer, + JSONRenderer) + queryset = Sequencer.objects.all() + serializer_class = SequencerSerializer + template_name = 'experiments/sequencer.html' + def flowcell_detail(request, flowcell_id, lane_number=None): fc = get_object_or_404(FlowCell, flowcell_id__startswith=flowcell_id) fc.update_data_runs() @@ -186,13 +263,6 @@ def read_result_file(self, key): raise Http404 -def sequencer(request, sequencer_id): - sequencer = get_object_or_404(Sequencer, id=sequencer_id) - context = RequestContext(request, - {'sequencer': sequencer}) - return render_to_response('experiments/sequencer.html', context) - - def lanes_for(request, username=None): """ Generate a report of recent activity for a user diff --git a/htsworkflow/settings/base.py b/htsworkflow/settings/base.py index 97518e0..dba1ab2 100644 --- a/htsworkflow/settings/base.py +++ b/htsworkflow/settings/base.py @@ -42,6 +42,7 @@ INSTALLED_APPS = [ 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.humanize', + 'rest_framework', 'eland_config', 'samples', @@ -106,3 +107,9 @@ NOTIFICATION_BCC=[] # Update this in settings_local to point to your flowcell result directory RESULT_HOME_DIR = join(PROJECT_ROOT, 'test', 'result', 'flowcells') + + +REST_FRAMEWORK = { + 'DEFAULT_PAGINATION_SERIALIZER_CLASS': 'rest_framework.pagination.PaginationSerializer', + 'PAGINATE_BY' : 25, +} diff --git a/htsworkflow/templates/samples/species_list.html b/htsworkflow/templates/samples/species_list.html new file mode 100644 index 0000000..58727b5 --- /dev/null +++ b/htsworkflow/templates/samples/species_list.html @@ -0,0 +1,30 @@ +{% extends "base_site.html" %} +{% load admin_list i18n %} +{% load staticfiles %} +{% block bodyclass %}change-list{% endblock %} +{% block coltype %}flex{% endblock %} + +{% block content %} +
+
+ {% block summary_stats %} + + + + + + + + + {% for s in species %} + + + + + {% endfor %} + +
SpeciesCommon Name
{{ s.scientific_name }}{{ s.common_name }}
+
+ {% endblock %} +
+{% endblock %} diff --git a/htsworkflow/urls.py b/htsworkflow/urls.py index bb83642..1f258eb 100644 --- a/htsworkflow/urls.py +++ b/htsworkflow/urls.py @@ -3,29 +3,32 @@ from django.contrib import admin import django admin.autodiscover() -from django.conf import settings +from experiments.urls import urlpatterns as experiment_urls -urlpatterns = patterns('', +urlpatterns = experiment_urls + +urlpatterns += patterns( + '', url('^accounts/', include('django.contrib.auth.urls')), # Base: url(r'^eland_config/', include('eland_config.urls')), # Experiments: - url(r'^experiments/', include('experiments.urls')), - url(r'^lane/(?P\w+)', - 'experiments.views.flowcell_lane_detail'), - url(r'^flowcell/(?P\w+)/((?P\w+)/)?$', - 'experiments.views.flowcell_detail'), + # url(r'^experiments/', include('experiments.urls')), + # url(r'^lane/(?P\w+)', + # 'experiments.views.flowcell_lane_detail'), + # url(r'^flowcell/(?P\w+)/((?P\w+)/)?$', + # 'experiments.views.flowcell_detail'), url(r'^inventory/', include('inventory.urls')), url(r'^library/', include('samples.urls')), - url(r'^lanes_for/$', 'experiments.views.lanes_for'), - url(r'^lanes_for/(?P[-_ \w]+)', 'experiments.views.lanes_for'), - ### library id to admin url - url(r'^library_id_to_admin_url/(?P\w+)/$', - 'samples.views.library_id_to_admin_url'), - ### sample / library information + # url(r'^lanes_for/$', 'experiments.views.lanes_for'), + # url(r'^lanes_for/(?P[-_ \w]+)', 'experiments.views.lanes_for'), + # library id to admin url + # url(r'^library_id_to_admin_url/(?P\w+)/$', + # 'samples.views.library_id_to_admin_url'), + # sample / library information url(r'^samples/', include('samples.urls')), - url(r'^sequencer/(?P\w+)', - 'experiments.views.sequencer'), + # url(r'^sequencer/(?P\w+)', + # 'experiments.views.sequencer'), url(r'^admin/', include(admin.site.urls)), ) diff --git a/samples/serializers.py b/samples/serializers.py new file mode 100644 index 0000000..766d988 --- /dev/null +++ b/samples/serializers.py @@ -0,0 +1,30 @@ +from rest_framework import serializers + +from .models import (Antibody, + Cellline, + ExperimentType, + Species, + Affiliation, + Library, + HTSUser) + + +class ExperimentTypeSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = ExperimentType + fields = ('url', 'name') + + +class SpeciesSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = Species + fields = ('url', 'common_name', 'scientific_name') + + +class LibrarySerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = Library + fields = ('url', 'library_name', 'library_species', 'replicate', + 'experiment_type', + 'made_for', 'made_by', 'stopping_point', + 'undiluted_concentration', 'gel_cut_size', 'notes') diff --git a/samples/urls.py b/samples/urls.py index 1bda463..e4c4073 100644 --- a/samples/urls.py +++ b/samples/urls.py @@ -2,15 +2,26 @@ from __future__ import unicode_literals from django.conf.urls import patterns, url -urlpatterns = patterns('samples.views', - # View livrary list - url(r'^$', 'library'), - url(r'^not_run/$', 'library_not_run'), - url(r'^(?P\w+)/$', - 'library_to_flowcells'), +from rest_framework import routers - url(r"^library/(?P\w+)/json$", 'library_json'), - url(r"^species/(?P\w+)/json$", 'species_json'), - url(r"^species/(?P\w+)$", 'species'), - url(r"^antibody/$", 'antibodies'), +from .views import ExperimentTypeViewSet, LibraryViewSet, SpeciesViewSet + +urlpatterns = patterns( + 'samples.views', + # View library list + # url(r'^$', 'library'), + # url(r'^not_run/$', 'library_not_run'), + # url(r'^(?P\w+)/$', + # 'library_to_flowcells'), + + # url(r"^library/(?P\w+)/json$", 'library_json'), + # url(r"^species/(?P\w+)/json$", 'species_json'), + # url(r"^species/(?P\w+)$", 'species'), + # url(r"^antibody/$", 'antibodies'), ) + +router = routers.DefaultRouter() +router.register(r'species', SpeciesViewSet) +router.register(r'libraries', LibraryViewSet) +router.register(r'experiment_type', ExperimentTypeViewSet) +urlpatterns += router.urls diff --git a/samples/views.py b/samples/views.py index 3b5ea35..78cd0ba 100644 --- a/samples/views.py +++ b/samples/views.py @@ -12,12 +12,22 @@ from django.template import RequestContext from django.template.loader import get_template from django.contrib.auth.decorators import login_required +from rest_framework import viewsets +from rest_framework.response import Response +from rest_framework.renderers import (TemplateHTMLRenderer, + JSONRenderer, + BrowsableAPIRenderer) + from htsworkflow.auth import require_api_key from experiments.models import FlowCell, LANE_STATUS_MAP from .changelist import HTSChangeList from .models import Antibody, Library, Species from .admin import LibraryOptions from .results import get_flowcell_result_dict +from .serializers import (ExperimentTypeSerializer, + LibrarySerializer, + SpeciesSerializer) + from bcmagic.forms import BarcodeMagicForm from htsworkflow.pipelines import runfolder from htsworkflow.pipelines.samplekey import SampleKey @@ -451,26 +461,62 @@ def library_json(request, library_id): return HttpResponse(lib_json, content_type='application/json') -@csrf_exempt -def species_json(request, species_id): - """ - Return information about a species. - """ - raise Http404 - - -def species(request, species_id): - species = get_object_or_404(Species, id=species_id) - - context = RequestContext(request, - {'species': species}) - - return render_to_response("samples/species_detail.html", context) +class LibraryViewSet(viewsets.ReadOnlyModelViewSet): + renderer_classes = (TemplateHTMLRenderer, + BrowsableAPIRenderer, + JSONRenderer) + queryset = Library.objects.all() + serializer_class = LibrarySerializer + pagination_class = 'rest_framework.pagination.LimitOffsetPagination' + default_limit = 50 + template_name = 'samples/library_detail.html' + + +class ExperimentTypeViewSet(viewsets.ReadOnlyModelViewSet): + renderer_classes = (BrowsableAPIRenderer, + JSONRenderer) + queryset = ExperimentType.objects.all() + serializer_class = ExperimentTypeSerializer + +#@csrf_exempt +#def species_json(request, species_id): +# """ +# Return information about a species. +# """ +# raise Http404 +# +# +#def species(request, species_id): +# species = get_object_or_404(Species, id=species_id) +# +# context = RequestContext(request, +# {'species': species}) +# +# return render_to_response("samples/species_detail.html", context) +# + +class SpeciesViewSet(viewsets.ReadOnlyModelViewSet): + renderer_classes = (TemplateHTMLRenderer, + BrowsableAPIRenderer, + JSONRenderer) + queryset = Species.objects.all() + serializer_class = SpeciesSerializer + template_name = 'samples/species_detail.html' + + def list(self, request, format=format): + queryset = Species.objects.all() + serializer = self.serializer_class( + queryset, + many=True, + context={'request': request}) + return Response({'species': serializer.data}, + template_name='samples/species_list.html') def antibodies(request): - context = RequestContext(request, - {'antibodies': Antibody.objects.order_by('antigene')}) + context = RequestContext( + request, + {'antibodies': Antibody.objects.order_by('antigene')}) return render_to_response("samples/antibody_index.html", context) -- 2.30.2