{"action":"created","comment":{"url":"https://api.github.com/repos/zestedesavoir/zds-site/pulls/comments/28413978","id":28413978,"diff_hunk":"@@ -177,230 +237,222 @@ def modify_gallery(request):\n                 \"images\": gallery.get_images(),\n                 \"form\": form,\n             })\n-    return redirect(gallery.get_absolute_url())\n+        return redirect(gallery.get_absolute_url())\n \n \n-@login_required\n-@can_write_and_read_now\n-def edit_image(request, gal_pk, img_pk):\n+class GalleryMixin(object):\n+    \"\"\"Mixin that ensure the access to the gallery and fill context data properly\"\"\"\n+\n+    can_write = False  # if `True`, check for user write access\n+\n+    def get_context_data(self, **kwargs):\n+        context = super(GalleryMixin, self).get_context_data(**kwargs)\n+        pk_gallery = self.kwargs.pop('pk_gallery', None)\n+\n+        gallery = get_object_or_404(Gallery, pk=pk_gallery)\n+\n+        user_gallery = ensure_user_access(gallery, self.request.user, can_write=self.can_write)\n+\n+        context['gallery'] = gallery\n+        context['gallery_mode'] = user_gallery\n+\n+        return context\n+\n+\n+class NewImage(GalleryMixin, CreateView):\n+    \"\"\"Creates a new image.\"\"\"\n+\n+    form_class = ImageForm\n+    template_name = 'gallery/image/new.html'\n+    can_write = True  # only allowed users can insert images\n+\n+    @method_decorator(login_required)\n+    @method_decorator(can_write_and_read_now)\n+    def dispatch(self, *args, **kwargs):\n+        return super(NewImage, self).dispatch(*args, **kwargs)\n+\n+    def form_valid(self, form):\n+\n+        context = self.get_context_data(**self.kwargs)\n+\n+        img = Image()\n+        img.gallery = context['gallery']\n+        img.title = form.cleaned_data['title']\n+\n+        if form.cleaned_data['legend'] and form.cleaned_data['legend'] != '':\n+            img.legend = form.cleaned_data['legend']\n+        else:\n+            img.legend = img.title\n+\n+        img.physical = self.request.FILES['physical']\n+        img.pubdate = datetime.now()\n+        img.save()\n+\n+        return redirect(reverse(\"gallery-image-edit\", args=[img.gallery.pk, img.pk]))\n+\n+\n+class EditImage(GalleryMixin, UpdateView):\n     \"\"\"Edit or view an existing image.\"\"\"\n \n-    gal = get_object_or_404(Gallery, pk=gal_pk)\n-    img = get_object_or_404(Image, pk=img_pk)\n+    model = Image\n+    form_class = UpdateImageForm\n+    template_name = \"gallery/image/edit.html\"\n \n-    # Check if user can edit image\n-    try:\n-        gal_mode = UserGallery.objects.get(user=request.user, gallery=gal)\n-        assert gal_mode is not None\n-        if not gal_mode.is_write() and request.method != \"GET\":\n+    @method_decorator(login_required)\n+    @method_decorator(can_write_and_read_now)\n+    def dispatch(self, *args, **kwargs):\n+        return super(EditImage, self).dispatch(*args, **kwargs)\n+\n+    def get_object(self, queryset=None):\n+        pk = self.kwargs.pop('pk', None)\n+        return get_object_or_404(Image, pk=pk)\n+\n+    def get_context_data(self, **kwargs):\n+        context = super(EditImage, self).get_context_data(**kwargs)\n+\n+        context['as_avatar_form'] = ImageAsAvatarForm()\n+\n+        return context\n+\n+    def form_valid(self, form):\n+        self.can_write = True  # only allowed users can change images\n+        context = self.get_context_data(**self.kwargs)\n+        img = self.object\n+        gallery = context['gallery']\n+\n+        if img.gallery != gallery:\n             raise PermissionDenied\n-    except (AssertionError, ObjectDoesNotExist):\n-        raise PermissionDenied\n \n-    # Check if the image belongs to the gallery\n-    if img.gallery != gal:\n-        raise PermissionDenied\n+        can_change = True\n \n-    if request.method == \"POST\":\n-        form = UpdateImageForm(request.POST, request.FILES)\n-        if form.is_valid():\n-            if \"physical\" in request.FILES:\n-                if request.FILES[\"physical\"].size > settings.ZDS_APP['gallery']['image_max_size']:\n-                    messages.error(request, _(u\"Votre image est beaucoup trop lourde, \"\n-                                              u\"réduisez sa taille à moins de {} \"\n-                                              u\"<abbr title=\\\"kibioctet\\\">Kio</abbr> \"\n-                                              u\"avant de l'envoyer.\").format(\n-                                                  str(settings.ZDS_APP['gallery']['image_max_size'] / 1024)))\n-                else:\n-                    img.title = request.POST[\"title\"]\n-                    img.legend = request.POST[\"legend\"]\n-                    img.physical = request.FILES[\"physical\"]\n-                    img.slug = slugify(request.FILES[\"physical\"])\n-                    img.update = datetime.now()\n-                    img.save()\n-                    # Redirect to the newly uploaded image edit page after POST\n-                    return redirect(reverse(\"zds.gallery.views.edit_image\", args=[gal.pk, img.pk]))\n+        if 'physical' in self.request.FILES:  # the user request to change the image\n+            if self.request.FILES[\"physical\"].size > settings.ZDS_APP['gallery']['image_max_size']:\n+                    messages.error(\n+                        self.request,\n+                        _(u\"Votre image est beaucoup trop lourde, réduisez sa taille à moins de {:.0f} \"\n+                          u\"<abbr title=\\\"kibioctet\\\">Kio</abbr> avant de l'envoyer.\").format(\n+                            settings.ZDS_APP['gallery']['image_max_size'] / 1024))\n+\n+                    can_change = False\n             else:\n-                img.title = request.POST[\"title\"]\n-                img.legend = request.POST[\"legend\"]\n-                img.update = datetime.now()\n-                img.save()\n-                # Redirect to the newly uploaded image edit page after POST\n-                return redirect(reverse(\"zds.gallery.views.edit_image\", args=[gal.pk, img.pk]))\n-\n-    else:\n-        form = UpdateImageForm(initial={\n-            \"title\": img.title,\n-            \"legend\": img.legend,\n-            \"physical\": img.physical,\n-            \"new_image\": False,\n-        })\n-\n-    as_avatar_form = ImageAsAvatarForm()\n-    return render(\n-        request,\n-        \"gallery/image/edit.html\", {\n-            \"form\": form,\n-            \"gallery_mode\": gal_mode,\n-            \"as_avatar_form\": as_avatar_form,\n-            \"gallery\": gal,\n-            \"image\": img\n-        })\n+                img.physical = self.request.FILES[\"physical\"]\n+                img.slug = slugify(self.request.FILES[\"physical\"])\n \n+        if can_change:\n+            img.title = form.cleaned_data['title']\n+            img.legend = form.cleaned_data['legend']\n+            img.update = datetime.now()\n+            img.save()\n \n-@can_write_and_read_now\n-@login_required\n-@require_POST\n-def delete_image(request):\n+        return redirect(reverse(\"gallery-image-edit\", args=[img.gallery.pk, img.pk]))\n \n-    try:\n-        gal_pk = request.POST[\"gallery\"]\n-    except KeyError:\n-        raise Http404\n-    gal = get_object_or_404(Gallery, pk=gal_pk)\n-    try:\n-        gal_mode = UserGallery.objects.get(gallery=gal, user=request.user)\n-        assert gal_mode is not None\n \n-        # Only allow RW users to modify images\n-        if not gal_mode.is_write():\n-            raise PermissionDenied\n-    except:\n-        raise PermissionDenied\n-    if \"delete\" in request.POST:\n-        try:\n-            img = Image.objects.get(pk=request.POST[\"image\"], gallery=gal)\n-            img.delete()\n-        except KeyError:\n-            pass\n-        except:\n-            pass\n-    elif \"delete_multi\" in request.POST:\n-        l = request.POST.getlist(\"items\")\n-        Image.objects.filter(pk__in=l, gallery=gal).delete()\n-    return redirect(gal.get_absolute_url())\n+class DeleteImages(DeleteView):\n+    \"\"\"Delete a given image\"\"\"\n \n+    model = Image\n+    http_method_names = ['post', 'delete']\n \n-@can_write_and_read_now\n-@login_required\n-def new_image(request, gal_pk):\n-    \"\"\"Creates a new image.\"\"\"\n+    @method_decorator(login_required)\n+    @method_decorator(can_write_and_read_now)\n+    def dispatch(self, *args, **kwargs):\n+        return super(DeleteImages, self).dispatch(*args, **kwargs)\n \n-    gal = get_object_or_404(Gallery, pk=gal_pk)\n+    def delete(self, request, *args, **kwargs):\n \n-    # check if the user can upload new image in this gallery\n-    try:\n-        gal_mode = UserGallery.objects.get(gallery=gal, user=request.user)\n-        assert gal_mode is not None\n-        if not gal_mode.is_write():\n-            raise PermissionDenied\n-    except:\n-        raise PermissionDenied\n+        pk_gallery = self.request.POST['gallery']\n+        gallery = get_object_or_404(Gallery, pk=pk_gallery)\n+        ensure_user_access(gallery, request.user, can_write=True)\n \n-    if request.method == \"POST\":\n-        form = ImageForm(request.POST, request.FILES)\n-        if form.is_valid():\n-            img = Image()\n-            img.physical = request.FILES[\"physical\"]\n-            img.gallery = gal\n-            img.title = request.POST[\"title\"]\n-            img.slug = slugify(request.FILES[\"physical\"])\n-            img.legend = request.POST[\"legend\"]\n-            img.pubdate = datetime.now()\n-            img.save()\n+        if 'delete_multi' in request.POST:\n+            l = request.POST.getlist(\"items\")\n+            Image.objects.filter(pk__in=l, gallery=gallery).delete()\n+        elif 'delete' in request.POST:\n+            pk = self.request.POST['image']","path":"zds/gallery/views.py","position":467,"original_position":467,"commit_id":"de116ce1778f2e03611877f0c96232ea11faa265","original_commit_id":"de116ce1778f2e03611877f0c96232ea11faa265","user":{"login":"Eskimon","id":761168,"avatar_url":"https://avatars.githubusercontent.com/u/761168?v=3","gravatar_id":"","url":"https://api.github.com/users/Eskimon","html_url":"https://github.com/Eskimon","followers_url":"https://api.github.com/users/Eskimon/followers","following_url":"https://api.github.com/users/Eskimon/following{/other_user}","gists_url":"https://api.github.com/users/Eskimon/gists{/gist_id}","starred_url":"https://api.github.com/users/Eskimon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Eskimon/subscriptions","organizations_url":"https://api.github.com/users/Eskimon/orgs","repos_url":"https://api.github.com/users/Eskimon/repos","events_url":"https://api.github.com/users/Eskimon/events{/privacy}","received_events_url":"https://api.github.com/users/Eskimon/received_events","type":"User","site_admin":false},"body":"landscape a pas l'air d'aimer le nom de variable `pk`","created_at":"2015-04-15T12:16:04Z","updated_at":"2015-04-15T12:16:04Z","html_url":"https://github.com/zestedesavoir/zds-site/pull/2505#discussion_r28413978","pull_request_url":"https://api.github.com/repos/zestedesavoir/zds-site/pulls/2505","_links":{"self":{"href":"https://api.github.com/repos/zestedesavoir/zds-site/pulls/comments/28413978"},"html":{"href":"https://github.com/zestedesavoir/zds-site/pull/2505#discussion_r28413978"},"pull_request":{"href":"https://api.github.com/repos/zestedesavoir/zds-site/pulls/2505"}}},"pull_request":{"url":"https://api.github.com/repos/zestedesavoir/zds-site/pulls/2505","id":32639951,"html_url":"https://github.com/zestedesavoir/zds-site/pull/2505","diff_url":"https://github.com/zestedesavoir/zds-site/pull/2505.diff","patch_url":"https://github.com/zestedesavoir/zds-site/pull/2505.patch","issue_url":"https://api.github.com/repos/zestedesavoir/zds-site/issues/2505","number":2505,"state":"open","locked":false,"title":"Refacto des galeries (rebase de #1996 + refacto additionnelle)","user":{"login":"pierre-24","id":7889675,"avatar_url":"https://avatars.githubusercontent.com/u/7889675?v=3","gravatar_id":"","url":"https://api.github.com/users/pierre-24","html_url":"https://github.com/pierre-24","followers_url":"https://api.github.com/users/pierre-24/followers","following_url":"https://api.github.com/users/pierre-24/following{/other_user}","gists_url":"https://api.github.com/users/pierre-24/gists{/gist_id}","starred_url":"https://api.github.com/users/pierre-24/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pierre-24/subscriptions","organizations_url":"https://api.github.com/users/pierre-24/orgs","repos_url":"https://api.github.com/users/pierre-24/repos","events_url":"https://api.github.com/users/pierre-24/events{/privacy}","received_events_url":"https://api.github.com/users/pierre-24/received_events","type":"User","site_admin":false},"body":"Dans la grande série des grosses PRs, voici la suivante:\r\n\r\n| Q                         | R\r\n| ------------------------- | -------------------------------------------\r\n| Correction de bugs ?      | non\r\n| Nouvelle Fonctionnalité ? | ~oui\r\n| Tickets (_issues_) concernés         | #1996 \r\n\r\nRebase de la PR #1996 de @gustavi \r\n\r\nJ'en ai profité pour refaire un peu de refacto et pour balancer tout [en mode CBV](https://ccbv.co.uk/). \r\n\r\n# Note de QA\r\n\r\n**Attention :** n'oubliez pas de faire un `python manage.py migrate` !!\r\n\r\nIl va falloir tester tout le comportement des galeries, désolé.\r\n\r\nEn particulier, une nouvelle fonction fait son apparition: *édition de galerie*. Parce que j'en avais marre de voir cette énorme faute d'orthographe dans ma galerie.","created_at":"2015-04-04T21:28:30Z","updated_at":"2015-04-15T12:16:04Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a3b2717d437fead23265ab810d2e13d64bc325de","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/zestedesavoir/zds-site/pulls/2505/commits","review_comments_url":"https://api.github.com/repos/zestedesavoir/zds-site/pulls/2505/comments","review_comment_url":"https://api.github.com/repos/zestedesavoir/zds-site/pulls/comments{/number}","comments_url":"https://api.github.com/repos/zestedesavoir/zds-site/issues/2505/comments","statuses_url":"https://api.github.com/repos/zestedesavoir/zds-site/statuses/de116ce1778f2e03611877f0c96232ea11faa265","head":{"label":"pierre-24:rebase_clean_gallery","ref":"rebase_clean_gallery","sha":"de116ce1778f2e03611877f0c96232ea11faa265","user":{"login":"pierre-24","id":7889675,"avatar_url":"https://avatars.githubusercontent.com/u/7889675?v=3","gravatar_id":"","url":"https://api.github.com/users/pierre-24","html_url":"https://github.com/pierre-24","followers_url":"https://api.github.com/users/pierre-24/followers","following_url":"https://api.github.com/users/pierre-24/following{/other_user}","gists_url":"https://api.github.com/users/pierre-24/gists{/gist_id}","starred_url":"https://api.github.com/users/pierre-24/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pierre-24/subscriptions","organizations_url":"https://api.github.com/users/pierre-24/orgs","repos_url":"https://api.github.com/users/pierre-24/repos","events_url":"https://api.github.com/users/pierre-24/events{/privacy}","received_events_url":"https://api.github.com/users/pierre-24/received_events","type":"User","site_admin":false},"repo":{"id":20864390,"name":"zds-site","full_name":"pierre-24/zds-site","owner":{"login":"pierre-24","id":7889675,"avatar_url":"https://avatars.githubusercontent.com/u/7889675?v=3","gravatar_id":"","url":"https://api.github.com/users/pierre-24","html_url":"https://github.com/pierre-24","followers_url":"https://api.github.com/users/pierre-24/followers","following_url":"https://api.github.com/users/pierre-24/following{/other_user}","gists_url":"https://api.github.com/users/pierre-24/gists{/gist_id}","starred_url":"https://api.github.com/users/pierre-24/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pierre-24/subscriptions","organizations_url":"https://api.github.com/users/pierre-24/orgs","repos_url":"https://api.github.com/users/pierre-24/repos","events_url":"https://api.github.com/users/pierre-24/events{/privacy}","received_events_url":"https://api.github.com/users/pierre-24/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/pierre-24/zds-site","description":"Dépot ZDS","fork":true,"url":"https://api.github.com/repos/pierre-24/zds-site","forks_url":"https://api.github.com/repos/pierre-24/zds-site/forks","keys_url":"https://api.github.com/repos/pierre-24/zds-site/keys{/key_id}","collaborators_url":"https://api.github.com/repos/pierre-24/zds-site/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/pierre-24/zds-site/teams","hooks_url":"https://api.github.com/repos/pierre-24/zds-site/hooks","issue_events_url":"https://api.github.com/repos/pierre-24/zds-site/issues/events{/number}","events_url":"https://api.github.com/repos/pierre-24/zds-site/events","assignees_url":"https://api.github.com/repos/pierre-24/zds-site/assignees{/user}","branches_url":"https://api.github.com/repos/pierre-24/zds-site/branches{/branch}","tags_url":"https://api.github.com/repos/pierre-24/zds-site/tags","blobs_url":"https://api.github.com/repos/pierre-24/zds-site/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/pierre-24/zds-site/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/pierre-24/zds-site/git/refs{/sha}","trees_url":"https://api.github.com/repos/pierre-24/zds-site/git/trees{/sha}","statuses_url":"https://api.github.com/repos/pierre-24/zds-site/statuses/{sha}","languages_url":"https://api.github.com/repos/pierre-24/zds-site/languages","stargazers_url":"https://api.github.com/repos/pierre-24/zds-site/stargazers","contributors_url":"https://api.github.com/repos/pierre-24/zds-site/contributors","subscribers_url":"https://api.github.com/repos/pierre-24/zds-site/subscribers","subscription_url":"https://api.github.com/repos/pierre-24/zds-site/subscription","commits_url":"https://api.github.com/repos/pierre-24/zds-site/commits{/sha}","git_commits_url":"https://api.github.com/repos/pierre-24/zds-site/git/commits{/sha}","comments_url":"https://api.github.com/repos/pierre-24/zds-site/comments{/number}","issue_comment_url":"https://api.github.com/repos/pierre-24/zds-site/issues/comments{/number}","contents_url":"https://api.github.com/repos/pierre-24/zds-site/contents/{+path}","compare_url":"https://api.github.com/repos/pierre-24/zds-site/compare/{base}...{head}","merges_url":"https://api.github.com/repos/pierre-24/zds-site/merges","archive_url":"https://api.github.com/repos/pierre-24/zds-site/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/pierre-24/zds-site/downloads","issues_url":"https://api.github.com/repos/pierre-24/zds-site/issues{/number}","pulls_url":"https://api.github.com/repos/pierre-24/zds-site/pulls{/number}","milestones_url":"https://api.github.com/repos/pierre-24/zds-site/milestones{/number}","notifications_url":"https://api.github.com/repos/pierre-24/zds-site/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/pierre-24/zds-site/labels{/name}","releases_url":"https://api.github.com/repos/pierre-24/zds-site/releases{/id}","created_at":"2014-06-15T20:16:21Z","updated_at":"2015-04-14T20:16:41Z","pushed_at":"2015-04-15T11:54:58Z","git_url":"git://github.com/pierre-24/zds-site.git","ssh_url":"git@github.com:pierre-24/zds-site.git","clone_url":"https://github.com/pierre-24/zds-site.git","svn_url":"https://github.com/pierre-24/zds-site","homepage":null,"size":83245,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"dev"}},"base":{"label":"zestedesavoir:dev","ref":"dev","sha":"82ffc3e65c08f46c727adb770fb2f2d9053ae4a8","user":{"login":"zestedesavoir","id":7406239,"avatar_url":"https://avatars.githubusercontent.com/u/7406239?v=3","gravatar_id":"","url":"https://api.github.com/users/zestedesavoir","html_url":"https://github.com/zestedesavoir","followers_url":"https://api.github.com/users/zestedesavoir/followers","following_url":"https://api.github.com/users/zestedesavoir/following{/other_user}","gists_url":"https://api.github.com/users/zestedesavoir/gists{/gist_id}","starred_url":"https://api.github.com/users/zestedesavoir/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zestedesavoir/subscriptions","organizations_url":"https://api.github.com/users/zestedesavoir/orgs","repos_url":"https://api.github.com/users/zestedesavoir/repos","events_url":"https://api.github.com/users/zestedesavoir/events{/privacy}","received_events_url":"https://api.github.com/users/zestedesavoir/received_events","type":"Organization","site_admin":false},"repo":{"id":14778920,"name":"zds-site","full_name":"zestedesavoir/zds-site","owner":{"login":"zestedesavoir","id":7406239,"avatar_url":"https://avatars.githubusercontent.com/u/7406239?v=3","gravatar_id":"","url":"https://api.github.com/users/zestedesavoir","html_url":"https://github.com/zestedesavoir","followers_url":"https://api.github.com/users/zestedesavoir/followers","following_url":"https://api.github.com/users/zestedesavoir/following{/other_user}","gists_url":"https://api.github.com/users/zestedesavoir/gists{/gist_id}","starred_url":"https://api.github.com/users/zestedesavoir/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zestedesavoir/subscriptions","organizations_url":"https://api.github.com/users/zestedesavoir/orgs","repos_url":"https://api.github.com/users/zestedesavoir/repos","events_url":"https://api.github.com/users/zestedesavoir/events{/privacy}","received_events_url":"https://api.github.com/users/zestedesavoir/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/zestedesavoir/zds-site","description":"Dépot ZDS","fork":false,"url":"https://api.github.com/repos/zestedesavoir/zds-site","forks_url":"https://api.github.com/repos/zestedesavoir/zds-site/forks","keys_url":"https://api.github.com/repos/zestedesavoir/zds-site/keys{/key_id}","collaborators_url":"https://api.github.com/repos/zestedesavoir/zds-site/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/zestedesavoir/zds-site/teams","hooks_url":"https://api.github.com/repos/zestedesavoir/zds-site/hooks","issue_events_url":"https://api.github.com/repos/zestedesavoir/zds-site/issues/events{/number}","events_url":"https://api.github.com/repos/zestedesavoir/zds-site/events","assignees_url":"https://api.github.com/repos/zestedesavoir/zds-site/assignees{/user}","branches_url":"https://api.github.com/repos/zestedesavoir/zds-site/branches{/branch}","tags_url":"https://api.github.com/repos/zestedesavoir/zds-site/tags","blobs_url":"https://api.github.com/repos/zestedesavoir/zds-site/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/zestedesavoir/zds-site/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/zestedesavoir/zds-site/git/refs{/sha}","trees_url":"https://api.github.com/repos/zestedesavoir/zds-site/git/trees{/sha}","statuses_url":"https://api.github.com/repos/zestedesavoir/zds-site/statuses/{sha}","languages_url":"https://api.github.com/repos/zestedesavoir/zds-site/languages","stargazers_url":"https://api.github.com/repos/zestedesavoir/zds-site/stargazers","contributors_url":"https://api.github.com/repos/zestedesavoir/zds-site/contributors","subscribers_url":"https://api.github.com/repos/zestedesavoir/zds-site/subscribers","subscription_url":"https://api.github.com/repos/zestedesavoir/zds-site/subscription","commits_url":"https://api.github.com/repos/zestedesavoir/zds-site/commits{/sha}","git_commits_url":"https://api.github.com/repos/zestedesavoir/zds-site/git/commits{/sha}","comments_url":"https://api.github.com/repos/zestedesavoir/zds-site/comments{/number}","issue_comment_url":"https://api.github.com/repos/zestedesavoir/zds-site/issues/comments{/number}","contents_url":"https://api.github.com/repos/zestedesavoir/zds-site/contents/{+path}","compare_url":"https://api.github.com/repos/zestedesavoir/zds-site/compare/{base}...{head}","merges_url":"https://api.github.com/repos/zestedesavoir/zds-site/merges","archive_url":"https://api.github.com/repos/zestedesavoir/zds-site/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/zestedesavoir/zds-site/downloads","issues_url":"https://api.github.com/repos/zestedesavoir/zds-site/issues{/number}","pulls_url":"https://api.github.com/repos/zestedesavoir/zds-site/pulls{/number}","milestones_url":"https://api.github.com/repos/zestedesavoir/zds-site/milestones{/number}","notifications_url":"https://api.github.com/repos/zestedesavoir/zds-site/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/zestedesavoir/zds-site/labels{/name}","releases_url":"https://api.github.com/repos/zestedesavoir/zds-site/releases{/id}","created_at":"2013-11-28T14:23:48Z","updated_at":"2015-04-14T19:49:20Z","pushed_at":"2015-04-15T11:54:59Z","git_url":"git://github.com/zestedesavoir/zds-site.git","ssh_url":"git@github.com:zestedesavoir/zds-site.git","clone_url":"https://github.com/zestedesavoir/zds-site.git","svn_url":"https://github.com/zestedesavoir/zds-site","homepage":null,"size":164062,"stargazers_count":90,"watchers_count":90,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":82,"mirror_url":null,"open_issues_count":231,"forks":82,"open_issues":231,"watchers":90,"default_branch":"dev"}},"_links":{"self":{"href":"https://api.github.com/repos/zestedesavoir/zds-site/pulls/2505"},"html":{"href":"https://github.com/zestedesavoir/zds-site/pull/2505"},"issue":{"href":"https://api.github.com/repos/zestedesavoir/zds-site/issues/2505"},"comments":{"href":"https://api.github.com/repos/zestedesavoir/zds-site/issues/2505/comments"},"review_comments":{"href":"https://api.github.com/repos/zestedesavoir/zds-site/pulls/2505/comments"},"review_comment":{"href":"https://api.github.com/repos/zestedesavoir/zds-site/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/zestedesavoir/zds-site/pulls/2505/commits"},"statuses":{"href":"https://api.github.com/repos/zestedesavoir/zds-site/statuses/de116ce1778f2e03611877f0c96232ea11faa265"}}}}