diff options
Diffstat (limited to 'tbc')
-rw-r--r-- | tbc/admin.py | 2 | ||||
-rw-r--r-- | tbc/forms.py | 2 | ||||
-rw-r--r-- | tbc/models.py | 20 | ||||
-rw-r--r-- | tbc/static/js/hitcount-jquery.js | 60 | ||||
-rw-r--r-- | tbc/static/js/jquery.postcsrf.js | 59 | ||||
-rw-r--r-- | tbc/templates/tbc/book-details.html | 24 | ||||
-rw-r--r-- | tbc/urls.py | 107 | ||||
-rw-r--r-- | tbc/views.py | 14 |
8 files changed, 217 insertions, 71 deletions
diff --git a/tbc/admin.py b/tbc/admin.py index 30b5b34..4707d33 100644 --- a/tbc/admin.py +++ b/tbc/admin.py @@ -1,4 +1,4 @@ -from models import * +from .models import * from django.contrib import admin admin.site.register(Profile) diff --git a/tbc/forms.py b/tbc/forms.py index aa3b477..effe45b 100644 --- a/tbc/forms.py +++ b/tbc/forms.py @@ -16,7 +16,7 @@ class UserProfileForm(forms.ModelForm): self.fields['about_proj'].label = "How did you come to know about the project" class Meta: model = Profile - exclude = ('user') + exclude = ('user',) widgets = { 'about':forms.TextInput(attrs={'placeholder':'Tell us about yourself'}), 'dob':forms.TextInput(attrs={'placeholder':'mm/dd/yyyy'}), diff --git a/tbc/models.py b/tbc/models.py index 7deb31c..9b2adbf 100644 --- a/tbc/models.py +++ b/tbc/models.py @@ -2,7 +2,7 @@ from django.db import models from django.contrib.auth.models import User from PythonTBC import settings from django.contrib.admin.models import LogEntry -from local import sitemap_path +from .local import sitemap_path from taggit.managers import TaggableManager CATEGORY = (("fluid mechanics", "Fluid Mechanics"), @@ -82,7 +82,7 @@ class Profile(models.Model): about_proj = models.CharField(max_length=50, choices=ABOUT_PROJ) city = models.CharField(max_length=50, default=None) state = models.CharField(max_length=50, default=None) - pin_code = models.IntegerField(max_length=6, default=None) + pin_code = models.IntegerField(default=None) def __unicode__(self): name = self.user.first_name or 'Profile' return '%s'%(name) @@ -103,7 +103,7 @@ class Book(models.Model): isbn = models.CharField(max_length=50) edition = models.CharField(max_length=15) year_of_pub = models.CharField(max_length=4) - no_chapters = models.IntegerField(max_length=2, default=0, blank=True) + no_chapters = models.IntegerField(default=0, blank=True) contributor = models.ForeignKey(Profile) reviewer = models.ForeignKey(Reviewer) approved = models.BooleanField(default=False) @@ -144,7 +144,7 @@ class TempBook(models.Model): isbn = models.CharField(max_length=50) edition = models.CharField(max_length=15) year_of_pub = models.CharField(max_length=4) - no_chapters = models.IntegerField(max_length=2) + no_chapters = models.IntegerField() def __unicode__(self): name = self.title or 'Book' return '%s'%(name) @@ -177,12 +177,12 @@ class ActivityLog(LogEntry): class AicteBook(models.Model): title = models.TextField() - author = models.CharField(max_length=300L) - category = models.CharField(max_length=32L) - publisher_place = models.CharField(max_length=200L) - isbn = models.CharField(max_length=50L) - edition = models.CharField(max_length=15L) - year_of_pub = models.CharField(max_length=4L) + author = models.CharField(max_length=300) + category = models.CharField(max_length=32) + publisher_place = models.CharField(max_length=200) + isbn = models.CharField(max_length=50) + edition = models.CharField(max_length=15) + year_of_pub = models.CharField(max_length=4) proposed = models.BooleanField(default=False) def __unicode__(self): notebook = self.title or 'Book' diff --git a/tbc/static/js/hitcount-jquery.js b/tbc/static/js/hitcount-jquery.js new file mode 100644 index 0000000..e7106b3 --- /dev/null +++ b/tbc/static/js/hitcount-jquery.js @@ -0,0 +1,60 @@ +$(document).ready(function() { + /** + * https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax + * + * Remember you will need to ensure csrf tokens by adding: + * @ensure_csrf_cookie to your views that require this javascript + * + * Also, you will probably want to include this with your other sitewide + * javascript files ... this is just an example. + */ + + if ( typeof hitcountJS === 'undefined' ) { + // since this is loaded on every page only do something + // if a hit is going to be counted + return; + } + + var hitcountPK = hitcountJS['hitcountPK']; + var hitcountURL = hitcountJS['hitcountURL']; + var csrftoken = getCookie('csrftoken'); + + $.ajaxSetup({ + beforeSend: function(xhr, settings) { + if (!csrfSafeMethod(settings.type) && !this.crossDomain) { + xhr.setRequestHeader("X-CSRFToken", csrftoken); + } + } + }); + + $.post( hitcountURL, { "hitcountPK" : hitcountPK }, + function(data, status) { + + console.log(data); // just so you can see the response + + if (data.status == 'error') { + // do something for error? + } + }, 'json'); +}); + +function getCookie(name) { + var cookieValue = null; + if (document.cookie && document.cookie != '') { + var cookies = document.cookie.split(';'); + for (var i = 0; i < cookies.length; i++) { + var cookie = jQuery.trim(cookies[i]); + // Does this cookie string begin with the name we want? + if (cookie.substring(0, name.length + 1) == (name + '=')) { + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); + break; + } + } + } + return cookieValue; +} + +function csrfSafeMethod(method) { + // these HTTP methods do not require CSRF protection + return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); +} diff --git a/tbc/static/js/jquery.postcsrf.js b/tbc/static/js/jquery.postcsrf.js new file mode 100644 index 0000000..911626a --- /dev/null +++ b/tbc/static/js/jquery.postcsrf.js @@ -0,0 +1,59 @@ +/** + * Wrapper for jQuery's $.post() that retrieves the CSRF token from the browser + * cookie and sets then sets "X-CSRFToken" header in one fell swoop. + * + * Based on the example code given at the Django docs: + * https://docs.djangoproject.com/en/1.9/ref/csrf/#ajax + * + * Use as you would $.post(). + */ + +(function($) { + + $.postCSRF = function(url, data, callback, type) { + + function csrfSafeMethod(method) { + // these HTTP methods do not require CSRF protection + return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); + } + + function getCookie(name) { + var cookieValue = null; + if (document.cookie && document.cookie !== '') { + var cookies = document.cookie.split(';'); + for (var i = 0; i < cookies.length; i++) { + var cookie = jQuery.trim(cookies[i]); + // Does this cookie string begin with the name we want? + if (cookie.substring(0, name.length + 1) == (name + '=')) { + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); + break; + } + } + } + return cookieValue; + } + + var csrftoken = getCookie('csrftoken'); + + // shift arguments if data argument was omitted + if ($.isFunction(data)) { + type = type || callback; + callback = data; + data = undefined; + } + + return $.ajax(jQuery.extend({ + url: url, + type: "POST", + dataType: type, + data: data, + success: callback, + beforeSend: function(xhr, settings) { + if (!csrfSafeMethod(settings.type) && !this.crossDomain) { + xhr.setRequestHeader("X-CSRFToken", csrftoken); + } + } + }, jQuery.isPlainObject(url) && url)); + }; + +}(jQuery)); diff --git a/tbc/templates/tbc/book-details.html b/tbc/templates/tbc/book-details.html index fc67847..579b2db 100644 --- a/tbc/templates/tbc/book-details.html +++ b/tbc/templates/tbc/book-details.html @@ -2,6 +2,24 @@ {% load static %} {% block script %} +{% load staticfiles %} +<script src="{% static 'js/jquery.postcsrf.js' %}"></script> + +{% load hitcount_tags %} +{% get_hit_count_js_variables for book as hitcount %} +<script type="text/javascript"> +jQuery(document).ready(function($) { + // use the template tags in our JavaScript call + $.postCSRF("{{ hitcount.ajax_url }}", { hitcountPK : "{{ hitcount.pk }}" }) + .done(function(data){ + $('<i />').text(data.hit_counted).attr('id','hit-counted-value').appendTo('#hit-counted'); + $('#hit-response').text(data.hit_message); + }).fail(function(data){ + console.log('POST failed'); + console.log(data); + }); +}); +</script> <script> function redirectToIpynb(notebook) { @@ -50,6 +68,7 @@ function redirectToIpynb(notebook) <tr> <td>Author: </td> <td>{{ book.author }}</td> + </tr> <tr> <td>Publisher: </td> @@ -79,7 +98,12 @@ function redirectToIpynb(notebook) <td>GitHub: </td> <td><a href= 'https://github.com/FOSSEE/Python-Textbook-Companions/tree/master/{{ book.title.split|join:"_" }}_by_{{ book.author.split|join:"_" }}' target="_blank">{{ book.title }}</a></td> </tr> +<!--<tr> + <td>Page Hits: </td> +<td>{% get_hit_count for book %}</td> +</tr> +--> </table> </div> diff --git a/tbc/urls.py b/tbc/urls.py index 3db075b..4177f2f 100644 --- a/tbc/urls.py +++ b/tbc/urls.py @@ -1,61 +1,64 @@ from django.conf.urls import patterns, include, url +from django.conf import settings +from django.conf.urls.static import static +from django.contrib import admin +import tbc.views - -urlpatterns = patterns('', - url(r'^$', 'tbc.views.home', name='home'), - url(r'^internship-forms/$', 'tbc.views.internship_forms', name='internship_forms'), - url(r'^about-pythontbc/$', 'tbc.views.about_pytbc', name='about_pytbc'), +urlpatterns = [ + url(r'^$', tbc.views.home, name='home'), + url(r'^internship-forms/$', tbc.views.internship_forms, name='internship_forms'), + url(r'^about-pythontbc/$', tbc.views.about_pytbc, name='about_pytbc'), - url(r'^sample-notebook/$', 'tbc.views.sample_ipynb', name='sample_ipynb'), - url(r'^register/$', 'tbc.views.user_register', name='user_register'), - url(r'^login/$', 'tbc.views.user_login', name='user_login'), - url(r'^logout/$', 'tbc.views.user_logout', name='user_logout'), - url(r'^profile/$', 'tbc.views.user_profile', name='user_profile'), - url(r'^update-profile/$', 'tbc.views.update_profile', name='update_profile'), - url(r'^forgot-password/$', 'tbc.views.forgot_password', name='forgot_password'), - url(r'^update-password/$', 'tbc.views.update_password', name='update_password'), - url(r'^admin-tools/$', 'tbc.views.admin_tools', name='admin_tools'), + url(r'^sample-notebook/$', tbc.views.sample_ipynb, name='sample_ipynb'), + url(r'^register/$', tbc.views.user_register, name='user_register'), + url(r'^login/$', tbc.views.user_login, name='user_login'), + url(r'^logout/$', tbc.views.user_logout, name='user_logout'), + url(r'^profile/$', tbc.views.user_profile, name='user_profile'), + url(r'^update-profile/$', tbc.views.update_profile, name='update_profile'), + url(r'^forgot-password/$', tbc.views.forgot_password, name='forgot_password'), + url(r'^update-password/$', tbc.views.update_password, name='update_password'), + url(r'^admin-tools/$', tbc.views.admin_tools, name='admin_tools'), - url(r'^submit-proposal/$', 'tbc.views.submit_proposal', name='submit_proposal'), - url(r'^submit-aicte-proposal/$', 'tbc.views.list_aicte', name='list_aicte'), - url(r'^submit-aicte-proposal/(?P<aicte_book_id>\d+)/$', 'tbc.views.submit_aicte_proposal', name='submit_aicte_proposal'), - url(r'^submit-book/$', 'tbc.views.submit_book', name='submit_book'), - url(r'^submit-sample/$', 'tbc.views.submit_sample', name='submit_sample'), - url(r'^submit-sample/(?P<proposal_id>\d+)$', 'tbc.views.submit_sample', name='submit_sample'), - url(r'^submit-sample/(?P<proposal_id>\d+)/(?P<old_notebook_id>\d+)$', 'tbc.views.submit_sample', name='submit_sample'), - url(r'^confirm-book-details/$', 'tbc.views.confirm_book_details', name='confirm_book_details'), - url(r'^submit-book-old/$', 'tbc.views.submit_book', name='submit_book'), - url(r'^submit-code/$', 'tbc.views.submit_code', name='submit_code'), - url(r'^submit-code-old/(?P<book_id>\d+)$', 'tbc.views.submit_code_old', name='submit_code_old'), - url(r'^update-content/(?P<book_id>\d+)$', 'tbc.views.update_content', name='update_content'), - url(r'^get-zip/(?P<book_id>\d+)$', 'tbc.views.get_zip', name='get_zip'), - url(r'^browse-books/$', 'tbc.views.browse_books', name='browse_books'), - url(r'^browse-books/(?P<category>.+)$', 'tbc.views.browse_books', name='browse_books'), - url(r'^convert-notebook/(?P<notebook_path>.+)$', 'tbc.views.convert_notebook', name='convert_notebook'), - url(r'^book-details/(?P<book_id>\d+)/$', 'tbc.views.book_details', name='book_details'), - url(r'^completed-books/$', 'tbc.views.completed_books', name='completed_books'), - url(r'^completed-books/(?P<category>.+)$', 'tbc.views.completed_books', name='completed_books'), - url(r'^books-under-progress/$', 'tbc.views.books_under_progress', name='books_under_progress'), - url(r'^redirect-ipynb/(?P<notebook_path>.+)$', 'tbc.views.redirect_to_ipynb', name='redirect_to_ipynb'), - url(r'^get-certificate/$', 'tbc.views.get_certificate', name='get_certificate'), - url(r'^get-certificate/(?P<book_id>\d+)/$', 'tbc.views.get_certificate', name='get_certificate'), + url(r'^submit-proposal/$', tbc.views.submit_proposal, name='submit_proposal'), + url(r'^submit-aicte-proposal/$', tbc.views.list_aicte, name='list_aicte'), + url(r'^submit-aicte-proposal/(?P<aicte_book_id>\d+)/$', tbc.views.submit_aicte_proposal, name='submit_aicte_proposal'), + url(r'^submit-book/$', tbc.views.submit_book, name='submit_book'), + url(r'^submit-sample/$', tbc.views.submit_sample, name='submit_sample'), + url(r'^submit-sample/(?P<proposal_id>\d+)$', tbc.views.submit_sample, name='submit_sample'), + url(r'^submit-sample/(?P<proposal_id>\d+)/(?P<old_notebook_id>\d+)$', tbc.views.submit_sample, name='submit_sample'), + url(r'^confirm-book-details/$', tbc.views.confirm_book_details, name='confirm_book_details'), + url(r'^submit-book-old/$', tbc.views.submit_book, name='submit_book'), + url(r'^submit-code/$', tbc.views.submit_code, name='submit_code'), + url(r'^submit-code-old/(?P<book_id>\d+)$', tbc.views.submit_code_old, name='submit_code_old'), + url(r'^update-content/(?P<book_id>\d+)$', tbc.views.update_content, name='update_content'), + url(r'^get-zip/(?P<book_id>\d+)$', tbc.views.get_zip, name='get_zip'), + url(r'^browse-books/$', tbc.views.browse_books, name='browse_books'), + url(r'^browse-books/(?P<category>.+)$', tbc.views.browse_books, name='browse_books'), + url(r'^convert-notebook/(?P<notebook_path>.+)$', tbc.views.convert_notebook, name='convert_notebook'), + url(r'^book-details/(?P<book_id>\d+)/$', tbc.views.book_details, name='book_details'), + url(r'^completed-books/$', tbc.views.completed_books, name='completed_books'), + url(r'^completed-books/(?P<category>.+)$', tbc.views.completed_books, name='completed_books'), + url(r'^books-under-progress/$', tbc.views.books_under_progress, name='books_under_progress'), + url(r'^redirect-ipynb/(?P<notebook_path>.+)$', tbc.views.redirect_to_ipynb, name='redirect_to_ipynb'), + url(r'^get-certificate/$', tbc.views.get_certificate, name='get_certificate'), + url(r'^get-certificate/(?P<book_id>\d+)/$', tbc.views.get_certificate, name='get_certificate'), - url(r'^book-review/$', 'tbc.views.book_review', name='book_review'), - url(r'^proposal-review/$', 'tbc.views.review_proposals', name='review_proposals'), - url(r'^proposal-review/(?P<proposal_id>\d+)/(?P<textbook_id>\d+)$', 'tbc.views.review_proposals', name='review_proposals'), - url(r'^disapprove-sample-notebook/(?P<proposal_id>\d+)$', 'tbc.views.disapprove_proposal', name='disapprove_proposal'), - url(r'^allot-book/(?P<proposal_id>\d+)$', 'tbc.views.allot_book', name='allot_book'), - url(r'^reject-proposal/(?P<proposal_id>\d+)$', 'tbc.views.reject_proposal', name='reject_proposal'), - url(r'^book-review/(?P<book_id>\d+)$', 'tbc.views.book_review', name='book_review'), - url(r'^approve-book/(?P<book_id>\d+)$', 'tbc.views.approve_book', name='approve_book'), - url(r'^notify-changes/(?P<book_id>\d+)$', 'tbc.views.notify_changes', name='notify_changes'), - url(r'^brokenbooks/$', 'tbc.views.get_broken_books', name='broken_books'), - url(r'^link-image/$', 'tbc.views.link_image', name='link_image'), - url(r'^books/$', 'tbc.views.books', name='books'), - url(r'^edit-book/(?P<book_id>\d+)/$', 'tbc.views.edit_book', name='edit_book'), + url(r'^book-review/$', tbc.views.book_review, name='book_review'), + url(r'^proposal-review/$', tbc.views.review_proposals, name='review_proposals'), + url(r'^proposal-review/(?P<proposal_id>\d+)/(?P<textbook_id>\d+)$', tbc.views.review_proposals, name='review_proposals'), + url(r'^disapprove-sample-notebook/(?P<proposal_id>\d+)$', tbc.views.disapprove_proposal, name='disapprove_proposal'), + url(r'^allot-book/(?P<proposal_id>\d+)$', tbc.views.allot_book, name='allot_book'), + url(r'^reject-proposal/(?P<proposal_id>\d+)$', tbc.views.reject_proposal, name='reject_proposal'), + url(r'^book-review/(?P<book_id>\d+)$', tbc.views.book_review, name='book_review'), + url(r'^approve-book/(?P<book_id>\d+)$', tbc.views.approve_book, name='approve_book'), + url(r'^notify-changes/(?P<book_id>\d+)$', tbc.views.notify_changes, name='notify_changes'), + url(r'^brokenbooks/$', tbc.views.get_broken_books, name='broken_books'), + url(r'^link-image/$', tbc.views.link_image, name='link_image'), + url(r'^books/$', tbc.views.books, name='books'), + url(r'^edit-book/(?P<book_id>\d+)/$', tbc.views.edit_book, name='edit_book'), # ajax urls - url(r'^ajax/matching-books/$', 'tbc.views.ajax_matching_books', name='AjaxMatchingBooks'), + url(r'^ajax/matching-books/$', tbc.views.ajax_matching_books, name='AjaxMatchingBooks'), -) +] diff --git a/tbc/views.py b/tbc/views.py index d14093e..52a9478 100644 --- a/tbc/views.py +++ b/tbc/views.py @@ -3,17 +3,17 @@ from django.contrib.contenttypes.models import ContentType from django.http import HttpResponse, HttpResponseRedirect, Http404 from django.shortcuts import render_to_response, redirect from django.views.decorators.csrf import csrf_exempt -from django.core.context_processors import csrf +from django.template.context_processors import csrf from django.contrib.auth import authenticate, login, logout from django.contrib.admin.models import CHANGE from django.contrib.auth.decorators import login_required from django.template import RequestContext -from models import * +from .models import * from tbc.forms import * -import local +from . import local import os import zipfile -import StringIO +import io import smtplib import shutil import string @@ -21,7 +21,7 @@ import random import json import subprocess from email.mime.text import MIMEText - +import StringIO def add_log(user, object, flag, message, proposal_id=None, chat='No message'): '''Creates log entry of the user activities.''' @@ -1049,7 +1049,7 @@ def generate_zip(book_id): def get_zip(request, book_id=None): user = request.user s, zipfile_name = generate_zip(book_id) - resp = HttpResponse(s.getvalue(), mimetype = "application/x-zip-compressed") + resp = HttpResponse(s.getvalue(), content_type = "application/x-zip-compressed") resp['Content-Disposition'] = 'attachment; filename=%s' % zipfile_name return resp @@ -1362,7 +1362,7 @@ def get_certificate(request, book_id=None): else: error = True add_log(user, book, CHANGE, err, proposal_id) - except Exception, e: + except Exception as e: error = True add_log(user, book, CHANGE, e, proposal_id) |