django class-based views (slovenian)

26
Class-based views Luka Zakrajšek @bancek Django Meet Ljubljana, 22. maj 2012

Upload: luka-zakrajsek

Post on 16-May-2015

897 views

Category:

Technology


6 download

TRANSCRIPT

Page 1: Django Class-based views (Slovenian)

Class-based views

Luka Zakrajšek@bancek

Django Meet Ljubljana,22. maj 2012

Page 2: Django Class-based views (Slovenian)

Podatkovna baza

• baze ne potrebujemo, ker do vseh podatkov dostopamo preko REST-a

• radi bi uporabljali Session in Message framework

Page 3: Django Class-based views (Slovenian)

...

AUTHENTICATION_BACKENDS = ( 'federweb.auth.models.RestEngineBackend',)

INSTALLED_APPS = ( 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.contenttypes', ...)

SESSION_ENGINE = 'django.contrib.sessions.backends.file'

settings.py

Page 4: Django Class-based views (Slovenian)

Avtentikacija

• uporabimo Django Auth framework

• potrebujemo lastni Authentication backend

Page 5: Django Class-based views (Slovenian)

class RestEngineBackend(object): supports_object_permissions = False supports_anonymous_user = True def authenticate(self, username=None, password=None): users = federation.users.full() for user in users: if user.username == username and user.check_password(password): return user logger.error('Authentication failed for username %s' % username)

def get_user(self, user_id): return federation.users.get(user_id) or None

backend = RestEngineBackend()

user_logged_in.disconnect(update_last_login)

Authentication backend

Page 6: Django Class-based views (Slovenian)
Page 7: Django Class-based views (Slovenian)

class AppNodeMixin(object): def __init__(self, *args, **kwargs): super(AppNodeMixin, self).__init__(*args, **kwargs) self.app_name = getattr(self, 'app_name', None) self.node_name = getattr(self, 'node_name', None) self.action_name = getattr(self, 'action_name', None)

def get_template_names(self): if self.template_name: return [self.template_name] action_name = self.action_name or self.node_name template = '%s/%s/%s.html' % (self.app_name, self.node_name, action_name) return [template] def get_context_data(self, **kwargs): ctx = super(AppNodeMixin, self).get_context_data(**kwargs) ctx['request'] = self.request return ctx

App module mixin

Page 8: Django Class-based views (Slovenian)

def profile_url(user): url_map = { 'FederationCoordinator': reverse('federation'), 'CloudAdministrator': reverse('provider'), 'FederationUser': reverse('user') } roles = user.roles.all() for role in roles: if role.name in url_map: return url_map[role.name] logger.error('Unknown roles for user "%s"' % user)

def home(request): if request.user.is_authenticated(): return HttpResponseRedirect(profile_url(request.user)) else: return redirect_to_login(request.path)

Role router

Page 9: Django Class-based views (Slovenian)

class RoleRequiredMixin(object): user_role = None @method_decorator(login_required) def dispatch(self, request, *args, **kwargs): user = request.user if self.user_role: if not user or not user.is_authenticated(): raise Http404 roles = user.roles.all() for role in roles: if role.name == self.user_role: return super(RoleRequiredMixin, self).dispatch( request, *args, **kwargs) raise Http404

Role required mixin

Page 10: Django Class-based views (Slovenian)

class RestMixin(object): model = None def get_context_data(self, **kwargs): ctx = super(RestMixin, self).get_context_data(**kwargs) ctx['model'] = self.model return ctx

REST mixin

Page 11: Django Class-based views (Slovenian)

class RestDetailMixin(object): model = None action_name = 'detail'

def get_object(self, id): obj = self.model.get(id) if not obj: raise Http404('Object not found') return obj @cached_property def obj(self): return self.get_object(self.kwargs['id']) def get_context_data(self, **kwargs): ct = super(RestDetailMixin, self).get_context_data(**kwargs) ct['object'] = self.obj return ct

REST detail mixin

Page 12: Django Class-based views (Slovenian)

class RestDetailView(RestDetailMixin, TemplateView): pass

REST detail view

Page 13: Django Class-based views (Slovenian)

class RestRemoveView(RedirectView): model = None message = None permanent = False def get(self, request, id, *args, **kwargs): obj = self.model.get(id) if not obj.delete(): raise Http404 if self.message: messages.success(self.request, self.message) return super(RestRemoveView, self).get(request, *args, **kwargs)

REST remove object view

Page 14: Django Class-based views (Slovenian)

urlpatterns = patterns('', url(r'^$', Dashboard.as_view(), name='federation'), url(r'^/providers$', ProvidersList.as_view(), name='federation_providers'), url(r'^/providers/create$', ProvidersCreate.as_view(), name='federation_providers_create'), url(r'^/providers/(?P<id>\d+)/edit$', ProvidersEdit.as_view(), name='federation_providers_edit'), url(r'^/providers/(?P<id>\d+)/remove$', ProvidersRemove.as_view(), name='federation_providers_remove'), ...)

urls.py

Page 15: Django Class-based views (Slovenian)

class AppMixin(RoleRequiredMixin): app_name = 'federation' user_role = 'FederationCoordinator'

class Dashboard(AppMixin, AppNodeMixin, TemplateView): node_name = 'dashboard' # requires role: "FederationCoordinator" # renders template: "federation/dashboard/dashboard.html"

App views

Page 16: Django Class-based views (Slovenian)

{% extends 'base.html' %}

{% load common ui %}

{% block head_title %}Federation{% endblock %}

{% block nav %} <li class="{% block nav_dashboard %}{% endblock %}"> <a href="{% url federation %}">Dashboard</a> </li> <li class="{% block nav_users %}{% endblock %}"> <a href="{% url federation_users %}">Users</a> </li> ...{% endblock %}

{% block breadcrumbs %} {% url federation as url %}{% breadcrumb 'Home' url %}{{ block.super }}{% endblock %}

App base template

Page 17: Django Class-based views (Slovenian)

class ProvidersMixin(AppMixin, AppNodeMixin): node_name = 'providers' model = federation.providers # requires role "FederationCoordinator"

class ProvidersList(ProvidersMixin, RestMixin, TemplateView): pass # renders "federation/providers/providers.html"

class ProvidersEdit(ProvidersMixin, RestDetailMixin, FormView): action_name = 'edit' form_class = ProviderForm success_url = reverse_lazy('federation_providers') ... # renders "federation/providers/edit.html"

class ProvidersRemove(ProvidersMixin, RestRemoveView): message = u'Provider was successfully removed.' url = reverse_lazy('federation_providers') # redirects to "/federation/providers"

Module views

Page 18: Django Class-based views (Slovenian)

{% extends 'federation/base.html' %}

{% load common ui %}

{% block head_title %}Providers{% endblock %}

{% block nav_providers %}active{% endblock %}

{% block subnav %} <li class="{% block subnav_providers %}{% endblock %}"> <a href="{% url federation_providers %}">Providers</a> </li> <li class="{% block subnav_providers_create %}{% endblock %}"> <a href="{% url federation_providers_create %}">Create Provider</a> </li>{% endblock %}

{% block breadcrumbs %} {% url federation_providers as url %} {% breadcrumb 'Providers' url %}{{ block.super }}{% endblock %}

Module base template

Page 19: Django Class-based views (Slovenian)

{% extends 'federation/base.html' %}

{% load common ui %}

{% block nav_dashboard %}active{% endblock %}

{% block breadcrumbs %}{% endblock %}

{% block content %} <h2>Hey, {{ request.user.firstName}}</h2>{% endblock %}

Module dashboard

Page 20: Django Class-based views (Slovenian)
Page 21: Django Class-based views (Slovenian)

{% extends 'federation/providers/base.html' %}

{% load common ui %}

{% block subnav_providers %}active{% endblock %}

{% block title %} <h2>Providers</h2>{% endblock %}

{% block content %} {% for object in model.full %} <p> {{ object.name }} <a href="{% url federation_providers_edit object.id %}">Edit</a> </p> {% endfor %}{% endblock %}

Objects list

Page 22: Django Class-based views (Slovenian)
Page 23: Django Class-based views (Slovenian)

{% extends 'federation/providers/base.html' %}...{% block breadcrumbs %} {% url federation_providers_edit object.id as url %} {% breadcrumb 'Edit provider' url %}{{ block.super }}{% endblock %}

{% block title %}<h2>Edit Provider</h2>{% endblock title %}

{% block content %} <form action="" method="post" class="form-horizontal"> <fieldset> {% csrf_token %} {% form_errors form %} {% form_field form.name 'Name' %} {% form_field form.provider_uri 'Provider URI' %} <button class="btn btn-primary" type="submit">Save</button> </fieldset> </form>{% endblock %}

Object edit

Page 24: Django Class-based views (Slovenian)
Page 26: Django Class-based views (Slovenian)

Vprašanja?

• Hvala za pozornost!