Changeset 1713

Show
Ignore:
Timestamp:
07/24/08 16:16:21 (11 months ago)
Author:
JensDiemer
Message:

blog update 2:

  • nicer "create blog entry" form (existing tags can be selected)
  • some code cleanup
  • try to verify tag slugs
Location:
trunk/pylucid
Files:
5 modified

Legend:

Unmodified
Added
Removed
  • trunk/pylucid/media/PyLucid/internal_page/blog/display_blog.html

    r1712 r1713  
    100100{% endfor %} 
    101101 
     102{% if back_url %}<p><a href="{{ back_url }}" class="action_link">&laquo;  Display all blog entries</a></p>{% endif %} 
     103{% if create_url %}<p><a href="{{ create_url }}" class="action_link">create a new blog entry</a></p>{% endif %} 
     104 
    102105<fieldset class="tag_cloud"><legend>{% trans 'tag cloud' %}</legend> 
    103106    <ul> 
     
    121124    </ul> 
    122125</fieldset> 
    123  
    124 {% if back_url %}<p><a href="{{ back_url }}" class="action_link">&laquo;  Display all blog entries</a></p>{% endif %} 
    125 {% if create_url %}<p><a href="{{ create_url }}" class="action_link">create a new blog entry</a></p>{% endif %} 
  • trunk/pylucid/PyLucid/plugins_internal/blog/blog.py

    r1712 r1713  
    244244        """ 
    245245        slug = urlargs.strip("/") 
    246         # TODO: Verify tag 
    247         tag_obj = BlogTag.objects.get(slug = slug) 
     246        # TODO: Exist there a better way to verify the tag slug? 
     247        for char in (" ", "/", ";"): 
     248            if char in slug: 
     249                return self.error( 
     250                    _("Wrong URL."), "Not allowed character in tag name!" 
     251                ) 
     252 
     253        try: 
     254            tag_obj = BlogTag.objects.safe_get(slug) 
     255        except BlogTag.DoesNotExist, err: 
     256            return self.error( 
     257                _("Wrong URL."), "tag '%s' unknown: %s" % (slug, err) 
     258            ) 
    248259 
    249260        self.current_page.title += ( 
     
    278289            #self.page_msg(self.request.POST) 
    279290            if form.is_valid(): 
     291                new_tags = form.cleaned_data.pop("new_tags") # ListCharField 
    280292                if blog_obj == None: 
    281293                    # a new blog entry should be created 
    282294                    blog_obj = BlogEntry( 
    283                         headline = form.cleaned_data["headline"], 
    284                         content = form.cleaned_data["content"], 
    285                         markup = form.cleaned_data["markup"], 
     295                        headline  = form.cleaned_data["headline"], 
     296                        content   = form.cleaned_data["content"], 
     297                        markup    = form.cleaned_data["markup"], 
    286298                        is_public = form.cleaned_data["is_public"], 
    287                         createby = self.request.user, 
     299                        createby  = self.request.user, 
    288300                    ) 
    289301                    blog_obj.save() 
    290302                    self.page_msg.green("New blog entry created.") 
    291                     tags_string = form.cleaned_data["tags"] 
    292303                else: 
    293304                    # Update a existing blog entry 
    294                     tags_string = form.cleaned_data.pop("tags") 
    295305                    self.page_msg.green("Update existing blog entry.") 
    296306                    blog_obj.lastupdateby = self.request.user 
     
    298308                        setattr(blog_obj, k, v) 
    299309 
    300                 tag_objects, new_tags = BlogTag.objects.get_or_creates( 
    301                     tags_string 
    302                 ) 
    303                 if new_tags: 
    304                     self.page_msg(_("New tags created: %s") % new_tags) 
    305  
    306                 # Add many-to-many 
    307                 for tag in tag_objects: 
    308                     blog_obj.tags.add(tag) 
     310                if new_tags != []: 
     311                    # There are new tags to create incoming via ListCharField 
     312                    # Create the new tags and add them to the blog entry 
     313                    new_tags = BlogTag.objects.add_new_tags(new_tags, blog_obj) 
     314                    if new_tags: 
     315                        self.page_msg(_("New tags created: %s") % new_tags) 
    309316 
    310317                blog_obj.save() 
     
    314321            if blog_obj == None: 
    315322                context["legend"] = _("Create a new blog entry") 
    316  
    317323                form = BlogEntryForm( 
    318                     initial={ 
    319                         "markup": self.preferences["default_markup"], 
    320                     } 
     324                    initial={"markup": self.preferences["default_markup"],} 
    321325                ) 
    322326            else: 
    323327                context["legend"] = _("Edit a existing blog entry") 
    324                 form = BlogEntryForm( 
    325                     instance=blog_obj, 
    326                     initial={"tags":blog_obj.get_tag_string()} 
    327                 ) 
     328                form = BlogEntryForm(instance=blog_obj) 
    328329 
    329330        context["form"]= form 
     
    471472                "Comment contains mod_keyword: '%s'" % mod_keyword 
    472473            ) 
    473  
    474474 
    475475 
     
    499499            is_public = False 
    500500        else: 
    501             self.submit_msg("Blog comment published.") 
    502             mail_title = _("Blog comment published.") 
     501            msg = _("Blog comment published.") 
     502            self.submit_msg(msg) 
     503            mail_title = msg 
    503504            is_public = True 
    504505 
     
    618619            return 
    619620 
    620 #        CommentForm = AdminCommentForm 
    621 # 
    622 # 
    623 #        CommentForm = forms.form_for_instance( 
    624 #            instance=comment_entry#, form=BlogCommentForm 
    625 #        ) 
    626  
    627621        blog_entry = comment_entry.blog_entry # ForeignKey("BlogEntry") 
    628622 
    629623        if self.request.method == 'POST': 
    630 #            form = CommentForm(self.request.POST) 
    631624            form = AdminCommentForm(self.request.POST, instance=comment_entry) 
    632625            #self.page_msg(self.request.POST) 
     
    641634                ) 
    642635        else: 
    643 #            form = CommentForm() 
    644636            form = AdminCommentForm(instance=comment_entry) 
    645637 
     
    717709        Build the tag cloud context. 
    718710        """ 
    719         tags = BlogTag.objects.all() 
    720  
    721         frequency = set() 
    722         # get the counter information 
    723         for tag in tags: 
    724             count = tag.blogentry_set.count() 
    725             tag.count = count 
    726             #self.page_msg(tag, count) 
    727             frequency.add(count) 
    728  
    729         min_frequency = float(min(frequency)) 
    730         max_frequency = float(max(frequency)) 
     711        tags, min_frequency, max_frequency = BlogTag.objects.get_tag_info() 
     712 
    731713        diff_frequency = float(max_frequency - min_frequency) 
    732714 
     
    757739        feed_name = raw_feed_name.strip("/") 
    758740 
    759         # Verify the feed name 
     741        # Verify raw_feed_name 
    760742        try: 
    761743            self._feed_info_by_filename(feed_name) 
     
    799781            tag_slug = feed_name[len(TAG_FEED_PREFIX):] 
    800782            try: 
    801                 tag_obj = BlogTag.objects.get(slug = tag_slug) 
     783                tag_obj = BlogTag.objects.safe_get(tag_slug) 
    802784            except BlogTag.DoesNotExist, err: 
    803785                raise WrongFeedFilename( 
  • trunk/pylucid/PyLucid/plugins_internal/blog/forms.py

    r1701 r1713  
    2020from django.utils.translation import ugettext as _ 
    2121 
    22 from PyLucid.tools.newforms_utils import StripedCharField 
     22from PyLucid.tools.newforms_utils import StripedCharField, ListCharField 
    2323 
    2424# from blog plugin 
     
    5858        ) 
    5959 
    60  
    6160class BlogEntryForm(forms.ModelForm): 
    6261    """ 
    6362    Form for create/edit a blog entry. 
    6463    """ 
    65     content = forms.CharField( 
    66         widget=forms.Textarea(attrs={'rows': '15'}), 
     64    new_tags = ListCharField( # New field, (no field from BlogEntry model) 
     65        max_length=255, required=False, 
     66        help_text=_( 
     67            "New tags for this entry, if there not in the list above" 
     68            " (separated by spaces.)" 
     69        ), 
     70        widget=forms.TextInput(attrs={'class':'bigger'}), 
    6771    ) 
    6872 
    69     tags = forms.CharField( 
    70         max_length=255, required=False, 
    71         help_text=_("Tags for this entry (separated by spaces.)"), 
    72         widget=forms.TextInput(attrs={'class':'bigger'}), 
    73     ) 
     73    def __init__(self, *args, **kwargs): 
     74        """ 
     75        set some widget attributes 
     76        """ 
     77        super(BlogEntryForm, self).__init__(*args, **kwargs) 
     78 
     79        # Limit the MultipleChoiceField size 
     80        # Is there are a better way to do this? See: 
     81        # http://www.python-forum.de/topic-15503.html (de) 
     82        self.fields['tags'].widget.attrs["size"] = 7 
     83 
     84        # makes the content textarea bigger 
     85        self.fields['content'].widget.attrs["rows"] = 15 
     86 
    7487    class Meta: 
    7588        model = BlogEntry 
  • trunk/pylucid/PyLucid/plugins_internal/blog/models.py

    r1712 r1713  
    8787 
    8888 
     89BAD_TAG_SLUG_CHARS = (" ", "/", ";") 
    8990class BlogTagManager(models.Manager): 
    9091    """ 
    9192    Manager for BlogTag model. 
    9293    """ 
    93     def get_or_creates(self, tags_string): 
    94         """ 
    95         split the given tags_string and create not existing tags. 
    96         returns a list of all tag model objects and a list of all created tags. 
    97         """ 
    98         tag_objects = [] 
     94    def safe_get(self, slug): 
     95        """ 
     96        Get a tag entry by slug. Try to verify the slug before we access the 
     97        database. Should be used, if the slug comes from the Client 
     98        (e.g. via url) 
     99        TODO: Exist there a better way to verify the tag slug? 
     100        """ 
     101        slug = slug.strip("/") # If it comes from url args 
     102        for char in BAD_TAG_SLUG_CHARS: 
     103            if char in slug: 
     104                raise self.model.DoesNotExist("Not allowed character in tag name!") 
     105 
     106        return self.model.objects.get(slug = slug) 
     107 
     108    def add_new_tags(self, tag_list, blog_obj): 
     109        """ 
     110        Create new tag entries and add it to the given blog entry. 
     111        Skip existing tags and returns only the new created tags. 
     112        """ 
    99113        new_tags = [] 
    100         for tag_name in tags_string.split(" "): 
    101             tag_name = tag_name.strip().lower() 
     114        for tag_name in tag_list: 
    102115            try: 
    103116                tag_obj = self.get(name = tag_name) 
     
    106119                tag_obj = self.create(name = tag_name, slug = tag_name) 
    107120 
    108             tag_objects.append(tag_obj) 
    109  
    110         return tag_objects, new_tags 
     121            # Add many-to-many 
     122            blog_obj.tags.add(tag_obj) 
     123 
     124        return new_tags 
     125 
     126    def get_tag_info(self): 
     127        """ 
     128        Returns all tags with the additional information: 
     129         * tag.count     - How many blog entries used this tag? 
     130 
     131        returns min_frequency and max_frequency, too: The min/max usage of all 
     132        tags. Needed to build a tag cloud. 
     133        """ 
     134        tags = self.model.objects.all() 
     135 
     136        frequency = set() 
     137        # get the counter information 
     138        for tag in tags: 
     139            count = tag.blogentry_set.count() 
     140            tag.count = count 
     141            frequency.add(count) 
     142 
     143        min_frequency = float(min(frequency)) 
     144        max_frequency = float(max(frequency)) 
     145 
     146        return tags, min_frequency, max_frequency 
     147 
     148#    def get_tag_choices(self): 
     149#        """ 
     150#        returns >count< tags witch are the most used tags. 
     151#        """ 
     152#        tags, min_frequency, max_frequency = self.get_tag_info() 
     153# 
     154#        tags = sorted(tags, key=lambda x: x.count, reverse=True) 
     155# 
     156#        choices = tuple([(t.id, t.name) for t in tags]) 
     157#        return choices 
    111158 
    112159 
     
    114161    """ 
    115162    A blog entry tag 
     163    TODO: Add a usage counter! So we can easy sort from more to less usages and 
     164          building a tag cloud is easier. 
    116165    """ 
    117166    objects = BlogTagManager() 
  • trunk/pylucid/PyLucid/tools/newforms_utils.py

    r1691 r1713  
    1515 
    1616from django import newforms as forms 
     17from django.newforms import ValidationError 
    1718from django.utils.encoding import smart_unicode 
    1819 
     
    8788    """ 
    8889    Same as forms.CharField but stripes the output. 
    89      
     90 
    9091    >>> f = StripedCharField() 
    9192    >>> f.clean('\\n\\n[\\nTEST\\n]\\n\\n') 
     
    9798 
    9899 
     100class ListCharField(forms.CharField): 
     101    """ 
     102    Items seperated by spaces. 
     103 
     104    >>> f = ListCharField() 
     105    >>> f.clean(' one two  tree') 
     106    [u'one', u'two', u'tree'] 
     107    """ 
     108    def clean(self, value): 
     109        raw_value = super(ListCharField, self).clean(value) 
     110        value = raw_value.strip() 
     111        items = [i.strip() for i in value.split(" ")] 
     112        items = [i for i in items if i] # eliminate empty items 
     113        return items 
     114 
     115 
     116class InternalURLField(forms.CharField): 
     117    """ 
     118    Uses e.g. for back urls via a http GET parameter 
     119    validates the URL and check if is't a internal url and not 
     120    a external. 
     121 
     122    >>> f = InternalURLField() 
     123    >>> f.clean('/a/foobar/url/') 
     124    u'/a/foobar/url/' 
     125 
     126    >>> f.clean('http://eval.domain.tld') 
     127    Traceback (most recent call last): 
     128        ... 
     129    ValidationError: [u'Open redirect found.'] 
     130 
     131    >>> f = InternalURLField(must_start_with="/_command/") 
     132    >>> f.clean('/_command/a/foobar/url/') 
     133    u'/_command/a/foobar/url/' 
     134 
     135    >>> f.clean('/a/wrong/url/') 
     136    Traceback (most recent call last): 
     137        ... 
     138    ValidationError: [u'Open redirect found.'] 
     139    """ 
     140    default_error_message = "Open redirect found." 
     141 
     142    def __init__(self, must_start_with=None, *args, **kwargs): 
     143        self.must_start_with = must_start_with 
     144        super(InternalURLField, self).__init__(*args, **kwargs) 
     145 
     146    def clean(self, value): 
     147        value = super(InternalURLField, self).clean(value) 
     148        if "://" in value: 
     149            raise ValidationError(self.default_error_message) 
     150        if self.must_start_with and not value.startswith(self.must_start_with): 
     151            raise ValidationError(self.default_error_message) 
     152        return value 
     153 
     154 
     155 
    99156if __name__ == "__main__": 
    100157    import doctest