Merge pull request #1401 from normanjaeckel/DjangoRESTFramework

Added DjangoRESTFramework
This commit is contained in:
Oskar Hahn 2015-01-17 09:25:18 +01:00
commit 0b995b21ac
13 changed files with 169 additions and 1 deletions

View File

@ -15,8 +15,10 @@ class AgendaAppConfig(AppConfig):
from openslides.config.signals import config_signal from openslides.config.signals import config_signal
from openslides.projector.api import register_slide from openslides.projector.api import register_slide
from openslides.projector.signals import projector_overlays from openslides.projector.signals import projector_overlays
from openslides.utils.rest_api import router
from .signals import agenda_list_of_speakers, setup_agenda_config, listen_to_related_object_delete_signal from .signals import agenda_list_of_speakers, setup_agenda_config, listen_to_related_object_delete_signal
from .slides import agenda_slide from .slides import agenda_slide
from .views import ItemViewSet
# Connect signals. # Connect signals.
config_signal.connect(setup_agenda_config, dispatch_uid='setup_agenda_config') config_signal.connect(setup_agenda_config, dispatch_uid='setup_agenda_config')
@ -26,3 +28,6 @@ class AgendaAppConfig(AppConfig):
# Register slides. # Register slides.
Item = self.get_model('Item') Item = self.get_model('Item')
register_slide('agenda', agenda_slide, Item) register_slide('agenda', agenda_slide, Item)
# Register viewset.
router.register('agenda/item', ItemViewSet)

View File

@ -0,0 +1,34 @@
from rest_framework import serializers
from .models import Item, Speaker
class SpeakerSerializer(serializers.HyperlinkedModelSerializer):
"""
Serializer for a agenda.models.Speaker objects.
"""
class Meta:
model = Speaker
fields = (
'id',
'user',
'begin_time',
'end_time',
'weight')
class ItemSerializer(serializers.ModelSerializer):
"""
Serializer for a agenda.models.Item objects.
"""
get_title = serializers.CharField(read_only=True)
get_title_supplement = serializers.CharField(read_only=True)
item_no = serializers.CharField(read_only=True)
speaker_set = SpeakerSerializer(many=True, read_only=True)
# content_object = serializers.PrimaryKeyRelatedField(read_only=True)
class Meta:
model = Item
exclude = ('content_type', 'object_id')
# TODO: Problem: User can always see the time shedule. Filter fields with respect of permission.

View File

