def __call__(self, parser, token): tokens = token.contents.split() # Now tokens is a list like this: # ['get_comment_list', 'for', 'lcom.eventtimes', 'event.id', 'as', 'comment_list'] if not len(tokens) in (6, 7): raise template.TemplateSyntaxError, "%r tag requires 5 or 6 arguments" % tokens[0] if tokens[1] != 'for': raise template.TemplateSyntaxError, "Second argument in %r tag must be 'for'" % tokens[0] try: package, module = tokens[2].split('.') except ValueError: # unpack list of wrong size raise template.TemplateSyntaxError, "Third argument in %r tag must be in the format 'package.module'" % tokens[0] try: content_type = contenttypes.get_object(package__label__exact=package, python_module_name__exact=module) except contenttypes.ContentTypeDoesNotExist: raise template.TemplateSyntaxError, "%r tag has invalid content-type '%s.%s'" % (tokens[0], package, module) var_name, obj_id = None, None if tokens[3].isdigit(): obj_id = tokens[3] try: # ensure the object ID is valid content_type.get_object_for_this_type(pk=obj_id) except ObjectDoesNotExist: raise template.TemplateSyntaxError, "%r tag refers to %s object with ID %s, which doesn't exist" % (tokens[0], content_type.name, obj_id) else: var_name = tokens[3] if tokens[4] != 'as': raise template.TemplateSyntaxError, "Fourth argument in %r must be 'as'" % tokens[0] if len(tokens) == 7: if tokens[6] != 'reversed': raise template.TemplateSyntaxError, "Final argument in %r must be 'reversed' if given" % tokens[0] ordering = "-" else: ordering = "" return CommentListNode(package, module, var_name, obj_id, tokens[5], self.free, ordering)
def __call__(self, parser, token): tokens = token.contents.split() if len(tokens) < 4: raise template.TemplateSyntaxError, "%r tag requires at least 3 arguments" % tokens[0] if tokens[1] != 'for': raise template.TemplateSyntaxError, "Second argument in %r tag must be 'for'" % tokens[0] try: package, module = tokens[2].split('.') except ValueError: # unpack list of wrong size raise template.TemplateSyntaxError, "Third argument in %r tag must be in the format 'package.module'" % tokens[0] try: content_type = contenttypes.get_object(package__label__exact=package, python_module_name__exact=module) except contenttypes.ContentTypeDoesNotExist: raise template.TemplateSyntaxError, "%r tag has invalid content-type '%s.%s'" % (tokens[0], package, module) obj_id_lookup_var, obj_id = None, None if tokens[3].isdigit(): obj_id = tokens[3] try: # ensure the object ID is valid content_type.get_object_for_this_type(pk=obj_id) except ObjectDoesNotExist: raise template.TemplateSyntaxError, "%r tag refers to %s object with ID %s, which doesn't exist" % (tokens[0], content_type.name, obj_id) else: obj_id_lookup_var = tokens[3] kwargs = {} if len(tokens) > 4: if tokens[4] != 'with': raise template.TemplateSyntaxError, "Fourth argument in %r tag must be 'with'" % tokens[0] for option, args in zip(tokens[5::2], tokens[6::2]): if option in ('photos_optional', 'photos_required') and not self.free: # VALIDATION ############################################## option_list = args.split(',') if len(option_list) % 3 != 0: raise template.TemplateSyntaxError, "Incorrect number of comma-separated arguments to %r tag" % tokens[0] for opt in option_list[::3]: if not opt.isalnum(): raise template.TemplateSyntaxError, "Invalid photo directory name in %r tag: '%s'" % (tokens[0], opt) for opt in option_list[1::3] + option_list[2::3]: if not opt.isdigit() or not (comments.MIN_PHOTO_DIMENSION <= int(opt) <= comments.MAX_PHOTO_DIMENSION): raise template.TemplateSyntaxError, "Invalid photo dimension in %r tag: '%s'. Only values between %s and %s are allowed." % (tokens[0], opt, comments.MIN_PHOTO_DIMENSION, comments.MAX_PHOTO_DIMENSION) # VALIDATION ENDS ######################################### kwargs[option] = True kwargs['photo_options'] = args elif option in ('ratings_optional', 'ratings_required') and not self.free: # VALIDATION ############################################## if 2 < len(args.split('|')) > 9: raise template.TemplateSyntaxError, "Incorrect number of '%s' options in %r tag. Use between 2 and 8." % (option, tokens[0]) if re.match('^scale:\d+\-\d+\:$', args.split('|')[0]): raise template.TemplateSyntaxError, "Invalid 'scale' in %r tag's '%s' options" % (tokens[0], option) # VALIDATION ENDS ######################################### kwargs[option] = True kwargs['rating_options'] = args elif option in ('is_public'): kwargs[option] = (args == 'true') else: raise template.TemplateSyntaxError, "%r tag got invalid parameter '%s'" % (tokens[0], option) return CommentFormNode(content_type, obj_id_lookup_var, obj_id, self.free, **kwargs)
def comment_was_posted(request): """ Display "comment was posted" success page Templates: `comment_posted` Context: object The object the comment was posted on """ obj = None if request.GET.has_key('c'): content_type_id, object_id = request.GET['c'].split(':') try: content_type = contenttypes.get_object(pk=content_type_id) obj = content_type.get_object_for_this_type(pk=object_id) except ObjectDoesNotExist: pass return render_to_response('comments/posted', {'object': obj}, context_instance=DjangoContext(request))
def shortcut(request, content_type_id, object_id): "Redirect to an object's page based on a content-type ID and an object ID." # Look up the object, making sure it's got a get_absolute_url() function. try: content_type = contenttypes.get_object(pk=content_type_id) obj = content_type.get_object_for_this_type(pk=object_id) except ObjectDoesNotExist: raise Http404, "Content type %s object %s doesn't exist" % (content_type_id, object_id) try: absurl = obj.get_absolute_url() except AttributeError: raise Http404, "%s objects don't have get_absolute_url() methods" % content_type.name # Try to figure out the object's domain, so we can do a cross-site redirect # if necessary. # If the object actually defines a domain, we're done. if absurl.startswith('http://'): return httpwrappers.HttpResponseRedirect(absurl) object_domain = None # Next, look for an many-to-many relationship to sites if hasattr(obj, 'get_site_list'): site_list = obj.get_site_list() if site_list: object_domain = site_list[0].domain # Next, look for a many-to-one relationship to sites elif hasattr(obj, 'get_site'): try: object_domain = obj.get_site().domain except sites.SiteDoesNotExist: pass # Then, fall back to the current site (if possible) else: try: object_domain = sites.get_current().domain except sites.SiteDoesNotExist: # Finally, give up and use a URL without the domain name return httpwrappers.HttpResponseRedirect(obj.get_absolute_url()) return httpwrappers.HttpResponseRedirect('http://%s%s' % (object_domain, obj.get_absolute_url()))
def post_free_comment(request): """ Post a free comment (not requiring a log in) Redirects to `comments.comments.comment_was_posted` view on success. Templates: `comment_free_preview` Context: comment comment being posted comment_form comment form object options comment options target comment target hash security hash (must be included in a posted form to succesfully post a comment). """ if not request.POST: raise Http404, "Only POSTs are allowed" try: options, target, security_hash = request.POST['options'], request.POST['target'], request.POST['gonzo'] except KeyError: raise Http404, "One or more of the required fields wasn't submitted" if comments.get_security_hash(options, '', '', target) != security_hash: raise Http404, "Somebody tampered with the comment form (security violation)" content_type_id, object_id = target.split(':') # target is something like '52:5157' content_type = contenttypes.get_object(pk=content_type_id) try: obj = content_type.get_object_for_this_type(pk=object_id) except ObjectDoesNotExist: raise Http404, "The comment form had an invalid 'target' parameter -- the object ID was invalid" option_list = options.split(',') new_data = request.POST.copy() new_data['content_type_id'] = content_type_id new_data['object_id'] = object_id new_data['ip_address'] = request.META['REMOTE_ADDR'] new_data['is_public'] = comments.IS_PUBLIC in option_list manipulator = PublicFreeCommentManipulator() errors = manipulator.get_validation_errors(new_data) if errors or request.POST.has_key('preview'): comment = errors and '' or manipulator.get_comment(new_data) return render_to_response('comments/free_preview', { 'comment': comment, 'comment_form': formfields.FormWrapper(manipulator, new_data, errors), 'options': options, 'target': target, 'hash': security_hash, }, context_instance=DjangoContext(request)) elif request.POST.has_key('post'): # If the IP is banned, mail the admins, do NOT save the comment, and # serve up the "Thanks for posting" page as if the comment WAS posted. if request.META['REMOTE_ADDR'] in BANNED_IPS: from django.core.mail import mail_admins mail_admins("Practical joker", str(request.POST) + "\n\n" + str(request.META)) else: manipulator.do_html2python(new_data) comment = manipulator.save(new_data) return HttpResponseRedirect("/comments/posted/?c=%s:%s" % (content_type_id, object_id)) else: raise Http404, "The comment form didn't provide either 'preview' or 'post'"
def post_comment(request): """ Post a comment Redirects to the `comments.comments.comment_was_posted` view upon success. Templates: `comment_preview` Context: comment the comment being posted comment_form the comment form options comment options target comment target hash security hash (must be included in a posted form to succesfully post a comment). rating_options comment ratings options ratings_optional are ratings optional? ratings_required are ratings required? rating_range range of ratings rating_choices choice of ratings """ if not request.POST: raise Http404, "Only POSTs are allowed" try: options, target, security_hash = request.POST['options'], request.POST['target'], request.POST['gonzo'] except KeyError: raise Http404, "One or more of the required fields wasn't submitted" photo_options = request.POST.get('photo_options', '') rating_options = normalize_newlines(request.POST.get('rating_options', '')) if comments.get_security_hash(options, photo_options, rating_options, target) != security_hash: raise Http404, "Somebody tampered with the comment form (security violation)" # Now we can be assured the data is valid. if rating_options: rating_range, rating_choices = comments.get_rating_options(base64.decodestring(rating_options)) else: rating_range, rating_choices = [], [] content_type_id, object_id = target.split(':') # target is something like '52:5157' try: obj = contenttypes.get_object(pk=content_type_id).get_object_for_this_type(pk=object_id) except ObjectDoesNotExist: raise Http404, "The comment form had an invalid 'target' parameter -- the object ID was invalid" option_list = options.split(',') # options is something like 'pa,ra' new_data = request.POST.copy() new_data['content_type_id'] = content_type_id new_data['object_id'] = object_id new_data['ip_address'] = request.META.get('REMOTE_ADDR') new_data['is_public'] = comments.IS_PUBLIC in option_list manipulator = PublicCommentManipulator(request.user, ratings_required=comments.RATINGS_REQUIRED in option_list, ratings_range=rating_range, num_rating_choices=len(rating_choices)) errors = manipulator.get_validation_errors(new_data) # If user gave correct username/password and wasn't already logged in, log them in # so they don't have to enter a username/password again. if manipulator.get_user() and new_data.has_key('password') and manipulator.get_user().check_password(new_data['password']): request.session[users.SESSION_KEY] = manipulator.get_user_id() if errors or request.POST.has_key('preview'): class CommentFormWrapper(formfields.FormWrapper): def __init__(self, manipulator, new_data, errors, rating_choices): formfields.FormWrapper.__init__(self, manipulator, new_data, errors) self.rating_choices = rating_choices def ratings(self): field_list = [self['rating%d' % (i+1)] for i in range(len(rating_choices))] for i, f in enumerate(field_list): f.choice = rating_choices[i] return field_list comment = errors and '' or manipulator.get_comment(new_data) comment_form = CommentFormWrapper(manipulator, new_data, errors, rating_choices) return render_to_response('comments/preview', { 'comment': comment, 'comment_form': comment_form, 'options': options, 'target': target, 'hash': security_hash, 'rating_options': rating_options, 'ratings_optional': comments.RATINGS_OPTIONAL in option_list, 'ratings_required': comments.RATINGS_REQUIRED in option_list, 'rating_range': rating_range, 'rating_choices': rating_choices, }, context_instance=DjangoContext(request)) elif request.POST.has_key('post'): # If the IP is banned, mail the admins, do NOT save the comment, and # serve up the "Thanks for posting" page as if the comment WAS posted. if request.META['REMOTE_ADDR'] in BANNED_IPS: mail_admins("Banned IP attempted to post comment", str(request.POST) + "\n\n" + str(request.META)) else: manipulator.do_html2python(new_data) comment = manipulator.save(new_data) return HttpResponseRedirect("/comments/posted/?c=%s:%s" % (content_type_id, object_id)) else: raise Http404, "The comment form didn't provide either 'preview' or 'post'"