def anonymous_view(view): """Marks a view as an anonymous, meaning this view returns nothing specific to the logged in user. In order to enforce this, the user, session, and COOKIES attributes of the request are cleared along with some keys in META. Additionally it sets cache-control settings on the output of the page and sets request.anonymous = True, which can be used in templates.""" view = cache_control(public=True)(view) @wraps(view) def g(request, *args, **kwargs): request.anonymous = True request.COOKIES = { } request.user = AnonymousUser() if hasattr(request, "session"): request.session = { } for header in list(request.META.keys()): if header not in ( 'SERVER_NAME', 'SERVER_PORT', 'HTTPS', 'wsgi.url_scheme', 'SERVER_PROTOCOL', 'HTTP_HOST', 'REQUEST_METHOD', 'REQUEST_URI', 'DOCUMENT_URI', 'PATH_INFO', 'QUERY_STRING', 'CONTENT_LENGTH', 'CONTENT_TYPE', 'REMOTE_ADDR'): del request.META[header] # In order for the Django debug template context processor to work, we can't # clear REMOTE_ADDR. Clear it if {{debug}} would be false. The resulting page # should not be cached since it may depend on REMOTE_ADDR. if 'REMOTE_ADDR' in request.META and (not settings.DEBUG or request.META['REMOTE_ADDR'] not in settings.INTERNAL_IPS): del request.META['REMOTE_ADDR'] response = view(request, *args, **kwargs) response.csrf_processing_done = True # prevent generation of CSRF cookies return response return g
def api_cache_control(**kwargs): """ Adds cache headers to a view using our API cache header defaults. """ if settings.API_CACHE_ENABLED: directives = {"public": True, "max_age": settings.API_CACHE_TIME} else: directives = {"no_cache": True, "no_store": True, "must_revalidate": True} directives.update(kwargs) return cache_control(**directives)
def as_view(cls, **initkwargs): view = patched_view = super().as_view(**initkwargs) last_modified_evaluator = functools.lru_cache()(cls.last_modified) patched_view = last_modified(last_modified_evaluator)(patched_view) patched_view = cache_control(**cls.cache_control())(patched_view) patched_view = cache_page( None, key_prefix=last_modified_evaluator # will be used value of Cache-Control.max-age or default one )(patched_view) view = conditional(cls.cache_headers_allowed, patched_view)(view) @functools.wraps(cls.as_view) def logging_view(request, *args, **kwargs): request_logger.debug( "request_method: %(request_method)s, " "request_path: %(request_path)s, " "request_headers: %(request_headers)s, " "request_params: %(request_params)s, " "request_data: %(request_data)s, ", dict( request_method=request.method, request_path=request.path, request_headers=request.META, request_params=request.GET, request_data=request.POST, ), ) response = view(request, *args, **kwargs) response_logger.debug( "response_code: %(response_code)s, " "response_headers: %(response_headers)s, " "response_data: %(response_data)s", dict( response_code=response.status_code, response_headers=response.items(), response_data=response.content, ), ) return response return logging_view
def get_allow_handler(self): """ When cache_control is truthy and at least one cache_control_* value is set, wraps the base handler in the django.views.decorated.cache.cache_control() decorator. """ allow = super(CacheControl, self).get_allow_handler() if self.get_cache_control(): public = self.get_cache_control_public() no_cache = self.get_cache_control_no_cache() no_transform = self.get_cache_control_no_transform() must_revalidate = self.get_cache_control_must_revalidate() proxy_revalidate = self.get_cache_control_proxy_revalidate() max_age = self.get_cache_control_max_age() s_maxage = self.get_cache_control_s_maxage() controls = dict( ((("public", True,),) if public else () if public is None else (("private", True,),)) + ((("no_cache", True,),) if no_cache else ()) + ((("no_transform", True,),) if no_transform else ()) + ((("must_revalidate", True,),) if must_revalidate else ()) + ((("proxy_revalidate", True,),) if proxy_revalidate else ()) + ((("max_age", max_age,),) if max_age else ()) + ((("s_maxage", s_maxage,),) if s_maxage else ())) if controls: allow = cache.cache_control(**controls)(allow) return allow
def shared_cache_control(func=None, **kwargs): """ Decorator for view functions that defines the "Cache-Control" header for shared caches like CDN's. It's simply a thin wrapper around Django's cache-control that sets some defaults. By default, it does not permit use of the browser's cache without validation ("max-age=0"), and sets the caching period for shared caches ("s-maxage") based on the CACHE_CONTROL_DEFAULT_SHARED_MAX_AGE setting. All of the defaults can be overridden or extended via keyword arguments. """ # Set the default values. cc_kwargs = dict(public=True, max_age=0, s_maxage=settings.CACHE_CONTROL_DEFAULT_SHARED_MAX_AGE) # Override the default values and/or add new ones. cc_kwargs.update(kwargs) decorator = cache_control(**cc_kwargs) if not func: return decorator return decorator(func)
def anonymous_view(view): """Marks a view as an anonymous, meaning this view returns nothing specific to the logged in user. In order to enforce this, the user, session, and COOKIES attributes of the request are cleared along with some keys in META. Additionally it sets cache-control settings on the output of the page and sets request.anonymous = True, which can be used in templates.""" view = cache_control(public=True)(view) @wraps(view) def g(request, *args, **kwargs): request.anonymous = True request.COOKIES = { } request.user = AnonymousUser() if hasattr(request, "session"): request.session = { } for header in list(request.META.keys()): if header not in ('CONTENT_LENGTH', 'CONTENT_TYPE', 'HTTP_HOST', 'QUERY_STRING', 'REQUEST_METHOD', 'SERVER_NAME', 'SERVER_PORT', 'SERVER_PROTOCOL'): del request.META[header] response = view(request, *args, **kwargs) response.csrf_processing_done = True # prevent generation of CSRF cookies return response return g
class CoursewareIndex(View): """ View class for the Courseware page. """ @method_decorator(login_required) @method_decorator(ensure_csrf_cookie) @method_decorator( cache_control(no_cache=True, no_store=True, must_revalidate=True)) @method_decorator(ensure_valid_course_key) def get(self, request, course_id, chapter=None, section=None, position=None): """ Displays courseware accordion and associated content. If course, chapter, and section are all specified, renders the page, or returns an error if they are invalid. If section is not specified, displays the accordion opened to the right chapter. If neither chapter or section are specified, displays the user's most recent chapter, or the first chapter if this is the user's first visit. Arguments: request: HTTP request course_id (unicode): course id chapter (unicode): chapter url_name section (unicode): section url_name position (unicode): position in module, eg of <sequential> module """ self.course_key = CourseKey.from_string(course_id) self.request = request self.original_chapter_url_name = chapter self.original_section_url_name = section self.chapter_url_name = chapter self.section_url_name = section self.position = position self.chapter, self.section = None, None self.url = request.path try: self._init_new_relic() self._clean_position() with modulestore().bulk_operations(self.course_key): self.course = get_course_with_access(request.user, 'load', self.course_key, depth=CONTENT_DEPTH) self.is_staff = has_access(request.user, 'staff', self.course) self._setup_masquerade_for_effective_user() return self._get(request) except Redirect as redirect_error: return redirect(redirect_error.url) except UnicodeEncodeError: raise Http404("URL contains Unicode characters") except Http404: # let it propagate raise except Exception: # pylint: disable=broad-except return self._handle_unexpected_error() def _setup_masquerade_for_effective_user(self): """ Setup the masquerade information to allow the request to be processed for the requested effective user. """ self.real_user = self.request.user self.masquerade, self.effective_user = setup_masquerade( self.request, self.course_key, self.is_staff, reset_masquerade_data=True) # Set the user in the request to the effective user. self.request.user = self.effective_user def _get(self, request): """ Render the index page. """ self._redirect_if_needed_to_access_course() self._prefetch_and_bind_course(request) if self.course.has_children_at_depth(CONTENT_DEPTH): self._reset_section_to_exam_if_required() self.chapter = self._find_chapter() self.section = self._find_section() if self.chapter and self.section: self._redirect_if_not_requested_section() self._save_positions() self._prefetch_and_bind_section() return render_to_response('courseware/courseware.html', self._create_courseware_context()) def _redirect_if_not_requested_section(self): """ If the resulting section and chapter are different from what was initially requested, redirect back to the index page, but with an updated URL that includes the correct section and chapter values. We do this so that our analytics events and error logs have the appropriate URLs. """ if (self.chapter.url_name != self.original_chapter_url_name or (self.original_section_url_name and self.section.url_name != self.original_section_url_name)): raise Redirect( reverse( 'courseware_section', kwargs={ 'course_id': unicode(self.course_key), 'chapter': self.chapter.url_name, 'section': self.section.url_name, }, )) def _init_new_relic(self): """ Initialize metrics for New Relic so we can slice data in New Relic Insights """ if not newrelic: return newrelic.agent.add_custom_parameter('course_id', unicode(self.course_key)) newrelic.agent.add_custom_parameter('org', unicode(self.course_key.org)) def _clean_position(self): """ Verify that the given position is an integer. If it is not positive, set it to 1. """ if self.position is not None: try: self.position = max(int(self.position), 1) except ValueError: raise Http404(u"Position {} is not an integer!".format( self.position)) def _redirect_if_needed_to_access_course(self): """ Verifies that the user can enter the course. """ self._redirect_if_needed_to_pay_for_course() self._redirect_if_needed_to_register() self._redirect_if_needed_for_prereqs() self._redirect_if_needed_for_course_survey() self._redirect_if_data_sharing_consent_needed() def _redirect_if_data_sharing_consent_needed(self): """ Determine if the user needs to provide data sharing consent before accessing the course, and redirect the user to provide consent if needed. """ course_id = unicode(self.course_key) consent_url = get_enterprise_consent_url(self.request, course_id, user=self.real_user, return_to='courseware') if consent_url: log.warning( u'User %s cannot access the course %s because they have not granted consent', self.real_user, course_id, ) raise Redirect(consent_url) def _redirect_if_needed_to_pay_for_course(self): """ Redirect to dashboard if the course is blocked due to non-payment. """ self.real_user = User.objects.prefetch_related("groups").get( id=self.real_user.id) redeemed_registration_codes = CourseRegistrationCode.objects.filter( course_id=self.course_key, registrationcoderedemption__redeemed_by=self.real_user) if is_course_blocked(self.request, redeemed_registration_codes, self.course_key): # registration codes may be generated via Bulk Purchase Scenario # we have to check only for the invoice generated registration codes # that their invoice is valid or not log.warning( u'User %s cannot access the course %s because payment has not yet been received', self.real_user, unicode(self.course_key), ) raise Redirect(reverse('dashboard')) def _redirect_if_needed_to_register(self): """ Verify that the user is registered in the course. """ if not registered_for_course(self.course, self.effective_user): log.debug(u'User %s tried to view course %s but is not enrolled', self.effective_user, unicode(self.course.id)) user_is_global_staff = GlobalStaff().has_user(self.effective_user) user_is_enrolled = CourseEnrollment.is_enrolled( self.effective_user, self.course_key) if user_is_global_staff and not user_is_enrolled: redirect_url = get_redirect_url_for_global_staff( self.course_key, _next=self.url) raise Redirect(redirect_url) raise Redirect( reverse('about_course', args=[unicode(self.course.id)])) def _redirect_if_needed_for_prereqs(self): """ See if all pre-requisites (as per the milestones app feature) have been fulfilled. Note that if the pre-requisite feature flag has been turned off (default) then this check will always pass. """ if not has_access(self.effective_user, 'view_courseware_with_prerequisites', self.course): # Prerequisites have not been fulfilled. # Therefore redirect to the Dashboard. log.info( u'User %d tried to view course %s ' u'without fulfilling prerequisites', self.effective_user.id, unicode(self.course.id)) raise Redirect(reverse('dashboard')) def _redirect_if_needed_for_course_survey(self): """ Check to see if there is a required survey that must be taken before the user can access the course. """ if must_answer_survey(self.course, self.effective_user): raise Redirect( reverse('course_survey', args=[unicode(self.course.id)])) def _reset_section_to_exam_if_required(self): """ Check to see if an Entrance Exam is required for the user. """ if not user_can_skip_entrance_exam(self.effective_user, self.course): exam_chapter = get_entrance_exam_content(self.effective_user, self.course) if exam_chapter and exam_chapter.get_children(): exam_section = exam_chapter.get_children()[0] if exam_section: self.chapter_url_name = exam_chapter.url_name self.section_url_name = exam_section.url_name def _get_language_preference(self): """ Returns the preferred language for the actual user making the request. """ language_preference = get_user_preference(self.real_user, LANGUAGE_KEY) if not language_preference: language_preference = settings.LANGUAGE_CODE return language_preference def _is_masquerading_as_student(self): """ Returns whether the current request is masquerading as a student. """ return self.masquerade and self.masquerade.role == 'student' def _is_masquerading_as_specific_student(self): """ Returns whether the current request is masqueurading as a specific student. """ return self._is_masquerading_as_student() and self.masquerade.user_name def _find_block(self, parent, url_name, block_type, min_depth=None): """ Finds the block in the parent with the specified url_name. If not found, calls get_current_child on the parent. """ child = None if url_name: child = parent.get_child_by(lambda m: m.location.name == url_name) if not child: # User may be trying to access a child that isn't live yet if not self._is_masquerading_as_student(): raise Http404( 'No {block_type} found with name {url_name}'.format( block_type=block_type, url_name=url_name, )) elif min_depth and not child.has_children_at_depth(min_depth - 1): child = None if not child: child = get_current_child( parent, min_depth=min_depth, requested_child=self.request.GET.get("child")) return child def _find_chapter(self): """ Finds the requested chapter. """ return self._find_block(self.course, self.chapter_url_name, 'chapter', CONTENT_DEPTH - 1) def _find_section(self): """ Finds the requested section. """ if self.chapter: return self._find_block(self.chapter, self.section_url_name, 'section') def _prefetch_and_bind_course(self, request): """ Prefetches all descendant data for the requested section and sets up the runtime, which binds the request user to the section. """ self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents( self.course_key, self.effective_user, self.course, depth=CONTENT_DEPTH, read_only=CrawlersConfig.is_crawler(request), ) self.course = get_module_for_descriptor( self.effective_user, self.request, self.course, self.field_data_cache, self.course_key, course=self.course, ) def _prefetch_and_bind_section(self): """ Prefetches all descendant data for the requested section and sets up the runtime, which binds the request user to the section. """ # Pre-fetch all descendant data self.section = modulestore().get_item(self.section.location, depth=None, lazy=False) self.field_data_cache.add_descriptor_descendents(self.section, depth=None) # Bind section to user self.section = get_module_for_descriptor( self.effective_user, self.request, self.section, self.field_data_cache, self.course_key, self.position, course=self.course, ) def _save_positions(self): """ Save where we are in the course and chapter. """ save_child_position(self.course, self.chapter_url_name) save_child_position(self.chapter, self.section_url_name) def _create_courseware_context(self): """ Returns and creates the rendering context for the courseware. Also returns the table of contents for the courseware. """ request = RequestCache.get_current_request() courseware_context = { 'csrf': csrf(self.request)['csrf_token'], 'COURSE_TITLE': self.course.display_name_with_default_escaped, 'course': self.course, 'init': '', 'fragment': Fragment(), 'staff_access': self.is_staff, 'studio_url': get_studio_url(self.course, 'course'), 'masquerade': self.masquerade, 'real_user': self.real_user, 'xqa_server': settings.FEATURES.get('XQA_SERVER', "http://your_xqa_server.com"), 'bookmarks_api_url': reverse('bookmarks'), 'language_preference': self._get_language_preference(), 'disable_optimizely': True, 'section_title': None, 'sequence_title': None, 'disable_accordion': waffle.flag_is_active(request, 'unified_course_view') } table_of_contents = toc_for_course( self.effective_user, self.request, self.course, self.chapter_url_name, self.section_url_name, self.field_data_cache, ) courseware_context['accordion'] = render_accordion( self.request, self.course, table_of_contents['chapters'], ) # entrance exam data self._add_entrance_exam_to_context(courseware_context) # staff masquerading data now = datetime.now(UTC()) effective_start = _adjust_start_date_for_beta_testers( self.effective_user, self.course, self.course_key) if not in_preview_mode() and self.is_staff and now < effective_start: # Disable student view button if user is staff and # course is not yet visible to students. courseware_context['disable_student_access'] = True if self.section: # chromeless data if self.section.chrome: chrome = [ s.strip() for s in self.section.chrome.lower().split(",") ] if 'accordion' not in chrome: courseware_context['disable_accordion'] = True if 'tabs' not in chrome: courseware_context['disable_tabs'] = True # default tab if self.section.default_tab: courseware_context['default_tab'] = self.section.default_tab # section data courseware_context[ 'section_title'] = self.section.display_name_with_default_escaped section_context = self._create_section_context( table_of_contents['previous_of_active_section'], table_of_contents['next_of_active_section'], ) courseware_context['fragment'] = self.section.render( STUDENT_VIEW, section_context) if self.section.position and self.section.has_children: display_items = self.section.get_display_items() if display_items: courseware_context['sequence_title'] = display_items[self.section.position - 1] \ .display_name_with_default return courseware_context def _add_entrance_exam_to_context(self, courseware_context): """ Adds entrance exam related information to the given context. """ if course_has_entrance_exam(self.course) and getattr( self.chapter, 'is_entrance_exam', False): courseware_context[ 'entrance_exam_passed'] = user_has_passed_entrance_exam( self.effective_user, self.course) courseware_context[ 'entrance_exam_current_score'] = get_entrance_exam_score_ratio( CourseGradeFactory().create(self.effective_user, self.course), get_entrance_exam_usage_key(self.course), ) def _create_section_context(self, previous_of_active_section, next_of_active_section): """ Returns and creates the rendering context for the section. """ def _compute_section_url(section_info, requested_child): """ Returns the section URL for the given section_info with the given child parameter. """ return "{url}?child={requested_child}".format( url=reverse( 'courseware_section', args=[ unicode(self.course_key), section_info['chapter_url_name'], section_info['url_name'] ], ), requested_child=requested_child, ) section_context = { 'activate_block_id': self.request.GET.get('activate_block_id'), 'requested_child': self.request.GET.get("child"), 'progress_url': reverse('progress', kwargs={'course_id': unicode(self.course_key)}), } if previous_of_active_section: section_context['prev_url'] = _compute_section_url( previous_of_active_section, 'last') if next_of_active_section: section_context['next_url'] = _compute_section_url( next_of_active_section, 'first') # sections can hide data that masquerading staff should see when debugging issues with specific students section_context[ 'specific_masquerade'] = self._is_masquerading_as_specific_student( ) return section_context def _handle_unexpected_error(self): """ Handle unexpected exceptions raised by View. """ # In production, don't want to let a 500 out for any reason if settings.DEBUG: raise log.exception( u"Error in index view: user=%s, effective_user=%s, course=%s, chapter=%s section=%s position=%s", self.real_user, self.effective_user, unicode(self.course_key), self.chapter_url_name, self.section_url_name, self.position, ) try: return render_to_response('courseware/courseware-error.html', { 'staff_access': self.is_staff, 'course': self.course }) except: # Let the exception propagate, relying on global config to # at least return a nice error message log.exception("Error while rendering courseware-error page") raise
class LearnerAnalyticsView(View): """ Displays the Learner Analytics Dashboard. """ def __init__(self): View.__init__(self) self.analytics_client = Client(base_url=settings.ANALYTICS_API_URL, auth_token=settings.ANALYTICS_API_KEY) @method_decorator(login_required) @method_decorator( cache_control(no_cache=True, no_store=True, must_revalidate=True)) @method_decorator(ensure_valid_course_key) def get(self, request, course_id): """ Displays the user's Learner Analytics for the specified course. Arguments: request: HTTP request course_id (unicode): course id """ course_key = CourseKey.from_string(course_id) if not ENABLE_DASHBOARD_TAB.is_enabled(course_key): raise Http404 course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True) course_url_name = default_course_url_name(course.id) course_url = reverse(course_url_name, kwargs={'course_id': unicode(course.id)}) grading_policy = course.grading_policy (grade_data, answered_percent) = self.get_grade_data( request.user, course_key, grading_policy['GRADE_CUTOFFS']) schedule_data = self.get_assignments_with_due_date(request, course_key) (grade_data, schedule_data) = self.sort_grade_and_schedule_data( grade_data, schedule_data) context = { 'course': course, 'course_url': course_url, 'disable_courseware_js': True, 'uses_pattern_library': True, 'is_self_paced': course.self_paced, 'is_verified': CourseEnrollment.is_enrolled_as_verified(request.user, course_key), 'grading_policy': grading_policy, 'assignment_grades': grade_data, 'answered_percent': answered_percent, 'assignment_schedule': schedule_data, 'profile_image_urls': get_profile_image_urls_for_user(request.user, request), 'discussion_info': self.get_discussion_data(request, course_key), 'weekly_active_users': self.get_weekly_course_activity_count(course_key), 'week_streak': self.consecutive_weeks_of_course_activity_for_user( request.user.username, course_key) } return render_to_response('learner_analytics/dashboard.html', context) def get_grade_data(self, user, course_key, grade_cutoffs): """ Collects and formats the grades data for a particular user and course. Args: user (User) course_key (CourseKey) grade_cutoffs: # TODO: LEARNER-3854: Complete docstring if implementing Learner Analytics. """ course_grade = CourseGradeFactory().read(user, course_key=course_key) grades = [] total_earned = 0 total_possible = 0 answered_percent = None for (location, subsection_grade) in course_grade.subsection_grades.iteritems(): if subsection_grade.format is not None: possible = subsection_grade.graded_total.possible earned = subsection_grade.graded_total.earned passing_grade = math.ceil(possible * grade_cutoffs['Pass']) grades.append({ 'assignment_type': subsection_grade.format, 'total_earned': earned, 'total_possible': possible, 'passing_grade': passing_grade, 'location': unicode(location), 'assigment_url': reverse('jump_to_id', kwargs={ 'course_id': unicode(course_key), 'module_id': unicode(location), }) }) if earned > 0: total_earned += earned total_possible += possible if total_possible > 0: answered_percent = float(total_earned) / total_possible return (grades, answered_percent) def sort_grade_and_schedule_data(self, grade_data, schedule_data): """ Sort the assignments in grade_data and schedule_data to be in the same order. """ schedule_dict = { assignment['location']: assignment for assignment in schedule_data } sorted_schedule_data = [] sorted_grade_data = [] for grade in grade_data: assignment = schedule_dict.get(grade['location']) if assignment: sorted_grade_data.append(grade) sorted_schedule_data.append(assignment) return sorted_grade_data, sorted_schedule_data def get_discussion_data(self, request, course_key): """ Collects and formats the discussion data from a particular user and course. Args: request (HttpRequest) course_key (CourseKey) """ context = create_user_profile_context(request, course_key, request.user.id) threads = context['threads'] profiled_user = context['profiled_user'] # TODO: LEARNER-3854: If implementing Learner Analytics, rename to content_authored_count. content_authored = profiled_user['threads_count'] + profiled_user[ 'comments_count'] thread_votes = 0 for thread in threads: if thread['user_id'] == profiled_user['external_id']: thread_votes += thread['votes']['count'] discussion_data = { 'content_authored': content_authored, 'thread_votes': thread_votes, } return discussion_data def get_assignments_with_due_date(self, request, course_key): """ Returns a list of assignment (graded) blocks with due dates, including due date and location. Args: request (HttpRequest) course_key (CourseKey) """ course_usage_key = modulestore().make_course_usage_key(course_key) all_blocks = get_blocks( request, course_usage_key, user=request.user, nav_depth=3, requested_fields=['display_name', 'due', 'graded', 'format'], block_types_filter=['sequential']) assignment_blocks = [] for (location, block) in all_blocks['blocks'].iteritems(): if block.get('graded', False) and block.get('due') is not None: assignment_blocks.append(block) block['due'] = block['due'].isoformat() block['location'] = unicode(location) return assignment_blocks def get_weekly_course_activity_count(self, course_key): """ Get the count of any course activity (total for all users) from previous 7 days. Args: course_key (CourseKey) """ cache_key = 'learner_analytics_{course_key}_weekly_activities'.format( course_key=course_key) activities = cache.get(cache_key) if not activities: log.info( 'Weekly course activities for course {course_key} was not cached - fetching from Analytics API' .format(course_key=course_key)) weekly_course_activities = self.analytics_client.courses( course_key).activity() if not weekly_course_activities or 'any' not in weekly_course_activities[ 0]: return 0 # weekly course activities should only have one item activities = weekly_course_activities[0] cache.set(cache_key, activities, LearnerAnalyticsView.seconds_to_cache_expiration()) return activities['any'] def consecutive_weeks_of_course_activity_for_user(self, username, course_key): """ Get the most recent count of consecutive days that a user has performed a course activity Args: username (str) course_key (CourseKey) """ cache_key = 'learner_analytics_{username}_{course_key}_engagement_timeline'\ .format(username=username, course_key=course_key) timeline = cache.get(cache_key) if not timeline: log.info( 'Engagement timeline for course {course_key} was not cached - fetching from Analytics API' .format(course_key=course_key)) # TODO (LEARNER-3470): @jaebradley replace this once the Analytics client has an engagement timeline method url = '{base_url}/engagement_timelines/{username}?course_id={course_key}'\ .format(base_url=settings.ANALYTICS_API_URL, username=username, course_key=urllib.quote_plus(unicode(course_key))) headers = { 'Authorization': 'Token {token}'.format(token=settings.ANALYTICS_API_KEY) } response = requests.get(url=url, headers=headers) data = response.json() if not data or 'days' not in data or not data['days']: return 0 # Analytics API returns data in ascending (by date) order - we want to count starting from most recent day data_ordered_by_date_descending = list(reversed(data['days'])) cache.set(cache_key, data_ordered_by_date_descending, LearnerAnalyticsView.seconds_to_cache_expiration()) timeline = data_ordered_by_date_descending return LearnerAnalyticsView.calculate_week_streak(timeline) @staticmethod def calculate_week_streak(daily_activities): """ Check number of weeks in a row that a user has performed some activity. Regardless of when a week starts, a sufficient condition for checking if a specific week had any user activity (given a list of daily activities ordered by date) is to iterate through the list of days 7 days at a time and check to see if any of those days had any activity. Args: daily_activities: sorted list of dictionaries containing activities and their counts """ week_streak = 0 seven_day_buckets = [ daily_activities[i:i + 7] for i in range(0, len(daily_activities), 7) ] for bucket in seven_day_buckets: if any(LearnerAnalyticsView.has_activity(day) for day in bucket): week_streak += 1 else: return week_streak return week_streak @staticmethod def has_activity(daily_activity): """ Validate that a course had some activity that day Args: daily_activity: dictionary of activities and their counts """ return int(daily_activity['problems_attempted']) > 0 \ or int(daily_activity['problems_completed']) > 0 \ or int(daily_activity['discussion_contributions']) > 0 \ or int(daily_activity['videos_viewed']) > 0 @staticmethod def seconds_to_cache_expiration(): """Calculate cache expiration seconds. Currently set to seconds until midnight UTC""" next_midnight_utc = (datetime.today() + timedelta(days=1)).replace( hour=0, minute=0, second=0, microsecond=0, tzinfo=pytz.utc) now_utc = datetime.now(tz=pytz.utc) return round((next_midnight_utc - now_utc).total_seconds())
# Import additional urlpatterns from any apps that define a register_admin_urls hook for fn in hooks.get_hooks('register_admin_urls'): urls = fn() if urls: urlpatterns += urls # Add "wagtailadmin.access_admin" permission check urlpatterns = decorate_urlpatterns(urlpatterns, require_admin_access) # These url patterns do not require an authenticated admin user urlpatterns += [ url(r'^login/$', account.login, name='wagtailadmin_login'), # These two URLs have the "permission_required" decorator applied directly # as they need to fail with a 403 error rather than redirect to the login page url(r'^userbar/(\d+)/$', userbar.for_frontend, name='wagtailadmin_userbar_frontend'), url(r'^userbar/moderation/(\d+)/$', userbar.for_moderation, name='wagtailadmin_userbar_moderation'), # Password reset url(r'^password_reset/', include(wagtailadmin_password_reset_urls)), ] # Decorate all views with cache settings to prevent caching urlpatterns = decorate_urlpatterns( urlpatterns, cache_control(private=True, no_cache=True, no_store=True, max_age=0) )
def stats(request): """ The global stats """ # TODO: generate these nightly. we shouldn't be doing this for every request top_links_all_time = list(Link.objects.all().order_by('-view_count')[:10]) context = RequestContext(request, {'top_links_all_time': top_links_all_time}) return render_to_response('stats.html', context) @ssl_optional @if_anonymous(cache_control(max_age=settings.CACHE_MAX_AGES['single_linky'])) @ratelimit(method='GET', rate=settings.MINUTE_LIMIT, block=True, ip=False, keys=lambda req: req.META.get('HTTP_X_FORWARDED_FOR', req.META['REMOTE_ADDR'])) @ratelimit(method='GET', rate=settings.HOUR_LIMIT, block=True, ip=False, keys=lambda req: req.META.get('HTTP_X_FORWARDED_FOR', req.META['REMOTE_ADDR'])) @ratelimit(method='GET', rate=settings.DAY_LIMIT, block=True, ip=False, keys=lambda req: req.META.get('HTTP_X_FORWARDED_FOR', req.META['REMOTE_ADDR'])) def single_linky(request, guid): """ Given a Perma ID, serve it up. Vesting also takes place here. """ # Create a canonical version of guid (non-alphanumerics removed, hyphens every 4 characters, uppercase), # and forward to that if it's different from current guid. canonical_guid = Link.get_canonical_guid(guid) link = get_object_or_404(Link, guid=canonical_guid)
def permanent_public_cache(view): one_year = 60 * 60 * 24 * 365 decorator = cache_control(public=True, max_age=one_year) return decorator(view)
**kwargs ) urlpatterns = i18n_patterns( url(r'^$', login_required(LandingView.as_view()), name='home'), url(r'^', include('cashbook.urls')), url(r'^disbursements/', include('disbursements.urls', namespace='disbursements')), url(r'^', include('mtp_auth.urls')), url(r'^', include('mtp_common.user_admin.urls')), url(r'^', include('feedback.urls')), url(r'^js-i18n.js$', cache_control(public=True, max_age=86400)(JavaScriptCatalog.as_view()), name='js-i18n'), url(r'^404.html$', lambda request: TemplateResponse(request, 'mtp_common/errors/404.html', status=404)), url(r'^500.html$', lambda request: TemplateResponse(request, 'mtp_common/errors/500.html', status=500)), ) urlpatterns += [ url(r'^ping.json$', PingJsonView.as_view( build_date_key='APP_BUILD_DATE', commit_id_key='APP_GIT_COMMIT', version_number_key='APP_BUILD_TAG', ), name='ping_json'), url(r'^healthcheck.json$', HealthcheckView.as_view(), name='healthcheck_json'), url(r'^favicon.ico$', RedirectView.as_view(url=settings.STATIC_URL + 'images/favicon.ico', permanent=True)), url(r'^robots.txt$', lambda request: HttpResponse('User-agent: *\nDisallow: /', content_type='text/plain')),
def cache_headers(func): return vary_on_headers("Authorization")(cache_control(max_age=0, public=True, must_revalidate=True)(func))
class MyClass: @method_decorator(cache_control(a="b")) def a_view(self, request): return HttpResponse()
class OrderedPartyListView(ElectionMixin, TemplateView): template_name = "candidates/ordered-party-list.html" @method_decorator(cache_control(max_age=(60 * 20))) def dispatch(self, *args, **kwargs): return super().dispatch(*args, **kwargs) def get_context_data(self, **kwargs): from ..election_specific import shorten_post_label context = super().get_context_data(**kwargs) context["post_id"] = post_id = kwargs["post_id"] post_qs = Post.objects.all() mp_post = get_object_or_404(post_qs, slug=post_id) party_id = kwargs["legacy_slug"] party = get_object_or_404(Party, legacy_slug=party_id) context["party"] = party context["post_label"] = mp_post.label context["post_label_shorter"] = shorten_post_label( context["post_label"]) context["redirect_after_login"] = urlquote( reverse( "party-for-post", kwargs={ "election": self.election, "post_id": post_id, "legacy_slug": party_id, }, )) context["post_data"] = {"id": mp_post.slug, "label": mp_post.label} context["candidates_locked"] = is_post_locked(mp_post, self.election_data) context["lock_form"] = ToggleLockForm( initial={ "post_id": post_id, "lock": not context["candidates_locked"], }) context["candidate_list_edits_allowed"] = get_edits_allowed( self.request.user, context["candidates_locked"]) context[ "positions_and_people"] = get_party_people_for_election_from_memberships( self.election, party.ec_id, mp_post.memberships) party_set = PartySet.objects.get(post__slug=post_id) context["add_candidate_form"] = NewPersonForm( election=self.election, initial={ ("constituency_" + self.election): post_id, ("standing_" + self.election): "standing", ("party_" + party_set.slug + "_" + self.election): party_id, }, hidden_post_widget=True, ) return context
import os from urlparse import urlparse from django.contrib.auth.decorators import user_passes_test from django.http import HttpResponseRedirect from django.views.generic.simple import direct_to_template from django.core.urlresolvers import reverse from django.conf import settings from django.views.decorators.vary import vary_on_headers from django.views.decorators.cache import cache_control from google.appengine.api import users #: static_resource cache decorator will be used for things which can safely # be cached to improve client HTTP performance static_resource = cache_control(public=True, max_age=86400) def index(request): if request.user.is_authenticated and request.user.is_staff: return HttpResponseRedirect(reverse("error-list")) return direct_to_template(request, "index.html") @user_passes_test(lambda u: u.is_staff) def setup(request): return direct_to_template(request, "setup.html", extra_context={ "nav": {"selected": "setup"}, "app_id": os.environ.get("APPLICATION_ID"), }) @static_resource @vary_on_headers("Accept-Encoding")
def g(request, *args, **kwargs): if "nocache" not in request.GET: return cache_control(public=True, max_age=maps_settings.MAP_TILE_CACHE_SECONDS)(f)(request, *args, **kwargs) else: return cache_control(private=True, no_cache=True, must_revalidate=True)(f)(request, *args, **kwargs)
if not content.is_published: return Response(status=status.HTTP_404_NOT_FOUND) serializer = RecircContentSerializer( content.get_recirc_content(count=3).execute(), many=True ) return Response(serializer.data, status=status.HTTP_200_OK) class InlineRecircViewSet(views.APIView): permission_classes = (AllowAny,) def get(self, request, pk): content = get_object_or_404(Content, id=pk) if not content.is_published: return Response(status=status.HTTP_404_NOT_FOUND) serializer = RecircContentSerializer( content.get_inline_recirc_content(count=3).execute(), many=True ) return Response(serializer.data, status=status.HTTP_200_OK) inline_recirc = cache_control(max_age=600)(InlineRecircViewSet.as_view()) recirc = cache_control(max_age=600)(RecircViewSet.as_view())
class CoursewareIndex(View): """ View class for the Courseware page. """ @cached_property def enable_unenrolled_access(self): return COURSE_ENABLE_UNENROLLED_ACCESS_FLAG.is_enabled(self.course_key) @method_decorator(ensure_csrf_cookie) @method_decorator( cache_control(no_cache=True, no_store=True, must_revalidate=True)) @method_decorator(ensure_valid_course_key) @method_decorator(data_sharing_consent_required) def get(self, request, course_id, chapter=None, section=None, position=None): """ Displays courseware accordion and associated content. If course, chapter, and section are all specified, renders the page, or returns an error if they are invalid. If section is not specified, displays the accordion opened to the right chapter. If neither chapter or section are specified, displays the user's most recent chapter, or the first chapter if this is the user's first visit. Arguments: request: HTTP request course_id (unicode): course id chapter (unicode): chapter url_name section (unicode): section url_name position (unicode): position in module, eg of <sequential> module """ self.course_key = CourseKey.from_string(course_id) if not (request.user.is_authenticated or self.enable_unenrolled_access): return redirect_to_login(request.get_full_path()) self.original_chapter_url_name = chapter self.original_section_url_name = section self.chapter_url_name = chapter self.section_url_name = section self.position = position self.chapter, self.section = None, None self.course = None self.url = request.path try: set_custom_attributes_for_course_key(self.course_key) self._clean_position() with modulestore().bulk_operations(self.course_key): self.view = STUDENT_VIEW self.course = get_course_with_access( request.user, 'load', self.course_key, depth=CONTENT_DEPTH, check_if_enrolled=True, check_if_authenticated=True) self.course_overview = CourseOverview.get_from_id( self.course.id) self.is_staff = has_access(request.user, 'staff', self.course) # There's only one situation where we want to show the public view if (not self.is_staff and self.enable_unenrolled_access and self.course.course_visibility == COURSE_VISIBILITY_PUBLIC and not CourseEnrollment.is_enrolled( request.user, self.course_key)): self.view = PUBLIC_VIEW self.can_masquerade = request.user.has_perm( MASQUERADE_AS_STUDENT, self.course) self._setup_masquerade_for_effective_user() return self.render(request) except Exception as exception: # pylint: disable=broad-except return CourseTabView.handle_exceptions(request, self.course_key, self.course, exception) def _setup_masquerade_for_effective_user(self): """ Setup the masquerade information to allow the request to be processed for the requested effective user. """ self.real_user = self.request.user self.masquerade, self.effective_user = setup_masquerade( self.request, self.course_key, self.can_masquerade, reset_masquerade_data=True) # Set the user in the request to the effective user. self.request.user = self.effective_user def _redirect_to_learning_mfe(self): """ Redirect to the new courseware micro frontend, unless this is a time limited exam. """ # DENY: feature disabled globally if not settings.FEATURES.get('ENABLE_COURSEWARE_MICROFRONTEND'): return # DENY: staff access if self.is_staff: return # DENY: Old Mongo courses, until removed from platform if self.course_key.deprecated: return # DENY: Timed Exams, until supported if getattr(self.section, 'is_time_limited', False): return # ALLOW: when flag set for course if REDIRECT_TO_COURSEWARE_MICROFRONTEND.is_enabled(self.course_key): raise Redirect(self.microfrontend_url) @property def microfrontend_url(self): """ Return absolute URL to this section in the courseware micro-frontend. """ try: unit_key = UsageKey.from_string( self.request.GET.get('activate_block_id', '')) # `activate_block_id` is typically a Unit (a.k.a. Vertical), # but it can technically be any block type. Do a check to # make sure it's really a Unit before we use it for the MFE. if unit_key.block_type != 'vertical': unit_key = None except InvalidKeyError: unit_key = None url = get_microfrontend_url( self.course_key, self.section.location if self.section else None, unit_key) return url def render(self, request): """ Render the index page. """ self._prefetch_and_bind_course(request) if self.course.has_children_at_depth(CONTENT_DEPTH): self._reset_section_to_exam_if_required() self.chapter = self._find_chapter() self.section = self._find_section() if self.chapter and self.section: self._redirect_if_not_requested_section() self._save_positions() self._prefetch_and_bind_section() self._redirect_to_learning_mfe() check_content_start_date_for_masquerade_user( self.course_key, self.effective_user, request, self.course.start, self.chapter.start, self.section.start) if not request.user.is_authenticated: qs = six.moves.urllib.parse.urlencode({ 'course_id': self.course_key, 'enrollment_action': 'enroll', 'email_opt_in': False, }) allow_anonymous = check_public_access(self.course, [COURSE_VISIBILITY_PUBLIC]) if not allow_anonymous: PageLevelMessages.register_warning_message( request, Text( _(u"You are not signed in. To see additional course content, {sign_in_link} or " u"{register_link}, and enroll in this course.")). format( sign_in_link=HTML( u'<a href="{url}">{sign_in_label}</a>').format( sign_in_label=_('sign in'), url='{}?{}'.format(reverse('signin_user'), qs), ), register_link=HTML( u'<a href="/{url}">{register_label}</a>').format( register_label=_('register'), url=u'{}?{}'.format(reverse('register_user'), qs), ), )) return render_to_response('courseware/courseware.html', self._create_courseware_context(request)) def _redirect_if_not_requested_section(self): """ If the resulting section and chapter are different from what was initially requested, redirect back to the index page, but with an updated URL that includes the correct section and chapter values. We do this so that our analytics events and error logs have the appropriate URLs. """ if (self.chapter.url_name != self.original_chapter_url_name or (self.original_section_url_name and self.section.url_name != self.original_section_url_name)): raise CourseAccessRedirect( reverse( 'courseware_section', kwargs={ 'course_id': six.text_type(self.course_key), 'chapter': self.chapter.url_name, 'section': self.section.url_name, }, )) def _clean_position(self): """ Verify that the given position is an integer. If it is not positive, set it to 1. """ if self.position is not None: try: self.position = max(int(self.position), 1) except ValueError: raise Http404(u"Position {} is not an integer!".format( self.position)) def _reset_section_to_exam_if_required(self): """ Check to see if an Entrance Exam is required for the user. """ if not user_can_skip_entrance_exam(self.effective_user, self.course): exam_chapter = get_entrance_exam_content(self.effective_user, self.course) if exam_chapter and exam_chapter.get_children(): exam_section = exam_chapter.get_children()[0] if exam_section: self.chapter_url_name = exam_chapter.url_name self.section_url_name = exam_section.url_name def _get_language_preference(self): """ Returns the preferred language for the actual user making the request. """ language_preference = settings.LANGUAGE_CODE if self.request.user.is_authenticated: language_preference = get_user_preference(self.real_user, LANGUAGE_KEY) return language_preference def _is_masquerading_as_student(self): """ Returns whether the current request is masquerading as a student. """ return self.masquerade and self.masquerade.role == 'student' def _is_masquerading_as_specific_student(self): """ Returns whether the current request is masqueurading as a specific student. """ return self._is_masquerading_as_student() and self.masquerade.user_name def _find_block(self, parent, url_name, block_type, min_depth=None): """ Finds the block in the parent with the specified url_name. If not found, calls get_current_child on the parent. """ child = None if url_name: child = parent.get_child_by( lambda m: m.location.block_id == url_name) if not child: # User may be trying to access a child that isn't live yet if not self._is_masquerading_as_student(): raise Http404( u'No {block_type} found with name {url_name}'.format( block_type=block_type, url_name=url_name, )) elif min_depth and not child.has_children_at_depth(min_depth - 1): child = None if not child: child = get_current_child( parent, min_depth=min_depth, requested_child=self.request.GET.get("child")) return child def _find_chapter(self): """ Finds the requested chapter. """ return self._find_block(self.course, self.chapter_url_name, 'chapter', CONTENT_DEPTH - 1) def _find_section(self): """ Finds the requested section. """ if self.chapter: return self._find_block(self.chapter, self.section_url_name, 'section') def _prefetch_and_bind_course(self, request): """ Prefetches all descendant data for the requested section and sets up the runtime, which binds the request user to the section. """ self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents( self.course_key, self.effective_user, self.course, depth=CONTENT_DEPTH, read_only=CrawlersConfig.is_crawler(request), ) self.course = get_module_for_descriptor( self.effective_user, self.request, self.course, self.field_data_cache, self.course_key, course=self.course, will_recheck_access=True, ) def _prefetch_and_bind_section(self): """ Prefetches all descendant data for the requested section and sets up the runtime, which binds the request user to the section. """ # Pre-fetch all descendant data self.section = modulestore().get_item(self.section.location, depth=None, lazy=False) self.field_data_cache.add_descriptor_descendents(self.section, depth=None) # Bind section to user self.section = get_module_for_descriptor( self.effective_user, self.request, self.section, self.field_data_cache, self.course_key, self.position, course=self.course, will_recheck_access=True, ) def _save_positions(self): """ Save where we are in the course and chapter. """ save_child_position(self.course, self.chapter_url_name) save_child_position(self.chapter, self.section_url_name) def _create_courseware_context(self, request): """ Returns and creates the rendering context for the courseware. Also returns the table of contents for the courseware. """ course_url_name = default_course_url_name(self.course.id) course_url = reverse( course_url_name, kwargs={'course_id': six.text_type(self.course.id)}) show_search = ( settings.FEATURES.get('ENABLE_COURSEWARE_SEARCH') or (settings.FEATURES.get('ENABLE_COURSEWARE_SEARCH_FOR_COURSE_STAFF') and self.is_staff)) staff_access = self.is_staff courseware_context = { 'csrf': csrf(self.request)['csrf_token'], 'course': self.course, 'course_url': course_url, 'chapter': self.chapter, 'section': self.section, 'init': '', 'fragment': Fragment(), 'staff_access': staff_access, 'can_masquerade': self.can_masquerade, 'masquerade': self.masquerade, 'supports_preview_menu': True, 'studio_url': get_studio_url(self.course, 'course'), 'xqa_server': settings.FEATURES.get('XQA_SERVER', "http://your_xqa_server.com"), 'bookmarks_api_url': reverse('bookmarks'), 'language_preference': self._get_language_preference(), 'disable_optimizely': not LegacyWaffleSwitchNamespace('RET').is_enabled( 'enable_optimizely_in_courseware'), 'section_title': None, 'sequence_title': None, 'disable_accordion': not DISABLE_COURSE_OUTLINE_PAGE_FLAG.is_enabled(self.course.id), 'show_search': show_search, } courseware_context.update( get_experiment_user_metadata_context( self.course, self.effective_user, )) table_of_contents = toc_for_course( self.effective_user, self.request, self.course, self.chapter_url_name, self.section_url_name, self.field_data_cache, ) courseware_context['accordion'] = render_accordion( self.request, self.course, table_of_contents['chapters'], ) courseware_context['course_sock_fragment'] = CourseSockFragmentView( ).render_to_fragment(request, course=self.course) # entrance exam data self._add_entrance_exam_to_context(courseware_context) if self.section: # chromeless data if self.section.chrome: chrome = [ s.strip() for s in self.section.chrome.lower().split(",") ] if 'accordion' not in chrome: courseware_context['disable_accordion'] = True if 'tabs' not in chrome: courseware_context['disable_tabs'] = True # default tab if self.section.default_tab: courseware_context['default_tab'] = self.section.default_tab # section data courseware_context[ 'section_title'] = self.section.display_name_with_default section_context = self._create_section_context( table_of_contents['previous_of_active_section'], table_of_contents['next_of_active_section'], ) courseware_context['fragment'] = self.section.render( self.view, section_context) if self.section.position and self.section.has_children: self._add_sequence_title_to_context(courseware_context) # Courseware MFE link if show_courseware_mfe_link(request.user, staff_access, self.course.id): courseware_context['microfrontend_link'] = self.microfrontend_url else: courseware_context['microfrontend_link'] = None return courseware_context def _add_sequence_title_to_context(self, courseware_context): """ Adds sequence title to the given context. If we're rendering a section with some display items, but position exceeds the length of the displayable items, default the position to the first element. """ display_items = self.section.get_display_items() if not display_items: return if self.section.position > len(display_items): self.section.position = 1 courseware_context['sequence_title'] = display_items[ self.section.position - 1].display_name_with_default def _add_entrance_exam_to_context(self, courseware_context): """ Adds entrance exam related information to the given context. """ if course_has_entrance_exam(self.course) and getattr( self.chapter, 'is_entrance_exam', False): courseware_context[ 'entrance_exam_passed'] = user_has_passed_entrance_exam( self.effective_user, self.course) courseware_context[ 'entrance_exam_current_score'] = get_entrance_exam_score_ratio( CourseGradeFactory().read(self.effective_user, self.course), get_entrance_exam_usage_key(self.course), ) def _create_section_context(self, previous_of_active_section, next_of_active_section): """ Returns and creates the rendering context for the section. """ def _compute_section_url(section_info, requested_child): """ Returns the section URL for the given section_info with the given child parameter. """ return "{url}?child={requested_child}".format( url=reverse( 'courseware_section', args=[ six.text_type(self.course_key), section_info['chapter_url_name'], section_info['url_name'] ], ), requested_child=requested_child, ) # NOTE (CCB): Pull the position from the URL for un-authenticated users. Otherwise, pull the saved # state from the data store. position = None if self.request.user.is_authenticated else self.position section_context = { 'activate_block_id': self.request.GET.get('activate_block_id'), 'requested_child': self.request.GET.get("child"), 'progress_url': reverse('progress', kwargs={'course_id': six.text_type(self.course_key)}), 'user_authenticated': self.request.user.is_authenticated, 'position': position, } if previous_of_active_section: section_context['prev_url'] = _compute_section_url( previous_of_active_section, 'last') if next_of_active_section: section_context['next_url'] = _compute_section_url( next_of_active_section, 'first') # sections can hide data that masquerading staff should see when debugging issues with specific students section_context[ 'specific_masquerade'] = self._is_masquerading_as_specific_student( ) return section_context
class ConstituencyDetailView(ElectionMixin, TemplateView): template_name = 'candidates/constituency.html' @method_decorator(cache_control(max_age=(60 * 20))) def dispatch(self, *args, **kwargs): return super(ConstituencyDetailView, self).dispatch(*args, **kwargs) def get_context_data(self, **kwargs): from ..election_specific import shorten_post_label context = super(ConstituencyDetailView, self).get_context_data(**kwargs) context['post_id'] = post_id = kwargs['post_id'] mp_post = get_object_or_404(Post.objects.select_related('extra'), extra__slug=post_id) context['post_obj'] = mp_post documents_by_type = {} # Make sure that every available document type has a key in # the dictionary, even if there are no such documents. doc_lookup = { t[0]: (t[1], t[2]) for t in OfficialDocument.DOCUMENT_TYPES } for t in doc_lookup.values(): documents_by_type[t] = [] documents_for_post = OfficialDocument.objects.filter( post_id=mp_post.id, election__slug=self.election) for od in documents_for_post: documents_by_type[doc_lookup[od.document_type]].append(od) context['official_documents'] = documents_by_type.items() context['some_official_documents'] = documents_for_post.count() context['post_label'] = mp_post.label context['post_label_shorter'] = shorten_post_label( context['post_label']) context['redirect_after_login'] = \ urlquote(reverse('constituency', kwargs={ 'election': self.election, 'post_id': post_id, 'ignored_slug': slugify(context['post_label_shorter']) })) context['post_data'] = { 'id': mp_post.extra.slug, 'label': mp_post.label } context['candidates_locked'] = False if hasattr(mp_post, 'extra'): context['has_lock_suggestion'] = any([ spl.election_for_suggestion for spl in SuggestedPostLock.objects.filter( post_extra=mp_post.extra) ]) context['candidates_locked'] = mp_post.extra.candidates_locked context['suggest_lock_form'] = SuggestedPostLockForm( initial={'post_extra': mp_post.extra}, ) if self.request.user.is_authenticated(): context['user_has_suggested_lock'] = \ SuggestedPostLock.objects.filter( user=self.request.user, post_extra=mp_post.extra ).exists() context['lock_form'] = ToggleLockForm(initial={ 'post_id': post_id, 'lock': not context['candidates_locked'], }, ) context['candidate_list_edits_allowed'] = \ get_edits_allowed(self.request.user, context['candidates_locked']) extra_qs = MembershipExtra.objects.select_related('election') current_candidacies, past_candidacies = \ split_candidacies( self.election_data, mp_post.memberships.prefetch_related( Prefetch('extra', queryset=extra_qs) ).select_related( 'person', 'person__extra', 'on_behalf_of', 'on_behalf_of__extra', 'organization' ).all() ) current_candidates = set(c.person for c in current_candidacies) past_candidates = set(c.person for c in past_candidacies) other_candidates = past_candidates - current_candidates elected, unelected = split_by_elected( self.election_data, current_candidacies, ) # Now split those candidates into those that we know aren't # standing again, and those that we just don't know about. not_standing_candidates = set( p for p in other_candidates if self.election_data in p.extra.not_standing.all()) might_stand_candidates = set( p for p in other_candidates if self.election_data not in p.extra.not_standing.all()) not_standing_candidacies = [ c for c in past_candidacies if c.person in not_standing_candidates ] might_stand_candidacies = [ c for c in past_candidacies if c.person in might_stand_candidates ] context['candidacies_not_standing_again'] = \ group_candidates_by_party( self.election_data, not_standing_candidacies, ) context['candidacies_might_stand_again'] = \ group_candidates_by_party( self.election_data, might_stand_candidacies, ) context['elected'] = group_candidates_by_party( self.election_data, elected, show_all=True, ) context['unelected'] = group_candidates_by_party( self.election_data, unelected, ) context['has_elected'] = \ len(context['elected']['parties_and_people']) > 0 context['show_retract_result'] = False number_of_winners = 0 for c in current_candidacies: if c.extra.elected: number_of_winners += 1 if c.extra.elected is not None: context['show_retract_result'] = True max_winners = get_max_winners(mp_post, self.election_data) context['show_confirm_result'] = (max_winners < 0) \ or number_of_winners < max_winners context['add_candidate_form'] = NewPersonForm( election=self.election, initial={ ('constituency_' + self.election): post_id, ('standing_' + self.election): 'standing', }, hidden_post_widget=True, ) context = get_person_form_fields(context, context['add_candidate_form']) return context
class SysadminDashboardView(TemplateView): """Base class for sysadmin dashboard views with common methods""" template_name = 'sysadmin_dashboard.html' def __init__(self, **kwargs): """ Initialize base sysadmin dashboard class with modulestore, modulestore_type and return msg """ self.def_ms = modulestore() self.msg = u'' self.datatable = [] super(SysadminDashboardView, self).__init__(**kwargs) @method_decorator(ensure_csrf_cookie) @method_decorator(login_required) @method_decorator( cache_control(no_cache=True, no_store=True, must_revalidate=True)) @method_decorator(condition(etag_func=None)) def dispatch(self, *args, **kwargs): return super(SysadminDashboardView, self).dispatch(*args, **kwargs) def get_courses(self): """ Get an iterable list of courses.""" return self.def_ms.get_courses() def return_csv(self, filename, header, data): """ Convenient function for handling the http response of a csv. data should be iterable and is used to stream object over http """ csv_file = StringIO.StringIO() writer = csv.writer(csv_file, dialect='excel', quotechar='"', quoting=csv.QUOTE_ALL) writer.writerow(header) # Setup streaming of the data def read_and_flush(): """Read and clear buffer for optimization""" csv_file.seek(0) csv_data = csv_file.read() csv_file.seek(0) csv_file.truncate() return csv_data def csv_data(): """Generator for handling potentially large CSVs""" for row in data: writer.writerow(row) csv_data = read_and_flush() yield csv_data response = HttpResponse(csv_data(), content_type='text/csv') response['Content-Disposition'] = 'attachment; filename={0}'.format( filename) return response
class OrderedPartyListView(ElectionMixin, TemplateView): template_name = 'candidates/ordered-party-list.html' @method_decorator(cache_control(max_age=(60 * 20))) def dispatch(self, *args, **kwargs): return super(OrderedPartyListView, self).dispatch(*args, **kwargs) def get_context_data(self, **kwargs): from ..election_specific import shorten_post_label context = super(OrderedPartyListView, self).get_context_data(**kwargs) context['post_id'] = post_id = kwargs['post_id'] post_qs = Post.objects.select_related('extra') mp_post = get_object_or_404(post_qs, extra__slug=post_id) party_id = kwargs['organization_id'] party = get_object_or_404(Organization, extra__slug=party_id) context['party'] = party context['post_label'] = mp_post.label context['post_label_shorter'] = shorten_post_label( context['post_label']) context['redirect_after_login'] = \ urlquote(reverse('party-for-post', kwargs={ 'election': self.election, 'post_id': post_id, 'organization_id': party_id })) context['post_data'] = { 'id': mp_post.extra.slug, 'label': mp_post.label } context['candidates_locked'] = mp_post.extra.candidates_locked context['lock_form'] = ToggleLockForm(initial={ 'post_id': post_id, 'lock': not context['candidates_locked'], }, ) context['candidate_list_edits_allowed'] = \ get_edits_allowed(self.request.user, context['candidates_locked']) context['positions_and_people'] = \ get_party_people_for_election_from_memberships( self.election, party.id, mp_post.memberships ) party_set = PartySet.objects.get(postextra__slug=post_id) context['add_candidate_form'] = NewPersonForm( election=self.election, initial={ ('constituency_' + self.election): post_id, ('standing_' + self.election): 'standing', ('party_' + party_set.slug + '_' + self.election): party_id, }, hidden_post_widget=True, ) return context
def as_view(cls, **kwargs): view = super(NoCacheMixin, cls).as_view(**kwargs) return cache_control( private=True, no_cache=True, no_store=True, max_age=0)(view)
class ConstituencyDetailView(ElectionMixin, PopItApiMixin, TemplateView): template_name = 'candidates/constituency.html' @method_decorator(cache_control(max_age=(60 * 20))) def dispatch(self, *args, **kwargs): return super(ConstituencyDetailView, self).dispatch(*args, **kwargs) def get_context_data(self, **kwargs): context = super(ConstituencyDetailView, self).get_context_data(**kwargs) context['post_id'] = post_id = kwargs['post_id'] mp_post = get_post_cached(self.api, post_id) documents_by_type = {} # Make sure that every available document type has a key in # the dictionary, even if there are no such documents. doc_lookup = { t[0]: (t[1], t[2]) for t in OfficialDocument.DOCUMENT_TYPES } for t in doc_lookup.values(): documents_by_type[t] = [] documents_for_post = OfficialDocument.objects.filter(post_id=post_id) for od in documents_for_post: documents_by_type[doc_lookup[od.document_type]].append(od) context['official_documents'] = documents_by_type.items() context['some_official_documents'] = documents_for_post.count() context['post_label'] = mp_post['result']['label'] context['post_label_shorter'] = AREA_POST_DATA.shorten_post_label( self.election, context['post_label']) context['redirect_after_login'] = \ urlquote(reverse('constituency', kwargs={ 'election': self.election, 'post_id': post_id, 'ignored_slug': slugify(context['post_label_shorter']) })) context['post_data'] = { k: v for k, v in mp_post['result'].items() if k in ('id', 'label') } context['candidates_locked'] = mp_post['result'].get( 'candidates_locked', False) context['lock_form'] = ToggleLockForm(initial={ 'post_id': post_id, 'lock': not context['candidates_locked'], }, ) context['candidate_list_edits_allowed'] = \ get_edits_allowed(self.request.user, context['candidates_locked']) current_candidates, past_candidates = \ get_people_from_memberships( self.election_data, mp_post['result']['memberships'] ) context['candidates_standing_again'] = \ past_candidates.intersection(current_candidates) other_candidates = past_candidates - current_candidates # Now split those candidates into those that we know aren't # standing again, and those that we just don't know about: context['candidates_not_standing_again'] = \ set(p for p in other_candidates if p.not_standing_in_election(self.election)) context['candidates_might_stand_again'] = \ set(p for p in other_candidates if not p.known_status_in_election(self.election)) context['candidates'] = sorted(current_candidates, key=lambda c: c.last_name) context['show_retract_result'] = any( c.get_elected(self.election) is not None for c in context['candidates']) context['show_confirm_result'] = any( c.get_elected(self.election) is None for c in context['candidates']) context['add_candidate_form'] = NewPersonForm( election=self.election, initial={ ('constituency_' + self.election): post_id, ('standing_' + self.election): 'standing', }, hidden_post_widget=True, ) return context
'-ne-distribution-map(\.svg|/)?$', views.new_england_distribution_map, name='ne-distribution-map'), url(r'^maps/(?P<genus>[^/-]+)-(?P<epithet>[^/]+)' '-na-distribution-map(\.svg|/)?$', views.north_american_distribution_map, name='na-distribution-map'), url(r'^$', views.nonexistent, name='api-base'), # helps compute base URL ] # We only use caching if memcached itself is configured; otherwise, we # assume that the developer does not really intend caching to take # place. if 'memcache' in settings.CACHES['default']['BACKEND']: one_hour = 60 * 60 browsercache = cache_control(maxage=one_hour) memcache = cache_page(one_hour) both = lambda view: browsercache(memcache(view)) else: browsercache = lambda view: view memcache = lambda view: view both = lambda view: view urlpatterns.extend([ url(r'^glossaryblob/$', both(views.glossary_blob)), url(r'^hierarchy/$', both(views.hierarchy)), url(r'^sections/$', both(views.sections)), url(r'^dkey-images/([-\w\d]+)/$', both(views.dkey_images)), url(r'^families/([\w]+)/$', both(views.family)), url(r'^genera/([\w]+)/$', both(views.genus)), url(r'^species/([\w-]+)/$', browsercache(views.species)),
HardLoginRequiredMixin, SoftLoginRequiredMixin, GlobalOrObjectPermissionRequiredMixin, ) from agir.lib.http import add_query_params_to_url from .view_mixins import ( ReactBaseView, SimpleOpengraphMixin, ObjectOpengraphMixin, ) from ..events.views.event_views import EventDetailMixin from ..groups.views.public_views import SupportGroupDetailMixin from ..lib.utils import generate_token_params from ..msgs.models import SupportGroupMessage cache_decorators = [cache.cache_page(30), cache.cache_control(public=True)] class BasicOpenGraphMixin(SimpleOpengraphMixin): meta_title = "Action Populaire" meta_description = ( "Action Populaire est le réseau social d'action de la campagne de Jean-Luc Mélenchon pour " "l'élection présidentielle de 2022. ") meta_type = "website" meta_image = static("front/assets/og_image_NSP.jpg") ## BASE VIEWS class BaseAppView(BasicOpenGraphMixin, ReactBaseView):
Context: fatpage `staticpages.fatpages` object """ if not url.endswith('/') and settings.APPEND_SLASH: return HttpResponseRedirect("%s/" % request.path) if not url.startswith('/'): url = "/" + url f = get_object_or_404(FatPage, url__exact=url) return render_fatpage(request, f) # If a default Cache-Header Max-Age is defined in the settings # Apply it to Fatpages if hasattr(settings, 'CACHE_HEADER_MAX_AGE'): from django.views.decorators.cache import cache_control fatpage = cache_control(must_revalidate=True, max_age=settings.CACHE_HEADER_MAX_AGE)(fatpage) @csrf_protect def render_fatpage(request, f): """ Internal interface to the fat page view. """ # If registration is required for accessing this page, and the user isn't # logged in, redirect to the login page. if f.registration_required and not request.user.is_authenticated(): from django.contrib.auth.views import redirect_to_login return redirect_to_login(request.path) if f.template_name: t = loader.select_template((f.template_name, DEFAULT_TEMPLATE)) else:
path('', views.index, name='index'), path('app', views.app, name='app'), path('bubble_chart_act', views.bubble_chart_act, name='bubble_chart_act'), url(r'searchBubbleAct/(?P<pk>\d+)/(?P<pk_alt>\d+)/$',views.searchBubbleAct, name='searchBubbleAct'), path('sdg', views.sdg, name='sdg'), path('ihe', views.ihe, name='ihe'), path('svm_universal', views.universal_SVM, name='universal_SVM'), path('universal_SVM_IHE', views.universal_SVM_IHE, name='universal_SVM_IHE'), path('iheVisualisation', views.iheVisualisation, name='iheVisualisation'), path('sdgVisualisation', views.sdgVisualisation, name='sdgVisualisation'), path('tableauVisualisation', views.tableauVisualisation, name='tableauVisualisation'), path('module/<str:pk>', views.module, name='module'), path('publication/<str:pk>', views.publication, name='publication'), path('exportMod', views.export_modules_csv, name='export_modules_csv'), path('exportPub', views.export_publications_csv,name='export_publications_csv'), path('export_ihe_csv', views.export_ihe_csv, name='export_ihe_csv'), path('manual_add', views.manual_add, name='manual_add'), # path('auth', views.auth, name='auth'), # path('idp/profile/SAML2/Redirect/SSO', views.redirect, name='redirect'), # Matches any html file # re_path(r'^.*\.*', views.pages, name='pages'), ] if settings.DEBUG: urlpatterns += static(settings.STATIC_URL, view=cache_control(no_cache=True, must_revalidate=True)(serve))
class CoursewareIndex(View): """ View class for the Courseware page. """ @cached_property def enable_anonymous_courseware_access(self): waffle_flag = CourseWaffleFlag(WaffleFlagNamespace(name='seo'), 'enable_anonymous_courseware_access') return waffle_flag.is_enabled(self.course_key) @method_decorator(ensure_csrf_cookie) @method_decorator( cache_control(no_cache=True, no_store=True, must_revalidate=True)) @method_decorator(ensure_valid_course_key) @method_decorator(data_sharing_consent_required) def get(self, request, course_id, chapter=None, section=None, position=None): """ Displays courseware accordion and associated content. If course, chapter, and section are all specified, renders the page, or returns an error if they are invalid. If section is not specified, displays the accordion opened to the right chapter. If neither chapter or section are specified, displays the user's most recent chapter, or the first chapter if this is the user's first visit. Arguments: request: HTTP request course_id (unicode): course id chapter (unicode): chapter url_name section (unicode): section url_name position (unicode): position in module, eg of <sequential> module """ self.course_key = CourseKey.from_string(course_id) if not (request.user.is_authenticated or self.enable_anonymous_courseware_access): return redirect_to_login(request.get_full_path()) self.original_chapter_url_name = chapter self.original_section_url_name = section self.chapter_url_name = chapter self.section_url_name = section self.position = position self.chapter, self.section = None, None self.course = None self.url = request.path try: set_custom_metrics_for_course_key(self.course_key) self._clean_position() with modulestore().bulk_operations(self.course_key): self.course = get_course_with_access( request.user, 'load', self.course_key, depth=CONTENT_DEPTH, check_if_enrolled=not self. enable_anonymous_courseware_access, ) self.is_staff = has_access(request.user, 'staff', self.course) self._setup_masquerade_for_effective_user() return self.render(request) except Exception as exception: # pylint: disable=broad-except return CourseTabView.handle_exceptions(request, self.course, exception) def _setup_masquerade_for_effective_user(self): """ Setup the masquerade information to allow the request to be processed for the requested effective user. """ self.real_user = self.request.user self.masquerade, self.effective_user = setup_masquerade( self.request, self.course_key, self.is_staff, reset_masquerade_data=True) # Set the user in the request to the effective user. self.request.user = self.effective_user def render(self, request): """ Render the index page. """ self._redirect_if_needed_to_pay_for_course() self._prefetch_and_bind_course(request) if self.course.has_children_at_depth(CONTENT_DEPTH): self._reset_section_to_exam_if_required() self.chapter = self._find_chapter() self.section = self._find_section() if self.chapter and self.section: self._redirect_if_not_requested_section() self._save_positions() self._prefetch_and_bind_section() if not request.user.is_authenticated: qs = urllib.urlencode({ 'course_id': self.course_key, 'enrollment_action': 'enroll', 'email_opt_in': False, }) PageLevelMessages.register_warning_message( request, Text( _("You are not signed in. To see additional course content, {sign_in_link} or " "{register_link}, and enroll in this course.")).format( sign_in_link=HTML( '<a href="{url}">{sign_in_label}</a>').format( sign_in_label=_('sign in'), url='{}?{}'.format(reverse('signin_user'), qs), ), register_link=HTML( '<a href="/{url}">{register_label}</a>').format( register_label=_('register'), url='{}?{}'.format(reverse('register_user'), qs), ), )) return render_to_response('courseware/courseware.html', self._create_courseware_context(request)) def _redirect_if_not_requested_section(self): """ If the resulting section and chapter are different from what was initially requested, redirect back to the index page, but with an updated URL that includes the correct section and chapter values. We do this so that our analytics events and error logs have the appropriate URLs. """ if (self.chapter.url_name != self.original_chapter_url_name or (self.original_section_url_name and self.section.url_name != self.original_section_url_name)): raise CourseAccessRedirect( reverse( 'courseware_section', kwargs={ 'course_id': unicode(self.course_key), 'chapter': self.chapter.url_name, 'section': self.section.url_name, }, )) def _clean_position(self): """ Verify that the given position is an integer. If it is not positive, set it to 1. """ if self.position is not None: try: self.position = max(int(self.position), 1) except ValueError: raise Http404(u"Position {} is not an integer!".format( self.position)) def _redirect_if_needed_to_pay_for_course(self): """ Redirect to dashboard if the course is blocked due to non-payment. """ redeemed_registration_codes = [] if self.request.user.is_authenticated: self.real_user = User.objects.prefetch_related("groups").get( id=self.real_user.id) redeemed_registration_codes = CourseRegistrationCode.objects.filter( course_id=self.course_key, registrationcoderedemption__redeemed_by=self.real_user) if is_course_blocked(self.request, redeemed_registration_codes, self.course_key): # registration codes may be generated via Bulk Purchase Scenario # we have to check only for the invoice generated registration codes # that their invoice is valid or not # TODO Update message to account for the fact that the user is not authenticated. log.warning( u'User %s cannot access the course %s because payment has not yet been received', self.real_user, unicode(self.course_key), ) raise CourseAccessRedirect(reverse('dashboard')) def _reset_section_to_exam_if_required(self): """ Check to see if an Entrance Exam is required for the user. """ if not user_can_skip_entrance_exam(self.effective_user, self.course): exam_chapter = get_entrance_exam_content(self.effective_user, self.course) if exam_chapter and exam_chapter.get_children(): exam_section = exam_chapter.get_children()[0] if exam_section: self.chapter_url_name = exam_chapter.url_name self.section_url_name = exam_section.url_name def _get_language_preference(self): """ Returns the preferred language for the actual user making the request. """ language_preference = settings.LANGUAGE_CODE if self.request.user.is_authenticated: language_preference = get_user_preference(self.real_user, LANGUAGE_KEY) return language_preference def _is_masquerading_as_student(self): """ Returns whether the current request is masquerading as a student. """ return self.masquerade and self.masquerade.role == 'student' def _is_masquerading_as_specific_student(self): """ Returns whether the current request is masqueurading as a specific student. """ return self._is_masquerading_as_student() and self.masquerade.user_name def _find_block(self, parent, url_name, block_type, min_depth=None): """ Finds the block in the parent with the specified url_name. If not found, calls get_current_child on the parent. """ child = None if url_name: child = parent.get_child_by( lambda m: m.location.block_id == url_name) if not child: # User may be trying to access a child that isn't live yet if not self._is_masquerading_as_student(): raise Http404( 'No {block_type} found with name {url_name}'.format( block_type=block_type, url_name=url_name, )) elif min_depth and not child.has_children_at_depth(min_depth - 1): child = None if not child: child = get_current_child( parent, min_depth=min_depth, requested_child=self.request.GET.get("child")) return child def _find_chapter(self): """ Finds the requested chapter. """ return self._find_block(self.course, self.chapter_url_name, 'chapter', CONTENT_DEPTH - 1) def _find_section(self): """ Finds the requested section. """ if self.chapter: return self._find_block(self.chapter, self.section_url_name, 'section') def _prefetch_and_bind_course(self, request): """ Prefetches all descendant data for the requested section and sets up the runtime, which binds the request user to the section. """ self.field_data_cache = FieldDataCache.cache_for_descriptor_descendents( self.course_key, self.effective_user, self.course, depth=CONTENT_DEPTH, read_only=CrawlersConfig.is_crawler(request), ) self.course = get_module_for_descriptor( self.effective_user, self.request, self.course, self.field_data_cache, self.course_key, course=self.course, ) def _prefetch_and_bind_section(self): """ Prefetches all descendant data for the requested section and sets up the runtime, which binds the request user to the section. """ # Pre-fetch all descendant data self.section = modulestore().get_item(self.section.location, depth=None, lazy=False) self.field_data_cache.add_descriptor_descendents(self.section, depth=None) # Bind section to user self.section = get_module_for_descriptor( self.effective_user, self.request, self.section, self.field_data_cache, self.course_key, self.position, course=self.course, ) def _save_positions(self): """ Save where we are in the course and chapter. """ save_child_position(self.course, self.chapter_url_name) save_child_position(self.chapter, self.section_url_name) def _create_courseware_context(self, request): """ Returns and creates the rendering context for the courseware. Also returns the table of contents for the courseware. """ course_url_name = default_course_url_name(self.course.id) course_url = reverse(course_url_name, kwargs={'course_id': unicode(self.course.id)}) courseware_context = { 'csrf': csrf(self.request)['csrf_token'], 'course': self.course, 'course_url': course_url, 'chapter': self.chapter, 'section': self.section, 'init': '', 'fragment': Fragment(), 'staff_access': self.is_staff, 'masquerade': self.masquerade, 'supports_preview_menu': True, 'studio_url': get_studio_url(self.course, 'course'), 'xqa_server': settings.FEATURES.get('XQA_SERVER', "http://your_xqa_server.com"), 'bookmarks_api_url': reverse('bookmarks'), 'language_preference': self._get_language_preference(), 'disable_optimizely': not WaffleSwitchNamespace('RET').is_enabled( 'enable_optimizely_in_courseware'), 'section_title': None, 'sequence_title': None, 'disable_accordion': COURSE_OUTLINE_PAGE_FLAG.is_enabled(self.course.id), } courseware_context.update( get_experiment_user_metadata_context( self.course, self.effective_user, )) table_of_contents = toc_for_course( self.effective_user, self.request, self.course, self.chapter_url_name, self.section_url_name, self.field_data_cache, ) courseware_context['accordion'] = render_accordion( self.request, self.course, table_of_contents['chapters'], ) courseware_context['course_sock_fragment'] = CourseSockFragmentView( ).render_to_fragment(request, course=self.course) # entrance exam data self._add_entrance_exam_to_context(courseware_context) # staff masquerading data if not check_course_open_for_learner(self.effective_user, self.course): # Disable student view button if user is staff and # course is not yet visible to students. courseware_context['disable_student_access'] = True courseware_context['supports_preview_menu'] = False if self.section: # chromeless data if self.section.chrome: chrome = [ s.strip() for s in self.section.chrome.lower().split(",") ] if 'accordion' not in chrome: courseware_context['disable_accordion'] = True if 'tabs' not in chrome: courseware_context['disable_tabs'] = True # default tab if self.section.default_tab: courseware_context['default_tab'] = self.section.default_tab # section data courseware_context[ 'section_title'] = self.section.display_name_with_default section_context = self._create_section_context( table_of_contents['previous_of_active_section'], table_of_contents['next_of_active_section'], ) courseware_context['fragment'] = self.section.render( STUDENT_VIEW, section_context) if self.section.position and self.section.has_children: self._add_sequence_title_to_context(courseware_context) return courseware_context def _add_sequence_title_to_context(self, courseware_context): """ Adds sequence title to the given context. If we're rendering a section with some display items, but position exceeds the length of the displayable items, default the position to the first element. """ display_items = self.section.get_display_items() if not display_items: return if self.section.position > len(display_items): self.section.position = 1 courseware_context['sequence_title'] = display_items[ self.section.position - 1].display_name_with_default def _add_entrance_exam_to_context(self, courseware_context): """ Adds entrance exam related information to the given context. """ if course_has_entrance_exam(self.course) and getattr( self.chapter, 'is_entrance_exam', False): courseware_context[ 'entrance_exam_passed'] = user_has_passed_entrance_exam( self.effective_user, self.course) courseware_context[ 'entrance_exam_current_score'] = get_entrance_exam_score_ratio( CourseGradeFactory().read(self.effective_user, self.course), get_entrance_exam_usage_key(self.course), ) def _create_section_context(self, previous_of_active_section, next_of_active_section): """ Returns and creates the rendering context for the section. """ def _compute_section_url(section_info, requested_child): """ Returns the section URL for the given section_info with the given child parameter. """ return "{url}?child={requested_child}".format( url=reverse( 'courseware_section', args=[ unicode(self.course_key), section_info['chapter_url_name'], section_info['url_name'] ], ), requested_child=requested_child, ) # NOTE (CCB): Pull the position from the URL for un-authenticated users. Otherwise, pull the saved # state from the data store. position = None if self.request.user.is_authenticated else self.position section_context = { 'activate_block_id': self.request.GET.get('activate_block_id'), 'requested_child': self.request.GET.get("child"), 'progress_url': reverse('progress', kwargs={'course_id': unicode(self.course_key)}), 'user_authenticated': self.request.user.is_authenticated, 'position': position, } if previous_of_active_section: section_context['prev_url'] = _compute_section_url( previous_of_active_section, 'last') if next_of_active_section: section_context['next_url'] = _compute_section_url( next_of_active_section, 'first') # sections can hide data that masquerading staff should see when debugging issues with specific students section_context[ 'specific_masquerade'] = self._is_masquerading_as_specific_student( ) return section_context
def get_context_data(self, *args, **kwargs): per_page = 10 offset = int(self.kwargs.get("offset")) context = super(SpecialCoverageLoadMoreView, self).get_context_data() context["content_list"] = self.special_coverage.get_content( published=self.show_published_only())[offset:offset + per_page] return context class SpecialCoverageVideoView(SpecialCoverageView): def get_context_data(self, *args, **kwargs): context = super(SpecialCoverageVideoView, self).get_context_data() video_id = int(self.kwargs.get('video_id')) if video_id not in self.special_coverage.videos: raise Http404( 'Video with id={} not in SpecialCoverage'.format(video_id)) context['current_video'] = video_id return context special_coverage = cache_control(max_age=600)(SpecialCoverageView.as_view()) special_coverage_load_more = cache_control(max_age=600)( SpecialCoverageLoadMoreView.as_view()) special_coverage_video = cache_control(max_age=600)( SpecialCoverageVideoView.as_view())
1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.conf.urls import url, include 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) """ from django.conf.urls import url from django.contrib import admin from django.views.decorators.cache import cache_control from piston.resource import Resource from mysite.handlers import TestHandler1, TestHandler2, TestHandler3, TestHandler4 cached_resource = cache_control(public=False, maxage=0, s_maxage=0, no_cache=True, must_revalidate=True) def create_resource(Handler): resource = cached_resource(Resource(Handler)) return resource testhandler1=create_resource(TestHandler1) testhandler2=create_resource(TestHandler2) testhandler3=create_resource(TestHandler3) testhandler4=create_resource(TestHandler4) urlpatterns = [ # url(r'^admin/', admin.site.urls), url(r'^hello', testhandler1, name='testhandler1'), url(r'^hi', testhandler2, name='testhandler2'), url(r'^ola', testhandler3, name='testhandle3'),
class BallotPaperView(TemplateView): template_name = "elections/ballot_view.html" @method_decorator(cache_control(max_age=(60 * 20))) def dispatch(self, *args, **kwargs): return super().dispatch(*args, **kwargs) def get_context_data(self, **kwargs): from candidates.election_specific import shorten_post_label context = super().get_context_data(**kwargs) context["post_election"] = get_object_or_404( PostExtraElection.objects.all().select_related("post", "election"), ballot_paper_id=context["election"], ) mp_post = context["post_election"].post context["election"] = election = context["post_election"].election context["post_id"] = post_id = mp_post.slug context["post_obj"] = mp_post documents_by_type = {} # Make sure that every available document type has a key in # the dictionary, even if there are no such documents. doc_lookup = { t[0]: (t[1], t[2]) for t in OfficialDocument.DOCUMENT_TYPES } for t in doc_lookup.values(): documents_by_type[t] = [] documents_for_post = OfficialDocument.objects.filter( post_election=context["post_election"]) for od in documents_for_post: documents_by_type[doc_lookup[od.document_type]].append(od) context["official_documents"] = documents_by_type.items() context["some_official_documents"] = documents_for_post.count() context["post_label"] = mp_post.label context["post_label_shorter"] = shorten_post_label( context["post_label"]) context["redirect_after_login"] = context[ "post_election"].get_absolute_url() context["post_data"] = {"id": mp_post.slug, "label": mp_post.label} pee = context["post_election"] context["candidates_locked"] = pee.candidates_locked context["has_lock_suggestion"] = SuggestedPostLock.objects.filter( postextraelection=pee).exists() if self.request.user.is_authenticated: context[ "current_user_suggested_lock"] = SuggestedPostLock.objects.filter( user=self.request.user, postextraelection=pee).exists() context["suggest_lock_form"] = SuggestedPostLockForm( initial={"postextraelection": pee}) if self.request.user.is_authenticated: context[ "user_has_suggested_lock"] = SuggestedPostLock.objects.filter( user=self.request.user, postextraelection=pee).exists() context["lock_form"] = ToggleLockForm( initial={ "post_id": post_id, "lock": not context["candidates_locked"], }) context["candidate_list_edits_allowed"] = get_edits_allowed( self.request.user, context["candidates_locked"]) extra_qs = Membership.objects.select_related("post_election__election") current_candidacies, past_candidacies = split_candidacies( election, mp_post.memberships.select_related("person", "party").all(), ) area_2015_map = { "WMC:E14000824": "65693", "WMC:E14000825": "65633", "WMC:E14000826": "65735", "WMC:E14000827": "65556", "WMC:E14000820": "65657", "WMC:E14000821": "65953", "WMC:E14000822": "66076", "WMC:E14000823": "66038", "WMC:E14000828": "65815", "WMC:E14000829": "65696", "WMC:E14000948": "65829", "WMC:E14000543": "66006", "WMC:E14000810": "65647", "WMC:E14000813": "65718", "WMC:E14000540": "65662", "WMC:E14000699": "65857", "WMC:E14000751": "66069", "WMC:E14000546": "65711", "WMC:S14000048": "14445", "WMC:S14000049": "14446", "WMC:E14000912": "65889", "WMC:E14000913": "65891", "WMC:E14000914": "66027", "WMC:E14000915": "65763", "WMC:E14000916": "65706", "WMC:E14000917": "65842", "WMC:S14000040": "14436", "WMC:S14000041": "14437", "WMC:S14000042": "14438", "WMC:S14000043": "14439", "WMC:S14000044": "14440", "WMC:S14000045": "14441", "WMC:S14000046": "14442", "WMC:S14000047": "14443", "WMC:E14000727": "65576", "WMC:E14000726": "65836", "WMC:E14000725": "65915", "WMC:E14000724": "65671", "WMC:E14000723": "65599", "WMC:E14000649": "65636", "WMC:E14000721": "65752", "WMC:E14000720": "65550", "WMC:E14000644": "65926", "WMC:E14000645": "65835", "WMC:E14000646": "65771", "WMC:E14000690": "65816", "WMC:E14000640": "65734", "WMC:W07000063": "66111", "WMC:E14000642": "66030", "WMC:E14000643": "66057", "WMC:E14001034": "65629", "WMC:E14001035": "65758", "WMC:E14001036": "65851", "WMC:E14001037": "65963", "WMC:E14001030": "66047", "WMC:E14001031": "65716", "WMC:E14001032": "66058", "WMC:E14001033": "65873", "WMC:E14000544": "65898", "WMC:E14001038": "65742", "WMC:E14001039": "65612", "WMC:E14000965": "66067", "WMC:E14000964": "65854", "WMC:E14000967": "65960", "WMC:E14000966": "65907", "WMC:S14000039": "14435", "WMC:S14000038": "14434", "WMC:E14000963": "65732", "WMC:E14000962": "66073", "WMC:S14000035": "14431", "WMC:S14000034": "14430", "WMC:S14000037": "14433", "WMC:S14000036": "14432", "WMC:E14000969": "65606", "WMC:E14000968": "65571", "WMC:S14000033": "14429", "WMC:S14000032": "14428", "WMC:E14000639": "65759", "WMC:E14000731": "65650", "WMC:W07000072": "66093", "WMC:E14000868": "65663", "WMC:E14000869": "65653", "WMC:W07000077": "66097", "WMC:W07000049": "66101", "WMC:E14000860": "65822", "WMC:E14000861": "66059", "WMC:E14000862": "65910", "WMC:E14000863": "65768", "WMC:E14000864": "65634", "WMC:E14000865": "65559", "WMC:E14000866": "65643", "WMC:E14000867": "65945", "WMC:W07000062": "66121", "WMC:E14000631": "65801", "WMC:N06000006": "66129", "WMC:N06000007": "66130", "WMC:W07000066": "66109", "WMC:N06000001": "66124", "WMC:N06000002": "66125", "WMC:N06000003": "66126", "WMC:W07000068": "66088", "WMC:W07000069": "66082", "WMC:N06000008": "66131", "WMC:N06000009": "66132", "WMC:E14000819": "65998", "WMC:E14000818": "65888", "WMC:E14000549": "65731", "WMC:E14000548": "65751", "WMC:E14000547": "65798", "WMC:E14000814": "66007", "WMC:E14000545": "65623", "WMC:E14000816": "65949", "WMC:E14000811": "65772", "WMC:E14000542": "66012", "WMC:E14000541": "65665", "WMC:E14000812": "65932", "WMC:E14000600": "66009", "WMC:E14000601": "66031", "WMC:E14000602": "65574", "WMC:E14000603": "65852", "WMC:E14000604": "65954", "WMC:E14000605": "65617", "WMC:E14000606": "65639", "WMC:E14000607": "65849", "WMC:E14000608": "65909", "WMC:E14000609": "65846", "WMC:E14000929": "65920", "WMC:E14000928": "65986", "WMC:E14000921": "65601", "WMC:E14000920": "65793", "WMC:E14000923": "65549", "WMC:E14000654": "65603", "WMC:E14000925": "65959", "WMC:E14000924": "65632", "WMC:E14000927": "65610", "WMC:E14000926": "65563", "WMC:E14000778": "65941", "WMC:E14000779": "65866", "WMC:E14000774": "66053", "WMC:E14000775": "65869", "WMC:E14000776": "65568", "WMC:E14000777": "65765", "WMC:E14000770": "65778", "WMC:E14000771": "65709", "WMC:E14000772": "65618", "WMC:E14000773": "65984", "WMC:E14000675": "65701", "WMC:E14000674": "65755", "WMC:E14000677": "65823", "WMC:E14000676": "65794", "WMC:E14000671": "65806", "WMC:E14000670": "65555", "WMC:E14000673": "65808", "WMC:E14000672": "66054", "WMC:E14000679": "65573", "WMC:E14000678": "65813", "WMC:E14001009": "65733", "WMC:E14001008": "65825", "WMC:E14001005": "65782", "WMC:E14001004": "65660", "WMC:E14001007": "65613", "WMC:E14001006": "65868", "WMC:E14001001": "65810", "WMC:E14001000": "65904", "WMC:E14001003": "65659", "WMC:E14001002": "66074", "WMC:E14000733": "65990", "WMC:E14000781": "65988", "WMC:E14000780": "66068", "WMC:E14000783": "65604", "WMC:E14000782": "65807", "WMC:E14000785": "65978", "WMC:E14000784": "65587", "WMC:E14000787": "65705", "WMC:E14000786": "66020", "WMC:E14000789": "66041", "WMC:E14000788": "65616", "WMC:E14000851": "65760", "WMC:E14000850": "65817", "WMC:E14000581": "65821", "WMC:E14000580": "65738", "WMC:E14000587": "65694", "WMC:E14000586": "65697", "WMC:E14000585": "65933", "WMC:E14000856": "65859", "WMC:E14000859": "65713", "WMC:E14000858": "65776", "WMC:E14000589": "66036", "WMC:E14000588": "65995", "WMC:S14000028": "14424", "WMC:S14000029": "14425", "WMC:S14000020": "14417", "WMC:S14000021": "14418", "WMC:E14000922": "65741", "WMC:E14000739": "65967", "WMC:E14000730": "65578", "WMC:E14000638": "65885", "WMC:E14000732": "65796", "WMC:E14000746": "65850", "WMC:E14000734": "65674", "WMC:E14000735": "65640", "WMC:E14000736": "65699", "WMC:E14000737": "65912", "WMC:E14000738": "65557", "WMC:E14000630": "65946", "WMC:E14000633": "65558", "WMC:E14000632": "65980", "WMC:E14000635": "65940", "WMC:E14000634": "65721", "WMC:E14000637": "65792", "WMC:E14000636": "65886", "WMC:E14001041": "65921", "WMC:E14001040": "65827", "WMC:E14001043": "65847", "WMC:E14001042": "65552", "WMC:E14001045": "65831", "WMC:E14001044": "65897", "WMC:E14001047": "66039", "WMC:E14001046": "65622", "WMC:E14001049": "65777", "WMC:E14001048": "65774", "WMC:E14000910": "65654", "WMC:E14000911": "65688", "WMC:E14000976": "65609", "WMC:E14000977": "65648", "WMC:E14000974": "65770", "WMC:E14000975": "65950", "WMC:E14000972": "65710", "WMC:E14000973": "65783", "WMC:E14000970": "65641", "WMC:E14000971": "65908", "WMC:S14000026": "14423", "WMC:S14000027": "14444", "WMC:S14000024": "14421", "WMC:S14000025": "14422", "WMC:S14000022": "14419", "WMC:S14000023": "14420", "WMC:E14000978": "66042", "WMC:E14000979": "65911", "WMC:E14000745": "65994", "WMC:E14000744": "66003", "WMC:E14000747": "65814", "WMC:E14000830": "65862", "WMC:E14000741": "65754", "WMC:E14000740": "66018", "WMC:E14000743": "65582", "WMC:E14000742": "65786", "WMC:E14000749": "65724", "WMC:E14000748": "66052", "WMC:E14000918": "65698", "WMC:E14000919": "65957", "WMC:E14000895": "65722", "WMC:E14000894": "65579", "WMC:E14000897": "65843", "WMC:E14000896": "65598", "WMC:E14000891": "66032", "WMC:E14000890": "65982", "WMC:E14000893": "66005", "WMC:E14000892": "65700", "WMC:W07000057": "66108", "WMC:W07000056": "66099", "WMC:W07000055": "66094", "WMC:W07000054": "66084", "WMC:E14000899": "65584", "WMC:E14000898": "66043", "WMC:W07000051": "66120", "WMC:W07000050": "66090", "WMC:E14000648": "65590", "WMC:E14000722": "65971", "WMC:E14000558": "65611", "WMC:E14000559": "65581", "WMC:E14000808": "65834", "WMC:E14000809": "65819", "WMC:E14000806": "65661", "WMC:E14000807": "66048", "WMC:E14000804": "65936", "WMC:E14000553": "65689", "WMC:E14000554": "65726", "WMC:E14000803": "65901", "WMC:E14000556": "65934", "WMC:E14000801": "66080", "WMC:E14000647": "65893", "WMC:W07000059": "66100", "WMC:W07000058": "66085", "WMC:E14000641": "66021", "WMC:E14000729": "65875", "WMC:E14000728": "65675", "WMC:E14000949": "65848", "WMC:W07000053": "66104", "WMC:W07000052": "66092", "WMC:E14000758": "65899", "WMC:E14000652": "65781", "WMC:E14000938": "65684", "WMC:E14000939": "66051", "WMC:E14000932": "65812", "WMC:E14000933": "65962", "WMC:E14000930": "65680", "WMC:E14000931": "65879", "WMC:E14000936": "65788", "WMC:E14000937": "65997", "WMC:E14000934": "65922", "WMC:E14000935": "65762", "WMC:E14000709": "65870", "WMC:E14000708": "65900", "WMC:E14000701": "65655", "WMC:E14000700": "65764", "WMC:E14000703": "65938", "WMC:E14000702": "65865", "WMC:E14000705": "66064", "WMC:E14000704": "65779", "WMC:E14000707": "65952", "WMC:E14000706": "65955", "WMC:E14000666": "65746", "WMC:E14000667": "65553", "WMC:E14000664": "65799", "WMC:E14000665": "65723", "WMC:E14000662": "66070", "WMC:E14000663": "65863", "WMC:E14000660": "66025", "WMC:E14000661": "65924", "WMC:E14000668": "65621", "WMC:E14000669": "65672", "WMC:E14001018": "65916", "WMC:E14001019": "65608", "WMC:E14001016": "66079", "WMC:E14001017": "65874", "WMC:E14001014": "65631", "WMC:E14001015": "65638", "WMC:E14001012": "65832", "WMC:E14001013": "65651", "WMC:E14001010": "65635", "WMC:E14001011": "65890", "WMC:W07000061": "66096", "WMC:E14000989": "65992", "WMC:E14000988": "65767", "WMC:E14000987": "65964", "WMC:E14000986": "65880", "WMC:E14000985": "65703", "WMC:E14000984": "66040", "WMC:E14000983": "65747", "WMC:E14000982": "65586", "WMC:E14000981": "65607", "WMC:E14000980": "65858", "WMC:E14000815": "66061", "WMC:E14000792": "65704", "WMC:E14000793": "66066", "WMC:E14000790": "66013", "WMC:E14000791": "66046", "WMC:E14000796": "65766", "WMC:E14000797": "65785", "WMC:E14000794": "65970", "WMC:E14000795": "65644", "WMC:E14000798": "65987", "WMC:E14000799": "65690", "WMC:E14000598": "65787", "WMC:E14000599": "65839", "WMC:E14000594": "65685", "WMC:E14000595": "65620", "WMC:E14000596": "66000", "WMC:E14000597": "65844", "WMC:E14000590": "65670", "WMC:E14000591": "66065", "WMC:E14000592": "65595", "WMC:E14000593": "65958", "WMC:E14000842": "66063", "WMC:E14000843": "65676", "WMC:E14000840": "65745", "WMC:E14000841": "65855", "WMC:E14000846": "65619", "WMC:E14000847": "65642", "WMC:E14000844": "65729", "WMC:E14000845": "65840", "WMC:E14000848": "65872", "WMC:E14000849": "66017", "WMC:E14000817": "65999", "WMC:E14000561": "65667", "WMC:E14000560": "65931", "WMC:E14000563": "66072", "WMC:E14000562": "65597", "WMC:E14000565": "65966", "WMC:E14000564": "65989", "WMC:E14000567": "65804", "WMC:E14000566": "66028", "WMC:E14000569": "65820", "WMC:E14000568": "65707", "WMC:E14000961": "65591", "WMC:E14000960": "65715", "WMC:E14000628": "65797", "WMC:E14000629": "65818", "WMC:E14000622": "65914", "WMC:E14000623": "65749", "WMC:E14000620": "65929", "WMC:E14000621": "65972", "WMC:E14000626": "66075", "WMC:E14000627": "65727", "WMC:E14000624": "65748", "WMC:E14000625": "65615", "WMC:S14000031": "14427", "WMC:S14000030": "14426", "WMC:E14001052": "65577", "WMC:E14001053": "65625", "WMC:E14001050": "65593", "WMC:E14001051": "65948", "WMC:E14001056": "66010", "WMC:E14001057": "65695", "WMC:E14001054": "65757", "WMC:E14001055": "65562", "WMC:E14001058": "66078", "WMC:E14001059": "65669", "WMC:E14000943": "65951", "WMC:E14000942": "65902", "WMC:E14000941": "65666", "WMC:E14000940": "66034", "WMC:E14000947": "65800", "WMC:E14000946": "65614", "WMC:E14000945": "65943", "WMC:E14000944": "65719", "WMC:S14000013": "14410", "WMC:S14000012": "14409", "WMC:S14000011": "14408", "WMC:S14000010": "14407", "WMC:S14000017": "14414", "WMC:S14000016": "14413", "WMC:S14000015": "14412", "WMC:S14000014": "14411", "WMC:E14000756": "65624", "WMC:E14000757": "65592", "WMC:E14000754": "65947", "WMC:E14000755": "65691", "WMC:E14000752": "65883", "WMC:E14000753": "65717", "WMC:E14000750": "65824", "WMC:E14000698": "66033", "WMC:E14000697": "66062", "WMC:E14000696": "66023", "WMC:E14000695": "65743", "WMC:E14000694": "65803", "WMC:E14000693": "66044", "WMC:E14000692": "65567", "WMC:E14000691": "66050", "WMC:E14000759": "65630", "WMC:E14000886": "65637", "WMC:E14000887": "66045", "WMC:E14000884": "66014", "WMC:E14000885": "65673", "WMC:E14000882": "65917", "WMC:E14000883": "65566", "WMC:E14000880": "65737", "WMC:E14000881": "65860", "WMC:W07000041": "66115", "WMC:W07000042": "66112", "WMC:W07000043": "66103", "WMC:W07000044": "66113", "WMC:W07000045": "66117", "WMC:E14000888": "65795", "WMC:E14000889": "65973", "WMC:E14000550": "65687", "WMC:E14000551": "65725", "WMC:E14000552": "65561", "WMC:E14000805": "65645", "WMC:E14000901": "65884", "WMC:E14000802": "65896", "WMC:E14000900": "66077", "WMC:E14000555": "65853", "WMC:E14000800": "65887", "WMC:E14000557": "65845", "WMC:E14000688": "65991", "WMC:E14000689": "65677", "WMC:E14000839": "65702", "WMC:E14000838": "65658", "WMC:S14000051": "14448", "WMC:E14000833": "65664", "WMC:E14000832": "65594", "WMC:E14000831": "66055", "WMC:E14000908": "65736", "WMC:E14000837": "65602", "WMC:E14000836": "65918", "WMC:E14000835": "65828", "WMC:E14000834": "65861", "WMC:E14000583": "66071", "WMC:E14000582": "65969", "WMC:E14000853": "65720", "WMC:E14000852": "65605", "WMC:E14000855": "65565", "WMC:W07000048": "66091", "WMC:E14000682": "65780", "WMC:E14000854": "66024", "WMC:E14000683": "65979", "WMC:E14000857": "65894", "WMC:E14000584": "65993", "WMC:E14000538": "65739", "WMC:E14000539": "66008", "WMC:E14000536": "65811", "WMC:E14000537": "66056", "WMC:E14000534": "65784", "WMC:E14000535": "65895", "WMC:E14000532": "65892", "WMC:E14000533": "65809", "WMC:E14000530": "65730", "WMC:E14000531": "65773", "WMC:E14000907": "65589", "WMC:E14000906": "65681", "WMC:E14000905": "65656", "WMC:E14000904": "66029", "WMC:E14000903": "65930", "WMC:E14000902": "66019", "WMC:S14000059": "14456", "WMC:S14000058": "14455", "WMC:S14000057": "14454", "WMC:S14000056": "14453", "WMC:S14000055": "14452", "WMC:S14000054": "14451", "WMC:S14000053": "14450", "WMC:S14000052": "14449", "WMC:E14000909": "65833", "WMC:S14000050": "14447", "WMC:E14000718": "65837", "WMC:E14000719": "65838", "WMC:E14000712": "65996", "WMC:E14000713": "65928", "WMC:E14000710": "65551", "WMC:E14000711": "65864", "WMC:E14000716": "65600", "WMC:E14000717": "65627", "WMC:E14000714": "65683", "WMC:E14000715": "65944", "WMC:E14000653": "65572", "WMC:N06000004": "66127", "WMC:E14000651": "65877", "WMC:E14000650": "65575", "WMC:E14000657": "65985", "WMC:E14000656": "65923", "WMC:E14000655": "65867", "WMC:N06000005": "66128", "WMC:E14000659": "66011", "WMC:E14000658": "65802", "WMC:W07000060": "66116", "WMC:E14001029": "65983", "WMC:E14001028": "65588", "WMC:E14001023": "65961", "WMC:E14001022": "66004", "WMC:E14001021": "65626", "WMC:E14001020": "66049", "WMC:E14001027": "65740", "WMC:E14001026": "65560", "WMC:E14001025": "65830", "WMC:W07000067": "66089", "WMC:W07000064": "66110", "WMC:W07000065": "66102", "WMC:E14000998": "65554", "WMC:E14000999": "65692", "WMC:E14000990": "65976", "WMC:E14000991": "65789", "WMC:E14000992": "65977", "WMC:E14000993": "65686", "WMC:E14000994": "65905", "WMC:E14000995": "65919", "WMC:E14000996": "65761", "WMC:E14000997": "65744", "WMC:E14000879": "65974", "WMC:E14000878": "65649", "WMC:E14000877": "66081", "WMC:E14000876": "66002", "WMC:E14000875": "65668", "WMC:E14000874": "65564", "WMC:E14000873": "66060", "WMC:E14000872": "65682", "WMC:E14000871": "66022", "WMC:E14000870": "65903", "WMC:W07000071": "66086", "WMC:W07000070": "66105", "WMC:W07000073": "66095", "WMC:N06000018": "66141", "WMC:W07000075": "66087", "WMC:W07000074": "66107", "WMC:W07000046": "66083", "WMC:W07000076": "66106", "WMC:N06000013": "66136", "WMC:N06000012": "66135", "WMC:N06000011": "66134", "WMC:N06000010": "66133", "WMC:N06000017": "66140", "WMC:N06000016": "66139", "WMC:N06000015": "66138", "WMC:N06000014": "66137", "WMC:W07000047": "66118", "WMC:E14001024": "65769", "WMC:W07000080": "66119", "WMC:E14000572": "65750", "WMC:E14000573": "65679", "WMC:E14000570": "65981", "WMC:E14000571": "65583", "WMC:E14000576": "65841", "WMC:E14000577": "65628", "WMC:E14000574": "65805", "WMC:E14000575": "65753", "WMC:E14000578": "65646", "WMC:E14000579": "65712", "WMC:W07000079": "66114", "WMC:E14000617": "65927", "WMC:E14000616": "65826", "WMC:E14000615": "65913", "WMC:E14000614": "65906", "WMC:E14000613": "66035", "WMC:E14000612": "65975", "WMC:E14000611": "66015", "WMC:E14000610": "65708", "WMC:E14000619": "65878", "WMC:E14000618": "65790", "WMC:W07000078": "66098", "WMC:E14001062": "66037", "WMC:E14001061": "65965", "WMC:E14001060": "65935", "WMC:E14000958": "65728", "WMC:E14000959": "65942", "WMC:E14000954": "65956", "WMC:E14000955": "66016", "WMC:E14000956": "65580", "WMC:E14000957": "65876", "WMC:E14000950": "65775", "WMC:E14000951": "65596", "WMC:E14000952": "65652", "WMC:E14000953": "65678", "WMC:S14000004": "14401", "WMC:S14000005": "14402", "WMC:S14000006": "14403", "WMC:S14000007": "14404", "WMC:S14000001": "14398", "WMC:S14000002": "14399", "WMC:S14000003": "14400", "WMC:S14000008": "14405", "WMC:S14000009": "14406", "WMC:E14000763": "65937", "WMC:E14000762": "65791", "WMC:E14000761": "65925", "WMC:E14000760": "65585", "WMC:E14000767": "65968", "WMC:E14000766": "65871", "WMC:E14000765": "66026", "WMC:E14000764": "65882", "WMC:E14000680": "65569", "WMC:E14000681": "65856", "WMC:E14000769": "66001", "WMC:E14000768": "65939", "WMC:E14000684": "65714", "WMC:E14000685": "65881", "WMC:E14000686": "65756", "WMC:E14000687": "65570", "WMC:S14000019": "14416", "WMC:S14000018": "14415", } # HACK slug = area_2015_map.get(mp_post.slug) current_candidacies_2015 = set() past_candidacies_2015 = set() if slug: other_post = Post.objects.get(slug=slug) current_candidacies_2015, past_candidacies_2015 = split_candidacies( election, other_post.memberships.select_related( "person", "party").filter(post_election__election__slug="2015"), ) # HACK past_candidacies = past_candidacies.union(past_candidacies_2015) current_candidates = {c.person for c in current_candidacies} past_candidates = {c.person for c in past_candidacies} current_candidates = current_candidates.union( {c.person for c in current_candidacies_2015}) past_candidates = past_candidates.union( {c.person for c in past_candidacies_2015}) other_candidates = past_candidates - current_candidates elected, unelected = split_by_elected(election, current_candidacies) # Now split those candidates into those that we know aren't # standing again, and those that we just don't know about. not_standing_candidates = { p for p in other_candidates if election in p.not_standing.all() } might_stand_candidates = { p for p in other_candidates if election not in p.not_standing.all() } might_stand_candidates = { p for p in might_stand_candidates if p.death_date == "" } not_standing_candidacies = [ c for c in past_candidacies if c.person in not_standing_candidates ] might_stand_candidacies = [ c for c in past_candidacies if c.person in might_stand_candidates ] context["candidacies_not_standing_again"] = group_candidates_by_party( election, not_standing_candidacies) context["candidacies_might_stand_again"] = group_candidates_by_party( election, might_stand_candidacies) context["elected"] = group_candidates_by_party(election, elected, show_all=True) context["unelected"] = group_candidates_by_party(election, unelected) context["has_elected"] = (len(context["elected"]["parties_and_people"]) > 0) context["show_retract_result"] = False number_of_winners = 0 for c in current_candidacies: if c.elected: number_of_winners += 1 if c.elected is not None: context["show_retract_result"] = True max_winners = get_max_winners(pee) context["show_confirm_result"] = bool(max_winners) context["add_candidate_form"] = NewPersonForm( election=election.slug, initial={ ("constituency_" + election.slug): post_id, ("standing_" + election.slug): "standing", }, hidden_post_widget=True, ) context = get_person_form_fields(context, context["add_candidate_form"]) context["identifiers_formset"] = PersonIdentifierFormsetFactory() return context
from persistent_messages.models import Message from rest_framework import viewsets, permissions from rest_framework.decorators import action from rest_framework.renderers import BrowsableAPIRenderer from rest_framework.response import Response from astrobin_apps_notifications.api.filters import NotificationFilter from astrobin_apps_notifications.api.serializers import NotificationSerializer, NoticeSettingSerializers, \ NoticeTypeSerializer from common.permissions import ReadOnly from common.services.caching_service import CachingService @method_decorator([ last_modified(CachingService.get_last_notification_time), cache_control(private=True, no_cache=True), vary_on_headers('Cookie', 'Authorization') ], name='dispatch') class NotificationViewSet(viewsets.ModelViewSet): serializer_class = NotificationSerializer filter_class = NotificationFilter permission_classes = [permissions.IsAuthenticated] renderer_classes = [BrowsableAPIRenderer, CamelCaseJSONRenderer] parser_classes = [CamelCaseJSONParser] http_method_names = ['get', 'post', 'head', 'put'] def get_queryset(self): return Message.objects.filter( user=self.request.user).order_by('-created')
RedirectView.as_view(url=settings.STATIC_URL + "weblate-%(size)s.png", permanent=True), ), path( "apple-touch-icon.png", RedirectView.as_view(url=settings.STATIC_URL + "weblate-180.png", permanent=True), ), path( "favicon.ico", RedirectView.as_view(url=settings.STATIC_URL + "favicon.ico", permanent=True), ), path( "robots.txt", cache_control(max_age=86400)(TemplateView.as_view( template_name="robots.txt", content_type="text/plain")), ), path( "browserconfig.xml", cache_control(max_age=86400)( TemplateView.as_view(template_name="browserconfig.xml", content_type="application/xml")), ), path( "site.webmanifest", cache_control(max_age=86400)( TemplateView.as_view(template_name="site.webmanifest", content_type="application/json")), ), ]
full_decorator = compose( # django.views.decorators.http require_http_methods(["GET"]), require_GET, require_POST, require_safe, condition(lambda r: None, lambda r: None), # django.views.decorators.vary vary_on_headers('Accept-language'), vary_on_cookie, # django.views.decorators.cache cache_page(60 * 15), cache_control(private=True), never_cache, # django.contrib.auth.decorators # Apply user_passes_test twice to check #9474 user_passes_test(lambda u: True), login_required, permission_required('change_world'), # django.contrib.admin.views.decorators staff_member_required, # django.utils.functional allow_lazy, lazy, )
url(r'^login/$', jsonize_view(login), name='login'), # noqa url(r'^login/popup/end/$', views.LoginPopupEnd.as_view(), name='login_popup_end'), url(r'^logout/$', views.logout, name='logout'), url(r'^map/(?P<pk>\d+)/geojson/$', views.MapViewGeoJSON.as_view(), name='map_geojson'), url(r'^map/(?P<username>[-_\w]+)/(?P<slug>[-_\w]+)/$', views.MapOldUrl.as_view(), name='map_old_url'), url(r'^map/anonymous-edit/(?P<signature>.+)$', views.MapAnonymousEditUrl.as_view(), name='map_anonymous_edit_url'), url(r'^m/(?P<pk>\d+)/$', views.MapShortUrl.as_view(), name='map_short_url'), url(r'^pictogram/json/$', views.PictogramJSONList.as_view(), name='pictogram_list_json'), ) urlpatterns += decorated_patterns('', [cache_control(must_revalidate=True)], url(r'^datalayer/(?P<pk>[\d]+)/$', views.DataLayerView.as_view(), name='datalayer_view'), # noqa url(r'^datalayer/(?P<pk>[\d]+)/versions/$', views.DataLayerVersions.as_view(), name='datalayer_versions'), # noqa url(r'^datalayer/(?P<pk>[\d]+)/(?P<name>[_\w]+.geojson)$', views.DataLayerVersion.as_view(), name='datalayer_version'), # noqa ) urlpatterns += decorated_patterns('', [ensure_csrf_cookie, ], url(r'^map/(?P<slug>[-_\w]+)_(?P<pk>\d+)$', views.MapView.as_view(), name='map'), # noqa url(r'^map/new/$', views.MapNew.as_view(), name='map_new'), ) urlpatterns += decorated_patterns('', [login_required_if_not_anonymous_allowed, never_cache], # noqa url(r'^map/create/$', views.MapCreate.as_view(), name='map_create'), ) urlpatterns += decorated_patterns('', [map_permissions_check, never_cache, ], url(r'^map/(?P<map_id>[\d]+)/update/settings/$', views.MapUpdate.as_view(), # noqa name='map_update'),
from django.conf.urls import url from django.views.decorators.cache import cache_control from django.views.decorators.clickjacking import xframe_options_exempt from django.views.generic import TemplateView from .. import views L = getattr(settings, "DPASTE_SLUG_LENGTH", 4) config = apps.get_app_config("dpaste") urlpatterns = [ url(r"^$", views.SnippetView.as_view(), name="snippet_new"), url( r"^about/$", cache_control(max_age=config.CACHE_TIMEOUT)(TemplateView.as_view( template_name="dpaste/about.html", extra_context=config.extra_template_context, )), name="dpaste_about", ), url(r"^history/$", views.SnippetHistory.as_view(), name="snippet_history"), url( r"^(?P<snippet_id>[a-zA-Z0-9]{%d,})/?$" % L, views.SnippetDetailView.as_view(), name="snippet_details", ), url( r"^(?P<snippet_id>[a-zA-Z0-9]{%d,})/raw/?$" % L, views.SnippetRawView.as_view(), name="snippet_details_raw", ), url(
from django.conf.urls.defaults import * from piston.resource import Resource from api.handlers import PlaythingsHandler from django.views.decorators.cache import cache_control cached_resource = cache_control(static_root=True, maxage=300, s_maxage=3000) # cache resource (when enabled) play_resource = cached_resource(Resource(handler=PlaythingsHandler)) urlpatterns = patterns('', #url(r'^all\.(?P<emitter_format>.+)$', play_handler), url(r'^nearby/(?P<lat>.+)/(?P<lng>.+)/(?P<km>.+)\.(?P<emitter_format>.+)$', play_resource), )
class PersonView(TemplateView): template_name = 'candidates/person-view.html' @method_decorator(cache_control(max_age=(60 * 20))) def dispatch(self, *args, **kwargs): return super(PersonView, self).dispatch( *args, **kwargs ) def get_context_data(self, **kwargs): context = super(PersonView, self).get_context_data(**kwargs) path = self.person.extra.get_absolute_url() context['redirect_after_login'] = urlquote(path) context['canonical_url'] = self.request.build_absolute_uri(path) context['person'] = self.person elections_by_date = Election.objects.by_date().order_by('-election_date') # If there are lots of elections known to this site, don't # show a big list of elections they're not standing in - just # show those that they are standing in: if len(elections_by_date) > 2: context['elections_to_list'] = Election.objects.filter( candidacies__base__person=self.person ).order_by('-election_date') else: context['elections_to_list'] = elections_by_date context['last_candidacy'] = self.person.extra.last_candidacy context['election_to_show'] = None context['has_current_elections'] = any([ e.current for e in context['elections_to_list']]) context['simple_fields'] = [ field.name for field in SimplePopoloField.objects.all() ] personal_fields, demographic_fields = get_field_groupings() context['has_demographics'] = any( demographic in context['simple_fields'] for demographic in demographic_fields ) context['complex_fields'] = [ (field, getattr(self.person.extra, field.name)) for field in ComplexPopoloField.objects.all() ] context['extra_fields'] = get_extra_fields(self.person) return context def get(self, request, *args, **kwargs): person_id = self.kwargs['person_id'] try: self.person = Person.objects.select_related('extra'). \ prefetch_related('links', 'contact_details'). \ get(pk=person_id) except Person.DoesNotExist: try: return self.get_person_redirect(person_id) except PersonRedirect.DoesNotExist: raise Http404(_("No person found with ID {person_id}").format( person_id=person_id )) return super(PersonView, self).get(request, *args, **kwargs) def get_person_redirect(self, person_id): # If there's a PersonRedirect for this person ID, do the # redirect, otherwise process the GET request as usual. # try: new_person_id = PersonRedirect.objects.get( old_person_id=person_id ).new_person_id return HttpResponsePermanentRedirect( reverse('person-view', kwargs={ 'person_id': new_person_id, }) )
return r class Changesets(SignoffDataView): filename = 'l10n-changesets' def content(self, request, signoffs): sos = signoffs.annotate(tip=Max('push__changesets__id')) tips = dict(sos.values_list('locale__code', 'tip')) revs = Changeset.objects.filter(id__in=tips.values()) revmap = dict(revs.values_list('id', 'revision')) return ('%s %s\n' % (l, revmap[tips[l]][:12]) for l in sorted(tips.keys())) l10n_changesets = cache_control(max_age=60)(Changesets.as_view()) class ShippedLocales(SignoffDataView): filename = 'shipped-locales' def content(self, request, signoffs): sos = signoffs.values_list('locale__code', flat=True) locales = list(sos) + ['en-US'] def withPlatforms(loc): if loc == 'ja': return 'ja linux win32\n' if loc == 'ja-JP-mac': return 'ja-JP-mac osx\n' return loc + '\n'
return [ "instant_article/_instant_article_ad.html", ] def get_context_data(self, *args, **kwargs): context = super(InstantArticleAdView, self).get_context_data(*args, **kwargs) targeting = self.object.get_targeting() context["targeting"] = targeting context["targeting"]["dfp_position"] = self.request.GET.get("dfp_position", None) return context class InstantArticleAnalyticsView(InstantArticleContentView): def get_template_names(self): return [ "core/_analytics.html", ] def get_context_data(self, *args, **kwargs): context = super(InstantArticleAnalyticsView, self).get_context_data(*args, **kwargs) context["fire_pageview"] = True context["platform"] = "Instant Articles" context["path"] = self.request.GET.get("path", "") return context instant_article_rss = cache_control(max_age=600)(InstantArticleRSSView.as_view()) instant_article = cache_control(max_age=600)(InstantArticleContentView.as_view()) instant_article_analytics = cache_control(max_age=600)(InstantArticleAnalyticsView.as_view()) instant_article_ad = cache_control(max_age=600)(InstantArticleAdView.as_view())
'template_name': 'wagtailadmin/account/password_reset/form.html', 'email_template_name': 'wagtailadmin/account/password_reset/email.txt', 'subject_template_name': 'wagtailadmin/account/password_reset/email_subject.txt', 'password_reset_form': PasswordResetForm, 'post_reset_redirect': 'wagtailadmin_password_reset_done', }, name='wagtailadmin_password_reset' ), url( r'^password_reset/done/$', 'django.contrib.auth.views.password_reset_done', { 'template_name': 'wagtailadmin/account/password_reset/done.html' }, name='wagtailadmin_password_reset_done' ), url( r'^password_reset/confirm/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', 'django.contrib.auth.views.password_reset_confirm', { 'template_name': 'wagtailadmin/account/password_reset/confirm.html', 'post_reset_redirect': 'wagtailadmin_password_reset_complete', }, name='wagtailadmin_password_reset_confirm', ), url( r'^password_reset/complete/$', 'django.contrib.auth.views.password_reset_complete', { 'template_name': 'wagtailadmin/account/password_reset/complete.html' }, name='wagtailadmin_password_reset_complete' ), ] # Decorate all views with cache settings to prevent caching urlpatterns = decorate_urlpatterns(urlpatterns, cache_control(private=True, no_cache=True, no_store=True, max_age=0) )
from django.urls import path from . import views from django.conf.urls import url from django.contrib import admin from django.views.decorators.cache import cache_control from django.views.generic import TemplateView urlpatterns = [ path('', views.index), url(r'^sw_cached_site.js', cache_control(max_age=2592000)(TemplateView.as_view( template_name="sw_cached_site.js", content_type='application/javascript', )), name='sw_cached_site.js'), ]
from django.conf.urls import patterns, url from django.views.decorators.cache import cache_control from django.views.generic import TemplateView from . import views random_question = views.RandomQuestion.as_view() urlpatterns = patterns('', url(r'^$', TemplateView.as_view(template_name='index.html')), url(r'^questions/(?P<uuid>\w+)/$', cache_control(max_age=0)(random_question), name='random_question'), url(r'^questions/(?P<uuid>\w+)/submit/$', views.question_response, name='question_response'), )
"""Expected __doc__""" return HttpResponse('<html><body>dummy</body></html>') fully_decorated.anything = "Expected __dict__" # django.views.decorators.http fully_decorated = require_http_methods(["GET"])(fully_decorated) fully_decorated = require_GET(fully_decorated) fully_decorated = require_POST(fully_decorated) # django.views.decorators.vary fully_decorated = vary_on_headers('Accept-language')(fully_decorated) fully_decorated = vary_on_cookie(fully_decorated) # django.views.decorators.cache fully_decorated = cache_page(60*15)(fully_decorated) fully_decorated = cache_control(private=True)(fully_decorated) fully_decorated = never_cache(fully_decorated) # django.contrib.auth.decorators # Apply user_passes_test twice to check #9474 fully_decorated = user_passes_test(lambda u:True)(fully_decorated) fully_decorated = login_required(fully_decorated) fully_decorated = permission_required('change_world')(fully_decorated) # django.contrib.admin.views.decorators fully_decorated = staff_member_required(fully_decorated) # django.utils.functional fully_decorated = memoize(fully_decorated, {}, 1) fully_decorated = allow_lazy(fully_decorated) fully_decorated = lazy(fully_decorated)
"""logouttest URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/1.8/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') Including another URLconf 1. Add an import: from blog import urls as blog_urls 2. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls)) """ from django.conf.urls import include, url from django.contrib import admin from django.contrib.auth.views import logout from django.views.decorators.cache import cache_control from django.views.generic import TemplateView urlpatterns = [ url(r'^admin/', include(admin.site.urls)), # in production, Apache caches this site url(r'^logout/$', cache_control(max_age=60*60*24)(logout), name='logout'), url('^', include('django.contrib.auth.urls')), url('^$', TemplateView.as_view(template_name='home.html'), name='home') ]
from django.views.decorators.cache import cache_page, cache_control from django.views.generic.list_detail import object_detail from django.views.generic.simple import direct_to_template from django.db.models.signals import post_save from models import Theme from views import edit_theme from mdc3.decorators import better_cache theme_css = better_cache('theme-css', 600)(object_detail) def invalidate_theme(sender, instance, signal, *args, **kwargs): theme_css.invalidate(instance.id) post_save.connect(invalidate_theme, sender = Theme) default_cache_control = cache_control( max_age=604800, must_revalidate = False, ) urlpatterns = patterns('', url(r"^(?P<object_id>\d+)/$", default_cache_control(theme_css), { 'queryset' : Theme.objects , 'template_name' : 'themes/theme.css', 'mimetype' : 'text/css', }, name = 'theme-css'), url(r"^default/$", default_cache_control(cache_page(direct_to_template, 600)), { 'template' : 'themes/theme.css', 'mimetype': 'text/css', 'extra_context': { 'object': Theme(),
import logging from django.utils.decorators import method_decorator from django.views.decorators.cache import cache_control, cache_page from django.views.decorators.http import last_modified from django.views.decorators.vary import vary_on_cookie from django.views.generic import ListView from astrobin_apps_iotd.models import Iotd from astrobin_apps_iotd.services import IotdService from common.services.caching_service import CachingService log = logging.getLogger('apps') @method_decorator([ cache_page(3600), last_modified(CachingService.get_latest_iotd_datetime), cache_control(private=True), vary_on_cookie ], name='dispatch') class IotdArchiveView(ListView): model = Iotd template_name = 'astrobin_apps_iotd/iotd_archive.html' paginate_by = 30 def get_queryset(self): return IotdService().get_iotds()
from django.views.static import serve from django.views.decorators.cache import cache_control from django.http import HttpResponseServerError from django.template import loader, RequestContext from rooibos.ui.views import main from rooibos.access.views import login, logout from rooibos.legacy.views import legacy_viewer admin.autodiscover() apps = filter(lambda a: a.startswith('apps.'), settings.INSTALLED_APPS) apps_showcases = list(s[5:].replace('.', '-') + '-showcase.html' for s in apps) # Cache static files serve = cache_control(max_age=365 * 24 * 3600)(serve) def handler500_with_context(request): template = loader.get_template('500.html') return HttpResponseServerError(template.render(RequestContext(request))) handler404 = getattr(settings, 'HANDLER404', handler404) handler500 = getattr(settings, 'HANDLER500', handler500_with_context) def raise_exception(): raise Exception()
from django.conf import settings from django.db.models.loading import get_model from django.utils import timezone from django.views.decorators.cache import cache_control from bulbs.content.views import BaseContentDetailView LiveBlogModel = get_model(settings.BULBS_LIVEBLOG_MODEL) class LiveblogNewEntriesView(BaseContentDetailView): model = LiveBlogModel template_name = 'liveblog/new_entries.html' redirect_correct_path = False def get_context_data(self, object): context = {} if 'entry_ids' not in self.request.GET: raise ValueError('param "entry_ids" MUST be specified') parsed_entry_ids = [x.strip() for x in self.request.GET['entry_ids'].split(',')] context['entries'] = self.object.entries.filter( pk__in=parsed_entry_ids, published__lte=timezone.now()) return context liveblog_new_entries = cache_control(max_age=600)(LiveblogNewEntriesView.as_view())
INVALID_SERVICE = 'INVALID_SERVICE' INVALID_REQUEST = 'INVALID_REQUEST' INTERNAL_ERROR = 'INTERNAL_ERROR' ERROR_MESSAGES = ( (INVALID_TICKET, u'The provided ticket is invalid.'), (INVALID_SERVICE, u'Service is invalid'), (INVALID_REQUEST, u'Not all required parameters were sent.'), (INTERNAL_ERROR, u'An internal error occurred during ticket validation'), ) logger = logging.getLogger(__name__) _never_cache = cache_control(no_cache=True, must_revalidate=True) def never_cache(view_func): """ Decorator that adds headers to a response so that it will never be cached. """ @wraps(view_func, assigned=available_attrs(view_func)) def _wrapped_view_func(request, *args, **kwargs): response = view_func(request, *args, **kwargs) patch_cache_control(response, no_cache=True, must_revalidate=True, proxy_revalidate=True) response['Pragma'] = 'no-cache' return response return _wrapped_view_func
'object_list': queryset, 'cart_id': cart_id, 'cart_total': total } context_object_name = super().get_context_object_name(queryset) if context_object_name is not None: context[context_object_name] = queryset context.update(kwargs) return super().get_context_data(**context) class CheckoutView(BaseCartView): template_name = 'pages/cart.html' @method_decorator(cache_control(private=True), name='dispatch') class ShipmentView(BaseCartView): template_name = 'pages/shipment.html' @method_decorator(never_cache, name='dispatch') class PaymentView(BaseCartView): template_name = 'pages/payment.html' def post(self, request, **kwargs): payment.PreprocessPayment(request, set_in_session=True, shipping='standard') return render(request, self.template_name, super().get_context_data(**kwargs))
full_decorator = compose( # django.views.decorators.http require_http_methods(["GET"]), require_GET, require_POST, require_safe, condition(lambda r: None, lambda r: None), # django.views.decorators.vary vary_on_headers('Accept-language'), vary_on_cookie, # django.views.decorators.cache cache_page(60 * 15), cache_control(private=True), never_cache, # django.contrib.auth.decorators # Apply user_passes_test twice to check #9474 user_passes_test(lambda u: True), login_required, permission_required('change_world'), # django.contrib.admin.views.decorators staff_member_required, # django.utils.functional keep_lazy(HttpResponse), keep_lazy_text, lazy,
name='map_geojson'), url(r'^map/(?P<username>[-_\w]+)/(?P<slug>[-_\w]+)/$', views.MapOldUrl.as_view(), name='map_old_url'), url(r'^map/anonymous-edit/(?P<signature>.+)$', views.MapAnonymousEditUrl.as_view(), name='map_anonymous_edit_url'), url(r'^m/(?P<pk>\d+)/$', views.MapShortUrl.as_view(), name='map_short_url'), url(r'^pictogram/json/$', views.PictogramJSONList.as_view(), name='pictogram_list_json'), ) urlpatterns += decorated_patterns( '', [cache_control(must_revalidate=True)], url(r'^datalayer/(?P<pk>[\d]+)/$', views.DataLayerView.as_view(), name='datalayer_view'), # noqa url(r'^datalayer/(?P<pk>[\d]+)/versions/$', views.DataLayerVersions.as_view(), name='datalayer_versions'), # noqa url(r'^datalayer/(?P<pk>[\d]+)/(?P<name>[_\w]+.geojson)$', views.DataLayerVersion.as_view(), name='datalayer_version'), # noqa ) urlpatterns += decorated_patterns( '', [ ensure_csrf_cookie, ],
self.process_request(request) except BadRequestData, msg: return HttpResponseBadRequest(msg) try: data = self.get_data() except RuntimeError, msg: return HttpResponseBadRequest(str(msg)) content = self.content(request, *data) r = HttpResponse(content, content_type='text/plain; charset=utf-8') if self.filename: r['Content-Disposition'] = 'inline; filename="%s"' % self.filename r['Access-Control-Allow-Origin'] = '*' return r @class_decorator(cache_control(max_age=60)) class Changesets(SignoffDataView): filename = 'l10n-changesets' def content(self, request, signoffs): sos = signoffs.annotate(tip=Max('push__changesets__id')) tips = dict(sos.values_list('locale__code', 'tip')) revs = Changeset.objects.filter(id__in=tips.values()) revmap = dict(revs.values_list('id', 'revision')) return ('%s %s\n' % (l, revmap[tips[l]][:12]) for l in sorted(tips.keys())) l10n_changesets = Changesets.as_view() @class_decorator(cache_control(max_age=60))
'registrars_count': registrars_count, 'orgs_count': orgs_count, 'users_count': users_count, 'links_count': links_count, }) def stats(request): """ The global stats """ return render(request, 'stats.html') @if_anonymous( cache_control(max_age=settings.CACHE_MAX_AGES['single_permalink'])) @ratelimit(rate=settings.MINUTE_LIMIT, block=True, key=ratelimit_ip_key) @ratelimit(rate=settings.HOUR_LIMIT, block=True, key=ratelimit_ip_key) @ratelimit(rate=settings.DAY_LIMIT, block=True, key=ratelimit_ip_key) def single_permalink(request, guid): """ Given a Perma ID, serve it up. """ raw_user_agent = request.META.get('HTTP_USER_AGENT', '') # Create a canonical version of guid (non-alphanumerics removed, hyphens every 4 characters, uppercase), # and forward to that if it's different from current guid. canonical_guid = Link.get_canonical_guid(guid) # We only do the redirect if the correctly-formatted GUID actually exists -- # this prevents actual 404s from redirecting with weird formatting.
if self.special_coverage: context["targeting"]["dfp_specialcoverage"] = self.special_coverage.slug if self.special_coverage.tunic_campaign_id: context["targeting"]["dfp_campaign_id"] = self.special_coverage.tunic_campaign_id return context def show_published_only(self): """ Returns True if `full_preview` is not a query_parameter. Used to determine unpublished preview state. """ return bool("full_preview" not in self.request.GET) class SpecialCoverageVideoView(SpecialCoverageView): def get_context_data(self, *args, **kwargs): context = super(SpecialCoverageVideoView, self).get_context_data() video_id = int(self.kwargs.get('video_id')) if video_id not in self.special_coverage.videos: raise Http404('Video with id={} not in SpecialCoverage'.format(video_id)) context['current_video'] = video_id return context special_coverage = cache_control(max_age=600)(SpecialCoverageView.as_view()) special_coverage_video = cache_control(max_age=600)(SpecialCoverageVideoView.as_view())
autorespond.credentials for autorespond in self.queryset ] self.prefix = 'autorespond' def _construct_form(self, i, **kwargs): form = super(AutoResponseFormSet, self)._construct_form(i, **kwargs) form.fields['credentials'].queryset = self.credentials form.fields['credentials'].label_from_instance = lambda obj: obj.email if form.empty_permitted: del form.fields[DELETION_FIELD_NAME] return form @method_decorator(cache_control(public=True, max_age=3600), name='dispatch') class LoggedOutView(TemplateView): price = settings.PRICE_REPR trial_length = "%s day" % License.TRIAL_LENGTH.days template_name = 'logged_out.html' # TODO these shouldn't show the logged-in navbar so they can be cached class PrivacyView(TemplateView): template_name = 'privacy.html' class TermsView(TemplateView): template_name = 'terms.html'