##// END OF EJS Templates
Fixed wrapping of the long links on the small screes (mobile phones). This fixes #15
Fixed wrapping of the long links on the small screes (mobile phones). This fixes #15

File last commit:

r72:567c0f1f default
r73:86298773 default
Show More
models.py
278 lines | 7.9 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
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
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
OPENING_POST_WEIGHT = 5
IMAGES_DIRECTORY = 'images/'
FILE_EXTENSION_DELIMITER = '.'
REGEX_PRETTY = re.compile(r'^\d(0)+$')
REGEX_SAME = re.compile(r'^(.)\1+$')
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
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:
for tag in tags:
post.tags.add(tag)
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
Compiling regexes for gets. #17 Added pagination. #28 Visually differing the dead (not bumpable) threads.
r46 def get_threads(self, tag=None, page=ALL_PAGES):
neko259
Truncating thread text in threads list. Fixed tag threads order.
r27 if tag:
threads = self.filter(parent=NO_PARENT, tags=tag)
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
Optimized some post count calls.
r58 threads = threads.order_by('-last_edit_time')
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 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 opening_post = self.get(id=opening_post_id)
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
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 not opening_post:
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 one constant I did not move completely to the module scope.
r72 reply_count += OPENING_POST_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
Implemented form validation. When the form fails validation, showing the index page.
r29 title = models.CharField(max_length=50)
neko259
Added the new posting abstraction.
r2 pub_time = models.DateTimeField()
neko259
Added new markdown field. Added gets algorithm with regexes.
r39 text = MarkupField(default_markup_type='markdown', escape_html=True)
neko259
Converting file name to a preudo-unique number instead of the original name.
r50 image = thumbs.ImageWithThumbsField(upload_to=_update_image_filename,
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 blank=True, sizes=((200, 150),))
neko259
Added the new posting abstraction.
r2 poster_ip = models.IPAddressField()
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):
neko259
Fixed post display in admin page. Fixed css in Mystic Dark.
r40 return self.title + ' (' + self.text.raw + ')'
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
def is_get(self):
"""If the post has pretty id (1, 1000, 77777), than it is called GET"""
neko259
Added new markdown field. Added gets algorithm with regexes.
r39 first = self.id == 1
neko259
Added thread metadata (replies, images, gets) to the threads list.
r30
neko259
Compiling regexes for gets. #17 Added pagination. #28 Visually differing the dead (not bumpable) threads.
r46 id_str = str(self.id)
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 pretty = REGEX_PRETTY.match(id_str)
same_digits = REGEX_SAME.match(id_str)
neko259
Compiling regexes for gets. #17 Added pagination. #28 Visually differing the dead (not bumpable) threads.
r46
return first or pretty or same_digits
neko259
Changed metadata design. Make space split tags.
r31
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)