@ -23,6 +23,7 @@ from openslides.projector.api import (
get_projector_overlays_js, get_projector_overlays_js,
get_overlays, get_overlays,
update_projector) update_projector)
from openslides.utils import rest_api
from openslides.utils.exceptions import OpenSlidesError from openslides.utils.exceptions import OpenSlidesError
from openslides.utils.pdf import stylesheet from openslides.utils.pdf import stylesheet
from openslides.utils.utils import html_strong from openslides.utils.utils import html_strong
@ -42,6 +43,7 @@ from openslides.utils.views import (
from .csv_import import import_agenda_items from .csv_import import import_agenda_items
from .forms import AppendSpeakerForm, ItemForm, ItemOrderForm, RelatedItemForm from .forms import AppendSpeakerForm, ItemForm, ItemOrderForm, RelatedItemForm
from .models import Item, Speaker from .models import Item, Speaker
from .serializers import ItemSerializer
class Overview(TemplateView): class Overview(TemplateView):
@ -773,3 +775,42 @@ class ItemCSVImportView(CSVImportView):
required_permission = 'agenda.can_manage_agenda' required_permission = 'agenda.can_manage_agenda'
success_url_name = 'item_overview' success_url_name = 'item_overview'
template_name = 'agenda/item_form_csv_import.html' template_name = 'agenda/item_form_csv_import.html'
class ItemViewSet(rest_api.viewsets.ModelViewSet):
"""
API endpoint to view, edit and delete agenda items.
"""
model = Item
serializer_class = ItemSerializer
def check_permissions(self, request):
"""
Calls self.permission_denied() if the requesting user has not the
permission to see and in case of create, update or destroy requests
the permission to manage.
"""
if not request.user.has_perm('agenda.can_see_agenda'):
self.permission_denied(request)
elif (self.action in ('create', 'update', 'destroy')
and not request.user.has_perm('agenda.can_manage_agenda')):
# This is the same as self.action not in ('list', 'retrieve')
self.permission_denied(request)
def check_object_permissions(self, request, obj):
"""
Checks if the requesting user has permission to see also an
organizational item if it is one.
"""
if obj.type == obj.ORGANIZATIONAL_ITEM and not request.user.has_perm('agenda.can_see_orga_items'):
self.permission_denied(request)
def get_queryset(self):
"""
Filters organizational items if the user has no permission to see it.
"""
queryset = Item.objects.all()
if (not self.request.user.has_perm('agenda.can_see_orga_items') and
not self.request.user.has_perm('agenda.can_manage_agenda')):
queryset = queryset.exclude(type__exact=Item.ORGANIZATIONAL_ITEM)
return queryset

View File

@ -13,7 +13,9 @@ class CoreAppConfig(AppConfig):
# Import all required stuff. # Import all required stuff.
from openslides.config.signals import config_signal from openslides.config.signals import config_signal
from openslides.projector.api import register_slide_model from openslides.projector.api import register_slide_model
from openslides.utils.rest_api import router
from .signals import setup_general_config from .signals import setup_general_config
from .views import CustomSlideViewSet
# Connect signals. # Connect signals.
config_signal.connect(setup_general_config, dispatch_uid='setup_general_config') config_signal.connect(setup_general_config, dispatch_uid='setup_general_config')
@ -21,3 +23,6 @@ class CoreAppConfig(AppConfig):
# Register slides. # Register slides.
CustomSlide = self.get_model('CustomSlide') CustomSlide = self.get_model('CustomSlide')
register_slide_model(CustomSlide, 'core/customslide_slide.html') register_slide_model(CustomSlide, 'core/customslide_slide.html')
# Register viewset.
router.register('core/customslide', CustomSlideViewSet)

View File

@ -0,0 +1,11 @@
from rest_framework import serializers
from .models import CustomSlide
class CustomSlideSerializer(serializers.ModelSerializer):
"""
Serializer for a core.models.CustomSlide objects.
"""
class Meta:
model = CustomSlide

View File

@ -12,14 +12,16 @@ from haystack.views import SearchView as _SearchView
from openslides import get_version as get_openslides_version from openslides import get_version as get_openslides_version
from openslides import get_git_commit_id, RELEASE from openslides import get_git_commit_id, RELEASE
from openslides.config.api import config from openslides.config.api import config
from openslides.utils import rest_api
from openslides.utils import views as utils_views
from openslides.utils.plugins import get_plugin_description, get_plugin_verbose_name, get_plugin_version from openslides.utils.plugins import get_plugin_description, get_plugin_verbose_name, get_plugin_version
from openslides.utils.signals import template_manipulation from openslides.utils.signals import template_manipulation
from openslides.utils import views as utils_views
from openslides.utils.widgets import Widget from openslides.utils.widgets import Widget
from .forms import SelectWidgetsForm from .forms import SelectWidgetsForm
from .models import CustomSlide, Tag from .models import CustomSlide, Tag
from .exceptions import TagException from .exceptions import TagException
from .serializers import CustomSlideSerializer
class DashboardView(utils_views.AjaxMixin, utils_views.TemplateView): class DashboardView(utils_views.AjaxMixin, utils_views.TemplateView):
@ -291,3 +293,20 @@ class TagListView(utils_views.AjaxMixin, utils_views.ListView):
action=getattr(self, 'action', None), action=getattr(self, 'action', None),
error=getattr(self, 'error', None), error=getattr(self, 'error', None),
**context) **context)
class CustomSlideViewSet(rest_api.viewsets.ModelViewSet):
"""
API endpoint to view, edit and delete custom slides.
"""
model = CustomSlide
queryset = CustomSlide.objects.all()
serializer_class = CustomSlideSerializer
def check_permissions(self, request):
"""
Calls self.permission_denied() if the requesting user has not the
permission to manage.
"""
if not request.user.has_perm('core.can_manage_projector'):
self.permission_denied(request)

View File

