##// END OF EJS Templates
Added hover state to submit button in MD theme.
Added hover state to submit button in MD theme.

File last commit:

r137:fe230882 merge 1.1
r138:4fce6c8c default
Show More
models.py
290 lines | 8.2 KiB | text/x-python | PythonLexer
neko259
Implemented form validation. When the form fails validation, showing the index page.
r29 import os
neko259
Converting file name to a preudo-unique number instead of the original name.
r50 from random import random
neko259
Changed metadata design. Make space split tags.
r31 import re
neko259
Implemented form validation. When the form fails validation, showing the index page.
r29 import time
neko259
Compiling regexes for gets. #17 Added pagination. #28 Visually differing the dead (not bumpable) threads.
r46 import math
neko259
Fixed unicode tags validation. Moved constants from classes to modules. Added error 404 when trying to get the non-existent thread. This fixes #19
r71
from django.db import models
from django.http import Http404
from django.utils import timezone
from markupfield.fields import MarkupField
wnc_21
Added captcha support
r95 from threading import Thread
neko259
Removed images directory. Removed old urls. Added a bit code for the views.
r4
neko259
Added images upload. Changed the design a bit. Reformatted some code by PEP 8. Changed the urls: not the main site is located at /, not /boards/.
r22 from neboard import settings
neko259
Fixed unicode tags validation. Moved constants from classes to modules. Added error 404 when trying to get the non-existent thread. This fixes #19
r71 import thumbs
neko259
Added images upload. Changed the design a bit. Reformatted some code by PEP 8. Changed the urls: not the main site is located at /, not /boards/.
r22
neko259
Added error 404 for opening not existing thread or tag. This fixes #8
r79 IMAGE_THUMB_SIZE = (200, 150)
TITLE_MAX_LENGTH = 50
DEFAULT_MARKUP_TYPE = 'markdown'
neko259
Added images upload. Changed the design a bit. Reformatted some code by PEP 8. Changed the urls: not the main site is located at /, not /boards/.
r22
neko259
Removed images directory. Removed old urls. Added a bit code for the views.
r4 NO_PARENT = -1
NO_IP = '0.0.0.0'
UNKNOWN_UA = ''
neko259
Fixed unicode tags validation. Moved constants from classes to modules. Added error 404 when trying to get the non-existent thread. This fixes #19
r71 ALL_PAGES = -1
neko259
Fixed some translation issues. Changed default captcha setting to "off" to pass tests. Removed the maximum page scale. This refs #36 and fixes #26, #2
r85 OPENING_POST_POPULARITY_WEIGHT = 2
neko259
Fixed unicode tags validation. Moved constants from classes to modules. Added error 404 when trying to get the non-existent thread. This fixes #19
r71 IMAGES_DIRECTORY = 'images/'
FILE_EXTENSION_DELIMITER = '.'
neko259
Initial commit. One test doesn't work, missing posting form.
r0
neko259
Added the new posting abstraction.
r2 class PostManager(models.Manager):
neko259
Added images upload. Changed the design a bit. Reformatted some code by PEP 8. Changed the urls: not the main site is located at /, not /boards/.
r22 def create_post(self, title, text, image=None, parent_id=NO_PARENT,
neko259
Added localization (not fully working). Added tags posting. Changed the design a bit.
r24 ip=NO_IP, tags=None):
neko259
Added images upload. Changed the design a bit. Reformatted some code by PEP 8. Changed the urls: not the main site is located at /, not /boards/.
r22 post = self.create(title=title,
text=text,
pub_time=timezone.now(),
parent=parent_id,
image=image,
poster_ip=ip,
neko259
Added thread bumping.
r25 poster_user_agent=UNKNOWN_UA,
last_edit_time=timezone.now())
neko259
Initial commit. One test doesn't work, missing posting form.
r0
neko259
Added localization (not fully working). Added tags posting. Changed the design a bit.
r24 if tags:
neko259
Added error 404 for opening not existing thread or tag. This fixes #8
r79 map(post.tags.add, tags)
neko259
Added localization (not fully working). Added tags posting. Changed the design a bit.
r24
neko259
Added thread bumping.
r25 if parent_id != NO_PARENT:
neko259
Implemented bumplimit.
r38 self._bump_thread(parent_id)
neko259
Added maximum threads count parameter to the settings. Delete the old posts to preserve the max count. Small design tweaks.
r28 else:
self._delete_old_threads()
neko259
Added thread bumping.
r25
neko259
Fixed indents for pycharm. Moved images upload path to settings. Some cosmetic changes.
r1 return post
neko259
Initial commit. One test doesn't work, missing posting form.
r0
def delete_post(self, post):
neko259
Added images upload. Changed the design a bit. Reformatted some code by PEP 8. Changed the urls: not the main site is located at /, not /boards/.
r22 children = self.filter(parent=post.id)
neko259
Removed old views. Added a proper deletion of post with children.
r3 for child in children:
self.delete_post(child)
neko259
Added the new posting abstraction.
r2 post.delete()
neko259
Initial commit. One test doesn't work, missing posting form.
r0 def delete_posts_by_ip(self, ip):
neko259
Added images upload. Changed the design a bit. Reformatted some code by PEP 8. Changed the urls: not the main site is located at /, not /boards/.
r22 posts = self.filter(poster_ip=ip)
neko259
Fixed indents for pycharm. Moved images upload path to settings. Some cosmetic changes.
r1 for post in posts:
self.delete_post(post)
neko259
Initial commit. One test doesn't work, missing posting form.
r0
neko259
Quick fix for the 404 page defect. Now 404 page is not shown for tags, this must be investigated further. This refs #50
r87 def get_threads(self, tag=None, page=ALL_PAGES,
order_by='-last_edit_time'):
neko259
Truncating thread text in threads list. Fixed tag threads order.
r27 if tag:
threads = self.filter(parent=NO_PARENT, tags=tag)
neko259
Quick fix for the 404 page defect. Now 404 page is not shown for tags, this must be investigated further. This refs #50
r87
# TODO Throw error 404 if no threads for tag found?
neko259
Truncating thread text in threads list. Fixed tag threads order.
r27 else:
neko259
Added images upload. Changed the design a bit. Reformatted some code by PEP 8. Changed the urls: not the main site is located at /, not /boards/.
r22 threads = self.filter(parent=NO_PARENT)
neko259
Added error 404 for opening not existing thread or tag. This fixes #8
r79
neko259
Quick fix for the 404 page defect. Now 404 page is not shown for tags, this must be investigated further. This refs #50
r87 threads = threads.order_by(order_by)
neko259
Added methods for getting opening posts and threads.
r5
neko259
Fixed unicode tags validation. Moved constants from classes to modules. Added error 404 when trying to get the non-existent thread. This fixes #19
r71 if page != ALL_PAGES:
neko259
Compiling regexes for gets. #17 Added pagination. #28 Visually differing the dead (not bumpable) threads.
r46 thread_count = len(threads)
if page < self.get_thread_page_count(tag=tag):
start_thread = page * settings.THREADS_PER_PAGE
end_thread = min(start_thread + settings.THREADS_PER_PAGE,
thread_count)
threads = threads[start_thread:end_thread]
neko259
Added methods for getting opening posts and threads.
r5 return threads
def get_thread(self, opening_post_id):
neko259
Added error 404 for opening not existing thread or tag. This fixes #8
r79 try:
neko259
Defined encoding in the HTML. Fixed error 404 page on opening reply as thread. This fixes #46, #47
r86 opening_post = self.get(id=opening_post_id, parent=NO_PARENT)
neko259
Added error 404 for opening not existing thread or tag. This fixes #8
r79 except Post.DoesNotExist:
neko259
Fixed unicode tags validation. Moved constants from classes to modules. Added error 404 when trying to get the non-existent thread. This fixes #19
r71 raise Http404
neko259
Fixed medadata design when an image is present. Added a method to determine if the tag is empty (has no attached threads).
r33 if opening_post.parent == NO_PARENT:
replies = self.filter(parent=opening_post_id)
neko259
Added methods for getting opening posts and threads.
r5
neko259
Fixed medadata design when an image is present. Added a method to determine if the tag is empty (has no attached threads).
r33 thread = [opening_post]
thread.extend(replies)
neko259
Fixed getting posts for a thread. Implemented thread getting test.
r17
neko259
Fixed medadata design when an image is present. Added a method to determine if the tag is empty (has no attached threads).
r33 return thread
neko259
Added methods for getting opening posts and threads.
r5
neko259
Fixed the tests. Added exists() method for the post.
r8 def exists(self, post_id):
neko259
Added images upload. Changed the design a bit. Reformatted some code by PEP 8. Changed the urls: not the main site is located at /, not /boards/.
r22 posts = self.filter(id=post_id)
neko259
Fixed the tests. Added exists() method for the post.
r8
neko259
Optimized some post count calls.
r58 return posts.count() > 0
neko259
Fixed the tests. Added exists() method for the post.
r8
neko259
Compiling regexes for gets. #17 Added pagination. #28 Visually differing the dead (not bumpable) threads.
r46 def get_thread_page_count(self, tag=None):
if tag:
threads = self.filter(parent=NO_PARENT, tags=tag)
else:
threads = self.filter(parent=NO_PARENT)
neko259
Optimized some post count calls.
r58 return int(math.ceil(threads.count() / float(
settings.THREADS_PER_PAGE)))
neko259
Compiling regexes for gets. #17 Added pagination. #28 Visually differing the dead (not bumpable) threads.
r46
neko259
Added maximum threads count parameter to the settings. Delete the old posts to preserve the max count. Small design tweaks.
r28 def _delete_old_threads(self):
"""
Preserves maximum thread count. If there are too many threads,
delete the old ones.
"""
# TODO Move old threads to the archive instead of deleting them.
# Maybe make some 'old' field in the model to indicate the thread
# must not be shown and be able for replying.
threads = self.get_threads()
thread_count = len(threads)
if thread_count > settings.MAX_THREAD_COUNT:
num_threads_to_delete = thread_count - settings.MAX_THREAD_COUNT
neko259
Optimized some post count calls.
r58 old_threads = threads[thread_count - num_threads_to_delete:]
neko259
Added maximum threads count parameter to the settings. Delete the old posts to preserve the max count. Small design tweaks.
r28
for thread in old_threads:
self.delete_post(thread)
neko259
Implemented bumplimit.
r38 def _bump_thread(self, thread_id):
thread = self.get(id=thread_id)
neko259
Compiling regexes for gets. #17 Added pagination. #28 Visually differing the dead (not bumpable) threads.
r46 if thread.can_bump():
neko259
Implemented bumplimit.
r38 thread.last_edit_time = timezone.now()
thread.save()
neko259
Added methods for getting opening posts and threads.
r5
neko259
Fixed medadata design when an image is present. Added a method to determine if the tag is empty (has no attached threads).
r33 class TagManager(models.Manager):
def get_not_empty_tags(self):
neko259
Sort threads by name. Previous commit: added navigation panel, added tag manager to get active tags.
r34 all_tags = self.all().order_by('name')
neko259
Fixed medadata design when an image is present. Added a method to determine if the tag is empty (has no attached threads).
r33 tags = []
for tag in all_tags:
if not tag.is_empty():
tags.append(tag)
return tags
neko259
Limit number of tags shown in the navigation bar to only the most popular ones.
r57 def get_popular_tags(self):
all_tags = self.get_not_empty_tags()
sorted_tags = sorted(all_tags, key=lambda tag: tag.get_popularity(),
reverse=True)
return sorted_tags[:settings.POPULAR_TAGS]
neko259
Fixed medadata design when an image is present. Added a method to determine if the tag is empty (has no attached threads).
r33
neko259
Removed images directory. Removed old urls. Added a bit code for the views.
r4 class Tag(models.Model):
"""
A tag is a text node assigned to the post. The tag serves as a board
section. There can be multiple tags for each message
"""
neko259
Fixed medadata design when an image is present. Added a method to determine if the tag is empty (has no attached threads).
r33 objects = TagManager()
neko259
Added images upload. Changed the design a bit. Reformatted some code by PEP 8. Changed the urls: not the main site is located at /, not /boards/.
r22 name = models.CharField(max_length=100)
neko259
Added maximum threads count parameter to the settings. Delete the old posts to preserve the max count. Small design tweaks.
r28 # TODO Connect the tag to its posts to check the number of threads for
# the tag.
neko259
Removed images directory. Removed old urls. Added a bit code for the views.
r4
neko259
Changed metadata design. Make space split tags.
r31 def __unicode__(self):
return self.name
neko259
Fixed medadata design when an image is present. Added a method to determine if the tag is empty (has no attached threads).
r32 def is_empty(self):
neko259
Fixed medadata design when an image is present. Added a method to determine if the tag is empty (has no attached threads).
r33 return self.get_post_count() == 0
def get_post_count(self):
neko259
Fixed medadata design when an image is present. Added a method to determine if the tag is empty (has no attached threads).
r32 posts_with_tag = Post.objects.get_threads(tag=self)
neko259
Optimized some post count calls.
r58 return posts_with_tag.count()
neko259
Fixed medadata design when an image is present. Added a method to determine if the tag is empty (has no attached threads).
r32
neko259
Limit number of tags shown in the navigation bar to only the most popular ones.
r57 def get_popularity(self):
posts_with_tag = Post.objects.get_threads(tag=self)
reply_count = 0
for post in posts_with_tag:
reply_count += post.get_reply_count()
neko259
Fixed some translation issues. Changed default captcha setting to "off" to pass tests. Removed the maximum page scale. This refs #36 and fixes #26, #2
r85 reply_count += OPENING_POST_POPULARITY_WEIGHT
neko259
Limit number of tags shown in the navigation bar to only the most popular ones.
r57
return reply_count
neko259
Fixed the tests. Added exists() method for the post.
r8
neko259
Added the new posting abstraction.
r2 class Post(models.Model):
neko259
Removed images directory. Removed old urls. Added a bit code for the views.
r4 """A post is a message."""
neko259
Initial commit. One test doesn't work, missing posting form.
r0
neko259
Added the new posting abstraction.
r2 objects = PostManager()
neko259
Initial commit. One test doesn't work, missing posting form.
r0
neko259
Converting file name to a preudo-unique number instead of the original name.
r50 def _update_image_filename(self, filename):
"""Get unique image filename"""
neko259
Fixed unicode tags validation. Moved constants from classes to modules. Added error 404 when trying to get the non-existent thread. This fixes #19
r71 path = IMAGES_DIRECTORY
neko259
Converting file name to a preudo-unique number instead of the original name.
r50 new_name = str(int(time.mktime(time.gmtime())))
new_name += str(int(random() * 1000))
neko259
Fixed unicode tags validation. Moved constants from classes to modules. Added error 404 when trying to get the non-existent thread. This fixes #19
r71 new_name += FILE_EXTENSION_DELIMITER
new_name += filename.split(FILE_EXTENSION_DELIMITER)[-1:][0]
neko259
Converting file name to a preudo-unique number instead of the original name.
r50
return os.path.join(path, new_name)
neko259
Added error 404 for opening not existing thread or tag. This fixes #8
r79 title = models.CharField(max_length=TITLE_MAX_LENGTH)
neko259
Added the new posting abstraction.
r2 pub_time = models.DateTimeField()
neko259
Added error 404 for opening not existing thread or tag. This fixes #8
r79 text = MarkupField(default_markup_type=DEFAULT_MARKUP_TYPE,
neko259
Changed parser to show quotes and reflinks as they are posted, not with borders and '#' character.
r90 escape_html=False)
neko259
Removed method that checks gets (this will be implemented in JS). Added image width and height fields that will be used for image previews. This refs #72
r127
neko259
Added default value for image dimensions fields.
r129 image_width = models.IntegerField(default=0)
image_height = models.IntegerField(default=0)
neko259
Removed method that checks gets (this will be implemented in JS). Added image width and height fields that will be used for image previews. This refs #72
r127
neko259
Converting file name to a preudo-unique number instead of the original name.
r50 image = thumbs.ImageWithThumbsField(upload_to=_update_image_filename,
neko259
Removed method that checks gets (this will be implemented in JS). Added image width and height fields that will be used for image previews. This refs #72
r127 blank=True, sizes=(IMAGE_THUMB_SIZE,),
width_field='image_width',
height_field='image_height')
neko259
Added IP ban lists. Added migration for bans. Use generic ip address for posting instead of ipv4 only.
r116 poster_ip = models.GenericIPAddressField()
neko259
Added the new posting abstraction.
r2 poster_user_agent = models.TextField()
parent = models.BigIntegerField()
neko259
Partially fixed tests and model definition
r7 tags = models.ManyToManyField(Tag)
neko259
Added thread bumping.
r25 last_edit_time = models.DateTimeField()
neko259
Initial commit. One test doesn't work, missing posting form.
r0
def __unicode__(self):
Pavel Ryapolov
Made post unicode string value shorter for the admin interface.
r105 return '#' + str(self.id) + ' ' + self.title + ' (' + \
neko259
Removed method that checks gets (this will be implemented in JS). Added image width and height fields that will be used for image previews. This refs #72
r127 self.text.raw[:50] + ')'
Ilyas
Added admin loing possibility. Now it is abailable under {BASE_URL}/boards/login...
r9
neko259
Added thread metadata (replies, images, gets) to the threads list.
r30 def _get_replies(self):
return Post.objects.filter(parent=self.id)
def get_reply_count(self):
neko259
Optimized some post count calls.
r58 return self._get_replies().count()
neko259
Added thread metadata (replies, images, gets) to the threads list.
r30
def get_images_count(self):
images_count = 1 if self.image else 0
for reply in self._get_replies():
if reply.image:
images_count += 1
return images_count
def get_gets_count(self):
gets_count = 1 if self.is_get() else 0
for reply in self._get_replies():
if reply.is_get():
gets_count += 1
return gets_count
neko259
Compiling regexes for gets. #17 Added pagination. #28 Visually differing the dead (not bumpable) threads.
r46 def can_bump(self):
"""Check if the thread can be bumped by replying"""
replies_count = len(Post.objects.get_thread(self.id))
return replies_count <= settings.MAX_POSTS_PER_THREAD
neko259
Changed metadata design. Make space split tags.
r31
neko259
#44 Show last replies in the threads list.
r59 def get_last_replies(self):
if settings.LAST_REPLIES_COUNT > 0:
reply_count = self.get_reply_count()
if reply_count > 0:
reply_count_to_show = min(settings.LAST_REPLIES_COUNT,
reply_count)
last_replies = self._get_replies()[reply_count
- reply_count_to_show:]
return last_replies
Ilyas
Added admin loing possibility. Now it is abailable under {BASE_URL}/boards/login...
r9
neko259
Renamed model "admins" to "admin".
r11 class Admin(models.Model):
Ilyas
Added admin loing possibility. Now it is abailable under {BASE_URL}/boards/login...
r9 """
Model for admin users
"""
neko259
Added images upload. Changed the design a bit. Reformatted some code by PEP 8. Changed the urls: not the main site is located at /, not /boards/.
r22 name = models.CharField(max_length=100)
password = models.CharField(max_length=100)
Ilyas
Added admin loing possibility. Now it is abailable under {BASE_URL}/boards/login...
r9
def __unicode__(self):
neko259
Fixed one constant I did not move completely to the module scope.
r72 return self.name + '/' + '*' * len(self.password)
neko259
Added IP ban lists. Added migration for bans. Use generic ip address for posting instead of ipv4 only.
r116
class Ban(models.Model):
ip = models.GenericIPAddressField()
def __unicode__(self):
return self.ip