Merge pull request #1401 from normanjaeckel/DjangoRESTFramework
Added DjangoRESTFramework
This commit is contained in:
commit
0b995b21ac
@ -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)
|
||||||
|
34
openslides/agenda/serializers.py
Normal file
34
openslides/agenda/serializers.py
Normal 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.
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
11
openslides/core/serializers.py
Normal file
11
openslides/core/serializers.py
Normal 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
|
@ -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)
|
||||||
|
@ -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',
|
||||||
|
@ -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(
|
||||||
|
@ -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)
|
||||||
|
15
openslides/users/serializers.py
Normal file
15
openslides/users/serializers.py
Normal 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')
|
@ -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.
|
||||||
|
3
openslides/utils/rest_api.py
Normal file
3
openslides/utils/rest_api.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from rest_framework import permissions, routers, viewsets # noqa
|
||||||
|
|
||||||
|
router = routers.DefaultRouter()
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user