| 77 | | blog_entry = models.ForeignKey("BlogEntry") |
| 78 | | |
| 79 | | ip_address = models.IPAddressField(_('ip address'),) |
| 80 | | person_name = models.CharField( |
| 81 | | _("person's name"), max_length=50, |
| 82 | | help_text=_("Your full name (will be published) (required)"), |
| 83 | | ) |
| 84 | | email = models.EmailField( |
| 85 | | _('e-mail address'), |
| 86 | | help_text=_("Only for internal use. (will not be published) (required)"), |
| 87 | | ) |
| 88 | | homepage = models.URLField( |
| 89 | | _("homepage"), help_text = _("Your homepage (optional)"), |
| 90 | | verify_exists = False, max_length = 200, |
| 91 | | null=True, blank=True |
| 92 | | ) |
| 93 | | |
| 94 | | content = models.TextField(_('content'), max_length=3000) |
| 95 | | |
| 96 | | is_public = models.BooleanField(_('is public')) |
| 97 | | |
| 98 | | createtime = models.DateTimeField( |
| 99 | | auto_now_add=True, help_text="Create time", |
| 100 | | ) |
| 101 | | lastupdatetime = models.DateTimeField( |
| 102 | | auto_now=True, help_text="Time of the last change.", |
| 103 | | ) |
| 104 | | createby = models.ForeignKey( |
| 105 | | User, editable=False, |
| 106 | | help_text="User how create the current comment.", |
| 107 | | null=True, blank=True |
| 108 | | ) |
| 109 | | lastupdateby = models.ForeignKey( |
| 110 | | User, editable=False, |
| 111 | | help_text="User as last edit the current comment.", |
| 112 | | null=True, blank=True |
| 113 | | ) |
| 114 | | |
| 115 | | class Admin: |
| 116 | | pass |
| 117 | | |
| 118 | | class Meta: |
| 119 | | app_label = 'PyLucidPlugins' |
| 120 | | |
| 121 | | |
| 122 | | |
| 123 | | class BlogCommentForm(forms.ModelForm): |
| 124 | | """ |
| 125 | | Add a new comment. |
| 126 | | """ |
| 127 | | person_name = forms.CharField( |
| 128 | | min_length=4, max_length=50, |
| 129 | | help_text=_("Your name."), |
| 130 | | ) |
| 131 | | content = StripedCharField( |
| 132 | | label = _('content'), min_length=5, max_length=3000, |
| 133 | | help_text=_("Your comment to this blog entry."), |
| 134 | | widget=forms.Textarea(attrs={'rows': '15'}), |
| 135 | | ) |
| 136 | | |
| 137 | | class Meta: |
| 138 | | model = BlogComment |
| 139 | | # Using a subset of fields on the form |
| 140 | | fields = ('person_name', 'email', "homepage") |
| 141 | | |
| 142 | | |
| 143 | | class AdminCommentForm(BlogCommentForm): |
| 144 | | """ |
| 145 | | Form for editing a existing comment. Only for Admins |
| 146 | | """ |
| 147 | | class Meta: |
| 148 | | model = BlogComment |
| 149 | | fields = ( |
| 150 | | 'ip_address', 'person_name', 'email', "homepage", |
| 151 | | "content", "is_public", |
| 152 | | "createtime", "lastupdatetime", "createby", "lastupdateby" |
| 153 | | ) |
| | 81 | def add(self, title_info, url_parts): |
| | 82 | assert(isinstance(url_parts, (list,tuple))) #Needed? |
| | 83 | url_start = posixpath.join(*url_parts) |
| | 84 | |
| | 85 | list.append(self, { |
| | 86 | "feed_type": RSS, |
| | 87 | "title_info": title_info, |
| | 88 | "url": "%s.%s" % (url_start, RSS), |
| | 89 | }) |
| | 90 | list.append(self, { |
| | 91 | "feed_type": ATOM, |
| | 92 | "title_info": title_info, |
| | 93 | "url": "%s.%s" % (url_start, ATOM), |
| | 94 | }) |
| | 95 | |
| 156 | | |
| 157 | | |
| 158 | | class BlogTagManager(models.Manager): |
| 159 | | """ |
| 160 | | Manager for BlogTag model. |
| 161 | | """ |
| 162 | | def get_or_creates(self, tags_string): |
| 163 | | """ |
| 164 | | split the given tags_string and create not existing tags. |
| 165 | | returns a list of all tag model objects and a list of all created tags. |
| 166 | | """ |
| 167 | | tag_objects = [] |
| 168 | | new_tags = [] |
| 169 | | for tag_name in tags_string.split(" "): |
| 170 | | tag_name = tag_name.strip().lower() |
| 171 | | try: |
| 172 | | tag_obj = self.get(name = tag_name) |
| 173 | | except self.model.DoesNotExist: |
| 174 | | new_tags.append(tag_name) |
| 175 | | tag_obj = self.create(name = tag_name, slug = tag_name) |
| 176 | | |
| 177 | | tag_objects.append(tag_obj) |
| 178 | | |
| 179 | | return tag_objects, new_tags |
| 180 | | |
| 181 | | |
| 182 | | class BlogTag(models.Model): |
| 183 | | |
| 184 | | objects = BlogTagManager() |
| 185 | | |
| 186 | | name = models.CharField(max_length=255, core=True, unique=True) |
| 187 | | slug = models.SlugField( |
| 188 | | unique=True, prepopulate_from=('tag',), max_length=120 |
| 189 | | ) |
| 190 | | |
| 191 | | def __unicode__(self): |
| 192 | | return self.name |
| 193 | | |
| 194 | | class Admin: |
| 195 | | pass |
| 196 | | |
| 197 | | class Meta: |
| 198 | | app_label = 'PyLucidPlugins' |
| 199 | | |
| 200 | | |
| 201 | | #______________________________________________________________________________ |
| 202 | | |
| 203 | | class BlogEntry(models.Model): |
| 204 | | """ |
| 205 | | A blog entry |
| 206 | | """ |
| 207 | | headline = models.CharField(_('Headline'), |
| 208 | | help_text=_("The blog entry headline"), max_length=255 |
| 209 | | ) |
| 210 | | content = models.TextField(_('Content')) |
| 211 | | markup = models.IntegerField( |
| 212 | | max_length=1, choices=MARKUPS, |
| 213 | | help_text="the used markup language for this entry", |
| 214 | | ) |
| 215 | | |
| 216 | | tags = models.ManyToManyField(BlogTag, blank=True) |
| 217 | | |
| 218 | | is_public = models.BooleanField( |
| 219 | | default=True, help_text="Is post public viewable?" |
| 220 | | ) |
| 221 | | |
| 222 | | createtime = models.DateTimeField(auto_now_add=True) |
| 223 | | lastupdatetime = models.DateTimeField(auto_now=True) |
| 224 | | createby = models.ForeignKey(User, |
| 225 | | editable = False, |
| 226 | | ) |
| 227 | | lastupdateby = models.ForeignKey( |
| 228 | | User, |
| 229 | | editable = False, |
| 230 | | null=True, blank=True |
| 231 | | ) |
| 232 | | |
| 233 | | def html_content(self, context): |
| 234 | | """ |
| 235 | | returns the generatet html code from the content applyed the markup. |
| 236 | | """ |
| 237 | | return apply_markup( |
| 238 | | content = self.content, |
| 239 | | context = context, |
| 240 | | markup_no = self.markup |
| 241 | | ) |
| 242 | | |
| 243 | | def get_tag_string(self): |
| 244 | | """ |
| 245 | | Returns all tags as a joined string |
| 246 | | """ |
| 247 | | tags = self.tags.all() |
| 248 | | tags_names = [i.name for i in tags] |
| 249 | | return " ".join(tags_names) |
| 250 | | |
| 251 | | def __unicode__(self): |
| 252 | | return self.headline |
| 253 | | |
| 254 | | class Admin: |
| 255 | | pass |
| 256 | | |
| 257 | | class Meta: |
| 258 | | app_label = 'PyLucidPlugins' |
| 259 | | ordering = ('-createtime', '-lastupdatetime') |
| 260 | | |
| 261 | | ''' |
| 262 | | class RssBlogEntryFeed(Feed): |
| 263 | | """ |
| 264 | | TODO! |
| 265 | | http://www.djangoproject.com/documentation/syndication_feeds/ |
| 266 | | """ |
| 267 | | title = "Blog entry feed" |
| 268 | | link = "/TODO/" |
| 269 | | description = "FIXME" |
| 270 | | |
| 271 | | def items(self): |
| 272 | | return BlogEntry.objects.filter(is_public=True).all()[:count] |
| 273 | | |
| 274 | | class AtomBlogEntryFeed(RssBlogEntryFeed): |
| 275 | | feed_type = Atom1Feed |
| 276 | | subtitle = RssBlogEntryFeed.description |
| 277 | | |
| 278 | | class BlogEntryForm(forms.ModelForm): |
| 279 | | """ |
| 280 | | Form for create/edit a blog entry. |
| 281 | | """ |
| 282 | | content = forms.CharField( |
| 283 | | widget=forms.Textarea(attrs={'rows': '15'}), |
| 284 | | ) |
| 285 | | |
| 286 | | tags = forms.CharField( |
| 287 | | max_length=255, required=False, |
| 288 | | help_text=_("Tags for this entry (separated by spaces.)"), |
| 289 | | widget=forms.TextInput(attrs={'class':'bigger'}), |
| 290 | | ) |
| 291 | | class Meta: |
| 292 | | model = BlogEntry |
| 293 | | ''' |
| 294 | | |
| 295 | | #______________________________________________________________________________ |
| 296 | | |
| 297 | | |
| 298 | | PLUGIN_MODELS = (BlogComment, BlogTag, BlogEntry,) |
| 299 | | |
| 300 | | |
| 895 | | ''' |
| 896 | | def get_feeds_info(self): |
| 897 | | # return the existing feed names |
| 898 | | return (ENTRIES_FEED, COMMENTS_FEED) |
| 899 | | |
| 900 | | def feed(self, feed_name, FeedGenerator, count=10): |
| 901 | | """ |
| 902 | | Feeds |
| 903 | | * RSS 2.0 / Atom for all entries |
| 904 | | * RSS 2.0 / Atom for the comments |
| 905 | | |
| 906 | | FeedGenerator = django.utils.feedgenerator.Atom1Feed |
| 907 | | or |
| 908 | | FeedGenerator = django.utils.feedgenerator.Rss201rev2Feed |
| 909 | | |
| 910 | | |
| 911 | | RSSfeedGenerator.lucidTag |
| 912 | | - Generates a list of all available feeds |
| 913 | | - The links are always /feed/PluginName/FeedName/FeedType.xml |
| 914 | | |
| 915 | | /_command/1/RSSfeedGenerator/ |
| 916 | | |
| 917 | | |
| | 692 | |
| | 693 | def _get_feeds_info(self): |
| | 694 | """ |
| | 695 | returns information about all available syndication feeds. |
| | 696 | """ |
| | 697 | feed_info = FeedInfo() |
| | 698 | |
| | 699 | # Add "normal" feeds |
| | 700 | feed_info.add( |
| | 701 | title_info = ENTRIES_FEED_NAME, |
| | 702 | url_parts = (self.feed_url_prefix, ENTRIES_FEED_NAME,) |
| | 703 | ) |
| | 704 | feed_info.add( |
| | 705 | title_info = COMMENTS_FEED_NAME, |
| | 706 | url_parts = (self.feed_url_prefix, COMMENTS_FEED_NAME,) |
| | 707 | ) |
| | 708 | |
| | 709 | # Build a list of tag feeds |
| | 710 | limit = self.preferences.get("max_tag_feed", 10) |
| | 711 | tags = BlogTag.objects.values_list("slug", "name").all()[:limit] |
| | 712 | tag_feeds = [TAG_FEED_PREFIX + i[0] for i in tags] |
| | 713 | #self.page_msg(tag_feeds) |
| | 714 | |
| | 715 | # Add tag feeds |
| | 716 | for tag_slug, tag_name in tags: |
| | 717 | filename = TAG_FEED_PREFIX + tag_slug |
| | 718 | |
| | 719 | feed_info.add( |
| | 720 | title_info = tag_name, |
| | 721 | url_parts = (self.feed_url_prefix, filename,) |
| | 722 | ) |
| | 723 | |
| | 724 | return feed_info |
| | 725 | |
| | 726 | |
| | 727 | def feed(self, raw_feed_name): |
| | 728 | """ |
| | 729 | Generate and return a syndication feeds. |
| | 730 | |
| | 731 | feed_name e.g.: |
| | 732 | tag_%s.rss |
| | 733 | tag_%s.atom |
| | 734 | entries .rss/.atom |
| | 735 | comments .rss/.atom |
| 930 | | raise AttributeError("Wrong feed_name.") |
| 931 | | |
| 932 | | items = model.objects.filter(is_public=True).all()[:10] |
| 933 | | |
| 934 | | link = self.URLs.methodLink("feed", feed_name) |
| 935 | | |
| 936 | | feed = self._get_feed(FeedGenerator, items, title, link) |
| 937 | | |
| 938 | | return feed.writeString('utf8') |
| 939 | | |
| 940 | | |
| 941 | | def _get_feed(self, FeedGenerator, items, title, link): |
| | 775 | return self.error( |
| | 776 | _("Wrong URL."), " feed name '%s' unknown." % feed_name |
| | 777 | ) |
| | 778 | |
| | 779 | # Get the items |
| | 780 | items = entries.filter(is_public=True).all()[:limit] |
| | 781 | |
| | 782 | feed = self._get_feed(FeedGenerator, items, title) |
| | 783 | feed_content = feed.writeString('utf8') |
| | 784 | content_type = "%s; charset=utf-8" % feed.mime_type |
| | 785 | |
| | 786 | if FEED_DEBUG: |
| | 787 | self.response.write("<h2>Debug:</h2>") |
| | 788 | self.response.write("content type: %s" % content_type) |
| | 789 | self.response.write("<pre>") |
| | 790 | self.response.write(escape(feed_content)) |
| | 791 | self.response.write("</pre>") |
| | 792 | return |
| | 793 | |
| | 794 | # send the feed as a file to the client |
| | 795 | response = HttpResponse(content_type=content_type) |
| | 796 | response.write(feed_content) |
| | 797 | return response |
| | 798 | |
| | 799 | |
| | 800 | def _get_feed(self, FeedGenerator, items, title): |