1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-10 19:29:56 +00:00

[views] moved some functions from views/__init__.py to views/__ajax__.py

This commit is contained in:
llj
2014-04-28 17:18:41 +08:00
parent d4afde0d3f
commit 4d9ba15cfc
5 changed files with 204 additions and 205 deletions

View File

@@ -69,7 +69,7 @@ $(".cancel-share").click(function() {
function repoCreateSuccessCallback() { function repoCreateSuccessCallback() {
location.reload(); location.reload();
} }
{% url 'seahub.views.public_repo_create' as repo_create_url %} {% url 'public_repo_create' as repo_create_url %}
{% with post_url=repo_create_url %} {% with post_url=repo_create_url %}
{% include "snippets/repo_create_js.html" %} {% include "snippets/repo_create_js.html" %}
{% endwith %} {% endwith %}

View File

@@ -4,7 +4,7 @@
function reqEvents(start) { function reqEvents(start) {
$('#events-loading').removeClass('hide'); $('#events-loading').removeClass('hide');
$.ajax({ $.ajax({
url:'{{SITE_ROOT}}events/?start=' + start{% if org %} + '&org_id={{ org.org_id }}'{% endif %}, url:'{% url 'events' %}?start=' + start{% if org %} + '&org_id={{ org.org_id }}'{% endif %},
dataType: 'json', dataType: 'json',
cache: false, cache: false,
success: function(data) { success: function(data) {

View File

@@ -57,7 +57,6 @@ urlpatterns = patterns('',
# url(r'^home/public/reply/(?P<msg_id>[\d]+)/$', innerpub_msg_reply, name='innerpub_msg_reply'), # url(r'^home/public/reply/(?P<msg_id>[\d]+)/$', innerpub_msg_reply, name='innerpub_msg_reply'),
# url(r'^home/owner/(?P<owner_name>[^/]+)/$', ownerhome, name='ownerhome'), # url(r'^home/owner/(?P<owner_name>[^/]+)/$', ownerhome, name='ownerhome'),
(r'^repo/create/$', repo_create),
(r'^repo/upload_check/$', validate_filename), (r'^repo/upload_check/$', validate_filename),
url(r'^repo/unsetinnerpub/(?P<repo_id>[-0-9a-f]{36})/$', unsetinnerpub, name='unsetinnerpub'), url(r'^repo/unsetinnerpub/(?P<repo_id>[-0-9a-f]{36})/$', unsetinnerpub, name='unsetinnerpub'),
url(r'^repo/set_password/$', repo_set_password, name="repo_set_password"), url(r'^repo/set_password/$', repo_set_password, name="repo_set_password"),
@@ -74,7 +73,6 @@ urlpatterns = patterns('',
url(r'^repo/history/view/(?P<repo_id>[-0-9a-f]{36})/$', repo_history_view, name='repo_history_view'), url(r'^repo/history/view/(?P<repo_id>[-0-9a-f]{36})/$', repo_history_view, name='repo_history_view'),
url(r'^repo/recycle/(?P<repo_id>[-0-9a-f]{36})/$', repo_recycle_view, name='repo_recycle_view'), url(r'^repo/recycle/(?P<repo_id>[-0-9a-f]{36})/$', repo_recycle_view, name='repo_recycle_view'),
url(r'^repo/snapshot/view/(?P<repo_id>[-0-9a-f]{36})/$', repo_view_snapshot, name='repo_view_snapshot'), url(r'^repo/snapshot/view/(?P<repo_id>[-0-9a-f]{36})/$', repo_view_snapshot, name='repo_view_snapshot'),
url(r'^repo/history/changes/(?P<repo_id>[-0-9a-f]{36})/$', repo_history_changes, name='repo_history_changes'),
url(r'^repo/(?P<repo_id>[-0-9a-f]{36})/files/$', view_file, name="repo_view_file"), url(r'^repo/(?P<repo_id>[-0-9a-f]{36})/files/$', view_file, name="repo_view_file"),
url(r'^repo/(?P<repo_id>[-0-9a-f]{36})/history/files/$', view_history_file, name="view_history_file"), url(r'^repo/(?P<repo_id>[-0-9a-f]{36})/history/files/$', view_history_file, name="view_history_file"),
url(r'^repo/(?P<repo_id>[-0-9a-f]{36})/trash/files/$', view_trash_file, name="view_trash_file"), url(r'^repo/(?P<repo_id>[-0-9a-f]{36})/trash/files/$', view_trash_file, name="view_trash_file"),
@@ -100,7 +98,6 @@ urlpatterns = patterns('',
(r'^file_upload_progress_page/$', file_upload_progress_page), (r'^file_upload_progress_page/$', file_upload_progress_page),
url(r'^activities/$', activities, name='activities'), url(r'^activities/$', activities, name='activities'),
url(r'^starred/$', starred, name='starred'), url(r'^starred/$', starred, name='starred'),
(r'^events/$', events), # ajax
(r'^pdf_full_view/$', pdf_full_view), (r'^pdf_full_view/$', pdf_full_view),
url(r'^i18n/$', i18n, name='i18n'), url(r'^i18n/$', i18n, name='i18n'),
(r'^download/repo/$', repo_download), (r'^download/repo/$', repo_download),
@@ -113,6 +110,7 @@ urlpatterns = patterns('',
url(r'^download_client_program/$', TemplateView.as_view(template_name="download.html"), name="download_client"), url(r'^download_client_program/$', TemplateView.as_view(template_name="download.html"), name="download_client"),
### Ajax ### ### Ajax ###
url(r'^ajax/repo/create/$', repo_create, name="repo_create"),
(r'^ajax/repo/(?P<repo_id>[-0-9a-f]{36})/remove/$', repo_remove), (r'^ajax/repo/(?P<repo_id>[-0-9a-f]{36})/remove/$', repo_remove),
url(r'^ajax/repo/(?P<repo_id>[-0-9a-f]{36})/dirents/$', get_dirents, name="get_dirents"), url(r'^ajax/repo/(?P<repo_id>[-0-9a-f]{36})/dirents/$', get_dirents, name="get_dirents"),
@@ -142,6 +140,7 @@ urlpatterns = patterns('',
url(r'^ajax/repo/(?P<repo_id>[-0-9a-f]{36})/file/unstar/$', repo_unstar_file, name='repo_unstar_file'), url(r'^ajax/repo/(?P<repo_id>[-0-9a-f]{36})/file/unstar/$', repo_unstar_file, name='repo_unstar_file'),
url(r'^ajax/repo/(?P<repo_id>[-0-9a-f]{36})/current_commit/$', get_current_commit, name='get_current_commit'), url(r'^ajax/repo/(?P<repo_id>[-0-9a-f]{36})/current_commit/$', get_current_commit, name='get_current_commit'),
url(r'^ajax/repo/(?P<repo_id>[-0-9a-f]{36})/history/changes/$', repo_history_changes, name='repo_history_changes'),
url(r'^ajax/repo/(?P<repo_id>[-0-9a-f]{36})/encrypted_file/(?P<file_id>[0-9a-f]{40})/download/$', download_enc_file, name='download_enc_file'), url(r'^ajax/repo/(?P<repo_id>[-0-9a-f]{36})/encrypted_file/(?P<file_id>[0-9a-f]{40})/download/$', download_enc_file, name='download_enc_file'),
@@ -157,6 +156,8 @@ urlpatterns = patterns('',
url(r'^ajax/space_and_traffic/$', space_and_traffic, name='space_and_traffic'), url(r'^ajax/space_and_traffic/$', space_and_traffic, name='space_and_traffic'),
url(r'^ajax/my-shared-and-group-repos/$', my_shared_and_group_repos, name='my_shared_and_group_repos'), url(r'^ajax/my-shared-and-group-repos/$', my_shared_and_group_repos, name='my_shared_and_group_repos'),
url(r'^ajax/events/$', events, name="events"),
### Apps ### ### Apps ###
(r'^api2/', include('seahub.api2.urls')), (r'^api2/', include('seahub.api2.urls')),
(r'^avatar/', include('seahub.avatar.urls')), (r'^avatar/', include('seahub.avatar.urls')),
@@ -213,7 +214,7 @@ if getattr(settings, 'CLOUD_MODE', False):
else: else:
urlpatterns += patterns('', urlpatterns += patterns('',
url(r'^pubinfo/libraries/$', pubrepo, name='pubrepo'), url(r'^pubinfo/libraries/$', pubrepo, name='pubrepo'),
(r'^publicrepo/create/$', public_repo_create), url(r'^ajax/publicrepo/create/$', public_repo_create, name='public_repo_create'),
url(r'^pubinfo/groups/$', pubgrp, name='pubgrp'), url(r'^pubinfo/groups/$', pubgrp, name='pubgrp'),
url(r'^pubinfo/users/$', pubuser, name='pubuser'), url(r'^pubinfo/users/$', pubuser, name='pubuser'),
) )

View File

@@ -72,8 +72,7 @@ from seahub.notifications.models import UserNotification
from seahub.options.models import UserOptions, CryptoOptionNotSetError from seahub.options.models import UserOptions, CryptoOptionNotSetError
from seahub.profile.models import Profile from seahub.profile.models import Profile
from seahub.share.models import FileShare, PrivateFileDirShare, UploadLinkShare from seahub.share.models import FileShare, PrivateFileDirShare, UploadLinkShare
from seahub.forms import AddUserForm, RepoCreateForm, \ from seahub.forms import AddUserForm, RepoPassowrdForm, \
RepoPassowrdForm, SharedRepoCreateForm,\
SetUserQuotaForm, RepoSettingForm, SharedLinkPasswordForm SetUserQuotaForm, RepoSettingForm, SharedLinkPasswordForm
from seahub.signals import repo_created, repo_deleted from seahub.signals import repo_created, repo_deleted
from seahub.utils import render_permission_error, render_error, list_to_string, \ from seahub.utils import render_permission_error, render_error, list_to_string, \
@@ -865,53 +864,6 @@ def get_diff(repo_id, arg1, arg2):
return lists return lists
@login_required
def repo_history_changes(request, repo_id):
if not request.is_ajax():
return Http404
changes = {}
content_type = 'application/json; charset=utf-8'
if not access_to_repo(request, repo_id, ''):
return HttpResponse(json.dumps(changes), content_type=content_type)
repo = get_repo(repo_id)
if not repo:
return HttpResponse(json.dumps(changes), content_type=content_type)
username = request.user.username
try:
server_crypto = UserOptions.objects.is_server_crypto(username)
except CryptoOptionNotSetError:
# Assume server_crypto is ``False`` if this option is not set.
server_crypto = False
if repo.encrypted and \
(repo.enc_version == 1 or (repo.enc_version == 2 and server_crypto)) \
and not is_passwd_set(repo_id, username):
return HttpResponse(json.dumps(changes), content_type=content_type)
commit_id = request.GET.get('commit_id', '')
if not commit_id:
return HttpResponse(json.dumps(changes), content_type=content_type)
changes = get_diff(repo_id, '', commit_id)
c = get_commit(repo.id, repo.version, commit_id)
if c.parent_id is None:
# A commit is a first commit only if it's parent id is None.
changes['cmt_desc'] = repo.desc
elif c.second_parent_id is None:
# Normal commit only has one parent.
if c.desc.startswith('Changed library'):
changes['cmt_desc'] = _('Changed library name or description')
else:
# A commit is a merge only if it has two parents.
changes['cmt_desc'] = _('No conflict in the merge.')
return HttpResponse(json.dumps(changes), content_type=content_type)
@login_required @login_required
def modify_token(request, repo_id): def modify_token(request, repo_id):
if not validate_owner(request, repo_id): if not validate_owner(request, repo_id):
@@ -995,7 +947,7 @@ def myhome(request):
owned_repos = seafile_api.get_owned_repo_list(username) owned_repos = seafile_api.get_owned_repo_list(username)
calculate_repos_last_modify(owned_repos) calculate_repos_last_modify(owned_repos)
repo_create_url = reverse(repo_create) repo_create_url = reverse("repo_create")
return render_to_response('myhome.html', { return render_to_response('myhome.html', {
"owned_repos": owned_repos, "owned_repos": owned_repos,
@@ -1151,62 +1103,6 @@ def client_unsync(request):
# return HttpResponse(serialized_data, content_type=content_type) # return HttpResponse(serialized_data, content_type=content_type)
# else: # else:
# return HttpResponseBadRequest(content_type=content_type) # return HttpResponseBadRequest(content_type=content_type)
@login_required
def public_repo_create(request):
'''
Handle ajax post to create public repo.
'''
if not request.is_ajax() or request.method != 'POST':
return Http404
result = {}
content_type = 'application/json; charset=utf-8'
form = SharedRepoCreateForm(request.POST)
if not form.is_valid():
result['error'] = str(form.errors.values()[0])
return HttpResponseBadRequest(json.dumps(result),
content_type=content_type)
repo_name = form.cleaned_data['repo_name']
repo_desc = form.cleaned_data['repo_desc']
permission = form.cleaned_data['permission']
encryption = int(form.cleaned_data['encryption'])
uuid = form.cleaned_data['uuid']
magic_str = form.cleaned_data['magic_str']
encrypted_file_key = form.cleaned_data['encrypted_file_key']
user = request.user.username
try:
if not encryption:
repo_id = seafile_api.create_repo(repo_name, repo_desc, user, None)
else:
repo_id = seafile_api.create_enc_repo(uuid, repo_name, repo_desc, user, magic_str, encrypted_file_key, enc_version=2)
# set this repo as inner pub
seafile_api.add_inner_pub_repo(repo_id, permission)
#seafserv_threaded_rpc.set_inner_pub_repo(repo_id, permission)
except SearpcError as e:
repo_id = None
logger.error(e)
if not repo_id:
result['error'] = _(u'Internal Server Error')
return HttpResponse(json.dumps(result), status=500,
content_type=content_type)
else:
result['success'] = True
repo_created.send(sender=None,
org_id=-1,
creator=user,
repo_id=repo_id,
repo_name=repo_name)
return HttpResponse(json.dumps(result), content_type=content_type)
@login_required @login_required
def unsetinnerpub(request, repo_id): def unsetinnerpub(request, repo_id):
repo = get_repo(repo_id) repo = get_repo(repo_id)
@@ -1441,70 +1337,6 @@ def validate_filename(request):
content_type = 'application/json; charset=utf-8' content_type = 'application/json; charset=utf-8'
return HttpResponse(json.dumps(result), content_type=content_type) return HttpResponse(json.dumps(result), content_type=content_type)
@login_required
def repo_create(request):
'''
Handle ajax post to create a library.
'''
if not request.is_ajax() or request.method != 'POST':
return Http404
result = {}
content_type = 'application/json; charset=utf-8'
form = RepoCreateForm(request.POST)
if not form.is_valid():
result['error'] = str(form.errors.values()[0])
return HttpResponseBadRequest(json.dumps(result),
content_type=content_type)
repo_name = form.cleaned_data['repo_name']
repo_desc = form.cleaned_data['repo_desc']
encryption = int(form.cleaned_data['encryption'])
uuid = form.cleaned_data['uuid']
magic_str = form.cleaned_data['magic_str']
encrypted_file_key = form.cleaned_data['encrypted_file_key']
username = request.user.username
try:
if not encryption:
repo_id = seafile_api.create_repo(repo_name, repo_desc, username,
None)
else:
repo_id = seafile_api.create_enc_repo(
uuid, repo_name, repo_desc, username,
magic_str, encrypted_file_key, enc_version=2)
except SearpcError, e:
repo_id = None
if not repo_id:
result['error'] = _(u"Internal Server Error")
return HttpResponse(json.dumps(result), status=500,
content_type=content_type)
else:
try:
default_lib = (int(request.GET.get('default_lib', 0)) == 1)
except ValueError:
default_lib = False
if default_lib:
UserOptions.objects.set_default_repo(username, repo_id)
result = {
'repo_id': repo_id,
'repo_name': repo_name,
'repo_desc': repo_desc,
'repo_enc': encryption,
}
repo_created.send(sender=None,
org_id=-1,
creator=username,
repo_id=repo_id,
repo_name=repo_name)
return HttpResponse(json.dumps(result), content_type=content_type)
def render_file_revisions (request, repo_id): def render_file_revisions (request, repo_id):
"""List all history versions of a file.""" """List all history versions of a file."""
path = request.GET.get('p', '/') path = request.GET.get('p', '/')
@@ -1976,30 +1808,6 @@ def activities(request):
'new_start': start, 'new_start': start,
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))
@login_required
def events(request):
if not request.is_ajax():
raise Http404
events_count = 15
username = request.user.username
start = int(request.GET.get('start'))
if request.cloud_mode:
org_id = request.GET.get('org_id')
events, start = get_org_user_events(org_id, username, start, events_count)
else:
events, start = get_user_events(username, start, events_count)
events_more = True if len(events) == events_count else False
event_groups = group_events_data(events)
ctx = {'event_groups': event_groups}
html = render_to_string("snippets/events_body.html", ctx)
return HttpResponse(json.dumps({'html':html, 'events_more':events_more,
'new_start': start}),
content_type='application/json; charset=utf-8')
def group_events_data(events): def group_events_data(events):
""" """
Group events according to the date. Group events according to the date.

View File

@@ -20,21 +20,21 @@ from pysearpc import SearpcError
from seahub.auth.decorators import login_required from seahub.auth.decorators import login_required
from seahub.contacts.models import Contact from seahub.contacts.models import Contact
from seahub.forms import RepoNewDirentForm, RepoRenameDirentForm from seahub.forms import RepoNewDirentForm, RepoRenameDirentForm, \
RepoCreateForm, SharedRepoCreateForm
from seahub.options.models import UserOptions, CryptoOptionNotSetError from seahub.options.models import UserOptions, CryptoOptionNotSetError
from seahub.notifications.models import UserNotification from seahub.notifications.models import UserNotification
from seahub.signals import upload_file_successful from seahub.signals import upload_file_successful, repo_created, repo_deleted
from seahub.views import get_repo_dirents, validate_owner, \ from seahub.views import get_repo_dirents, validate_owner, \
check_repo_access_permission, get_unencry_rw_repos_by_user, \ check_repo_access_permission, get_unencry_rw_repos_by_user, \
get_system_default_repo_id get_system_default_repo_id, access_to_repo, get_diff, group_events_data
from seahub.views.repo import get_nav_path, get_fileshare, get_dir_share_link, \ from seahub.views.repo import get_nav_path, get_fileshare, get_dir_share_link, \
get_uploadlink, get_dir_shared_upload_link get_uploadlink, get_dir_shared_upload_link
import seahub.settings as settings import seahub.settings as settings
from seahub.signals import repo_deleted
from seahub.utils import check_filename_with_rename, EMPTY_SHA1, gen_block_get_url, \ from seahub.utils import check_filename_with_rename, EMPTY_SHA1, gen_block_get_url, \
check_and_get_org_by_repo, TRAFFIC_STATS_ENABLED, get_user_traffic_stat,\ check_and_get_org_by_repo, TRAFFIC_STATS_ENABLED, get_user_traffic_stat,\
new_merge_with_no_conflict, get_commit_before_new_merge, \ new_merge_with_no_conflict, get_commit_before_new_merge, \
get_repo_last_modify, gen_file_upload_url get_repo_last_modify, gen_file_upload_url, get_org_user_events, get_user_events
from seahub.utils.star import star_file, unstar_file from seahub.utils.star import star_file, unstar_file
# Get an instance of a logger # Get an instance of a logger
@@ -1464,3 +1464,193 @@ def get_file_op_url(request, repo_id):
url = gen_file_upload_url(token, op_type + '-aj') url = gen_file_upload_url(token, op_type + '-aj')
return HttpResponse(json.dumps({"url": url}), content_type=content_type) return HttpResponse(json.dumps({"url": url}), content_type=content_type)
@login_required
def repo_history_changes(request, repo_id):
if not request.is_ajax():
return Http404
changes = {}
content_type = 'application/json; charset=utf-8'
if not access_to_repo(request, repo_id, ''):
return HttpResponse(json.dumps(changes), content_type=content_type)
repo = get_repo(repo_id)
if not repo:
return HttpResponse(json.dumps(changes), content_type=content_type)
username = request.user.username
try:
server_crypto = UserOptions.objects.is_server_crypto(username)
except CryptoOptionNotSetError:
# Assume server_crypto is ``False`` if this option is not set.
server_crypto = False
if repo.encrypted and \
(repo.enc_version == 1 or (repo.enc_version == 2 and server_crypto)) \
and not is_passwd_set(repo_id, username):
return HttpResponse(json.dumps(changes), content_type=content_type)
commit_id = request.GET.get('commit_id', '')
if not commit_id:
return HttpResponse(json.dumps(changes), content_type=content_type)
changes = get_diff(repo_id, '', commit_id)
c = get_commit(repo.id, repo.version, commit_id)
if c.parent_id is None:
# A commit is a first commit only if it's parent id is None.
changes['cmt_desc'] = repo.desc
elif c.second_parent_id is None:
# Normal commit only has one parent.
if c.desc.startswith('Changed library'):
changes['cmt_desc'] = _('Changed library name or description')
else:
# A commit is a merge only if it has two parents.
changes['cmt_desc'] = _('No conflict in the merge.')
return HttpResponse(json.dumps(changes), content_type=content_type)
@login_required
def repo_create(request):
'''
Handle ajax post to create a library.
'''
if not request.is_ajax() or request.method != 'POST':
return Http404
result = {}
content_type = 'application/json; charset=utf-8'
form = RepoCreateForm(request.POST)
if not form.is_valid():
result['error'] = str(form.errors.values()[0])
return HttpResponseBadRequest(json.dumps(result),
content_type=content_type)
repo_name = form.cleaned_data['repo_name']
repo_desc = form.cleaned_data['repo_desc']
encryption = int(form.cleaned_data['encryption'])
uuid = form.cleaned_data['uuid']
magic_str = form.cleaned_data['magic_str']
encrypted_file_key = form.cleaned_data['encrypted_file_key']
username = request.user.username
try:
if not encryption:
repo_id = seafile_api.create_repo(repo_name, repo_desc, username,
None)
else:
repo_id = seafile_api.create_enc_repo(
uuid, repo_name, repo_desc, username,
magic_str, encrypted_file_key, enc_version=2)
except SearpcError, e:
repo_id = None
if not repo_id:
result['error'] = _(u"Internal Server Error")
return HttpResponse(json.dumps(result), status=500,
content_type=content_type)
try:
default_lib = (int(request.GET.get('default_lib', 0)) == 1)
except ValueError:
default_lib = False
if default_lib:
UserOptions.objects.set_default_repo(username, repo_id)
result = {
'repo_id': repo_id,
'repo_name': repo_name,
'repo_desc': repo_desc,
'repo_enc': encryption,
}
repo_created.send(sender=None,
org_id=-1,
creator=username,
repo_id=repo_id,
repo_name=repo_name)
return HttpResponse(json.dumps(result), content_type=content_type)
@login_required
def public_repo_create(request):
'''
Handle ajax post to create public repo.
'''
if not request.is_ajax() or request.method != 'POST':
return Http404
result = {}
content_type = 'application/json; charset=utf-8'
form = SharedRepoCreateForm(request.POST)
if not form.is_valid():
result['error'] = str(form.errors.values()[0])
return HttpResponseBadRequest(json.dumps(result),
content_type=content_type)
repo_name = form.cleaned_data['repo_name']
repo_desc = form.cleaned_data['repo_desc']
permission = form.cleaned_data['permission']
encryption = int(form.cleaned_data['encryption'])
uuid = form.cleaned_data['uuid']
magic_str = form.cleaned_data['magic_str']
encrypted_file_key = form.cleaned_data['encrypted_file_key']
user = request.user.username
try:
if not encryption:
repo_id = seafile_api.create_repo(repo_name, repo_desc, user, None)
else:
repo_id = seafile_api.create_enc_repo(uuid, repo_name, repo_desc, user, magic_str, encrypted_file_key, enc_version=2)
# set this repo as inner pub
seafile_api.add_inner_pub_repo(repo_id, permission)
#seafserv_threaded_rpc.set_inner_pub_repo(repo_id, permission)
except SearpcError as e:
repo_id = None
logger.error(e)
if not repo_id:
result['error'] = _(u'Internal Server Error')
return HttpResponse(json.dumps(result), status=500,
content_type=content_type)
result['success'] = True
repo_created.send(sender=None,
org_id=-1,
creator=user,
repo_id=repo_id,
repo_name=repo_name)
return HttpResponse(json.dumps(result), content_type=content_type)
@login_required
def events(request):
if not request.is_ajax():
raise Http404
events_count = 15
username = request.user.username
start = int(request.GET.get('start'))
if request.cloud_mode:
org_id = request.GET.get('org_id')
events, start = get_org_user_events(org_id, username, start, events_count)
else:
events, start = get_user_events(username, start, events_count)
events_more = True if len(events) == events_count else False
event_groups = group_events_data(events)
ctx = {'event_groups': event_groups}
html = render_to_string("snippets/events_body.html", ctx)
return HttpResponse(json.dumps({'html':html, 'events_more':events_more,
'new_start': start}),
content_type='application/json; charset=utf-8')