@ -88,6 +88,7 @@ INSTALLED_APPS = (
'mptt', 'mptt',
'haystack', # full-text-search 'haystack', # full-text-search
'ckeditor', 'ckeditor',
'rest_framework',
'openslides.poll', 'openslides.poll',
'openslides.core', 'openslides.core',
'openslides.account', 'openslides.account',

View File

@ -3,6 +3,7 @@ from django.conf.urls import include, patterns, url
from openslides.core.views import ErrorView from openslides.core.views import ErrorView
from openslides.utils.plugins import get_urlpatterns from openslides.utils.plugins import get_urlpatterns
from openslides.utils.rest_api import router
handler403 = ErrorView.as_view(status_code=403) handler403 = ErrorView.as_view(status_code=403)
handler404 = ErrorView.as_view(status_code=404) handler404 = ErrorView.as_view(status_code=404)
@ -31,6 +32,13 @@ urlpatterns += patterns(
(r'^ckeditor/', include('ckeditor.urls')), (r'^ckeditor/', include('ckeditor.urls')),
) )
urlpatterns += patterns(
'',
url(r'^api/', include(router.urls)),
# TODO: Remove the next line if you are sure.
# url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
)
# TODO: move this patterns into core or the participant app # TODO: move this patterns into core or the participant app
from openslides.users.views import UserSettingsView, UserPasswordSettingsView from openslides.users.views import UserSettingsView, UserPasswordSettingsView
urlpatterns += patterns( urlpatterns += patterns(

View File

@ -15,7 +15,9 @@ class UsersAppConfig(AppConfig):
from openslides.config.signals import config_signal from openslides.config.signals import config_signal
from openslides.core.signals import post_database_setup from openslides.core.signals import post_database_setup
from openslides.projector.api import register_slide_model from openslides.projector.api import register_slide_model
from openslides.utils.rest_api import router
from .signals import create_builtin_groups_and_admin, setup_users_config, user_post_save from .signals import create_builtin_groups_and_admin, setup_users_config, user_post_save
from .views import UserViewSet
# Load User model. # Load User model.
User = self.get_model('User') User = self.get_model('User')
@ -27,3 +29,6 @@ class UsersAppConfig(AppConfig):
# Register slides. # Register slides.
register_slide_model(User, 'participant/user_slide.html') register_slide_model(User, 'participant/user_slide.html')
# Register viewset.
router.register('users/user', UserViewSet)

View File

@ -0,0 +1,15 @@
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.ModelSerializer):
"""
Serializer for a users.models.User objects.
"""
class Meta:
model = User
fields = (
'username',
'first_name',
'last_name')

View File

@ -6,6 +6,7 @@ from django.core.urlresolvers import reverse
from django.utils.translation import ugettext as _, ugettext_lazy, activate from django.utils.translation import ugettext as _, ugettext_lazy, activate
from openslides.config.api import config from openslides.config.api import config
from openslides.utils import rest_api
from openslides.utils.utils import delete_default_permissions, html_strong from openslides.utils.utils import delete_default_permissions, html_strong
from openslides.utils.views import ( from openslides.utils.views import (
CreateView, CSVImportView, DeleteView, DetailView, FormView, ListView, CreateView, CSVImportView, DeleteView, DetailView, FormView, ListView,
@ -19,6 +20,7 @@ from .forms import (GroupForm, UserCreateForm, UserMultipleCreateForm,
UsersettingsForm, UserUpdateForm) UsersettingsForm, UserUpdateForm)
from .models import Group, User from .models import Group, User
from .pdf import users_to_pdf, users_passwords_to_pdf from .pdf import users_to_pdf, users_passwords_to_pdf
from .serializers import UserSerializer
class UserListView(ListView): class UserListView(ListView):
@ -259,6 +261,24 @@ class ResetPasswordView(SingleObjectMixin, QuestionView):
return _('The Password for %s was successfully reset.') % html_strong(self.get_object()) return _('The Password for %s was successfully reset.') % html_strong(self.get_object())
class UserViewSet(rest_api.viewsets.ModelViewSet):
"""
API endpoint to view, edit and delete users.
"""
model = User
queryset = User.objects.all()
serializer_class = UserSerializer
def check_permissions(self, request):
"""
Calls self.permission_denied() if the requesting user has not the
permission to manage.
"""
# TODO: More work on this required.
if not request.user.has_perm('users.can_manage'):
self.permission_denied(request)
class GroupListView(ListView): class GroupListView(ListView):
""" """
Overview over all groups. Overview over all groups.

View File

@ -0,0 +1,3 @@
from rest_framework import permissions, routers, viewsets # noqa
router = routers.DefaultRouter()

View File

@ -5,6 +5,7 @@ bleach>=1.4,<1.5
django-ckeditor-updated>=4.2.3,<4.4 django-ckeditor-updated>=4.2.3,<4.4
django-haystack>=2.1,<2.4 django-haystack>=2.1,<2.4
django-mptt>=0.6,<0.7 django-mptt>=0.6,<0.7
djangorestframework>=3.0.1,<3.1
jsonfield>=0.9.19,<1.1 jsonfield>=0.9.19,<1.1
natsort>=3.2,<3.6 natsort>=3.2,<3.6
reportlab>=3.0,<3.2 reportlab>=3.0,<3.2