##// END OF EJS Templates
Initial commit. One test doesn't work, missing posting form.
neko259 -
r0:8aafc193 default
parent child Browse files
Show More
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
@@ -0,0 +1,6 b''
1 from django.contrib import admin
2 from boards.models import Board, Thread, Post
3
4 admin.site.register(Board)
5 admin.site.register(Thread)
6 admin.site.register(Post)
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
@@ -0,0 +1,67 b''
1 from django.db import models
2 from django.utils import timezone
3 from django.conf import settings
4
5 class BoardManager(models.Manager):
6 def create_thread(self, board):
7 thread = self.create(board=board, posts=0, pub_date=timezone.now())
8
9 return thread
10
11 def create_post(self, title, text, thread, image):
12 post = self.create(title=title, text=text, pub_date=timezone.now(),
13 thread=thread, image=image, poster_ip='0.0.0.0',
14 poster_user_agent='')
15 thread.posts = thread.posts + 1
16
17 return post
18
19 def delete_post(self, post):
20 thread = post.thread
21 post.delete()
22 thread.posts = thread.posts - 1
23
24 if (thread.is_empty):
25 thread.delete()
26
27 def delete_posts_by_ip(self, ip):
28 posts = self.filter(poster_ip=ip)
29 for post in posts:
30 self.delete_post(post)
31
32 class Board(models.Model):
33 name = models.CharField(max_length=10)
34 description = models.CharField(max_length=50)
35
36 def __unicode__(self):
37 return self.name
38
39 class Thread(models.Model):
40 objects = BoardManager()
41
42 board = models.ForeignKey(Board)
43 posts = models.IntegerField()
44 pub_date = models.DateTimeField()
45
46 def __unicode__(self):
47 return str(self.id)
48
49 def is_dead(self):
50 return self.posts >= settings.MAX_POSTS_PER_THREAD
51
52 def is_empty(self):
53 return self.posts == 0
54
55 class Post(models.Model):
56 objects = BoardManager()
57
58 title = models.CharField(max_length=100)
59 pub_date = models.DateTimeField()
60 text = models.TextField()
61 thread = models.ForeignKey(Thread)
62 image = models.ImageField(upload_to='images/src/')
63 poster_ip = models.IPAddressField()
64 poster_user_agent = models.TextField()
65
66 def __unicode__(self):
67 return self.title + ' (' + self.text + ')'
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
@@ -0,0 +1,64 b''
1 from django.test import TestCase
2 from django.utils import timezone
3 from django.conf import settings
4
5 from boards.models import Board, Thread, Post
6
7 class BoardTests(TestCase):
8
9 def create_board(self):
10 return Board.objects.create(name='t', description='test')
11
12 def create_thread(self, board):
13 return Thread.objects.create_thread(board=board)
14
15 def create_post(self, thread):
16 return Post.objects.create_post(title='title',
17 text='text', thread=thread, image=None)
18
19 def test_add_thread(self):
20 thread = self.create_thread(self.create_board())
21
22 self.assertIsNotNone(thread)
23
24 def test_post_add(self):
25 thread = self.create_thread(self.create_board())
26 post = self.create_post(thread)
27
28 self.assertIsNotNone(post)
29 self.assertEqual(thread, post.thread)
30
31 def test_thread_post_count(self):
32 thread = self.create_thread(self.create_board())
33 self.create_post(thread)
34
35 self.assertEqual(1, thread.posts)
36
37 def test_thread_dead(self):
38 thread = self.create_thread(self.create_board())
39
40 for i in range(0, settings.MAX_POSTS_PER_THREAD):
41 self.create_post(thread)
42
43 self.assertTrue(thread.is_dead())
44
45 def test_thread_empty(self):
46 thread = self.create_thread(self.create_board())
47
48 self.assertTrue(thread.is_empty)
49
50 def test_delete_post(self):
51 thread = self.create_thread(self.create_board())
52 post = self.create_post(thread)
53
54 Post.objects.delete_post(post)
55
56 self.assertTrue(thread.is_empty())
57
58 def test_delete_posts_by_ip(self):
59 thread = self.create_thread(self.create_board())
60 self.create_post(thread)
61
62 Post.objects.delete_posts_by_ip('0.0.0.0')
63
64 self.assertTrue(thread.is_empty())
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
@@ -0,0 +1,15 b''
1 from django.conf.urls import patterns, url
2 from boards import views
3
4 urlpatterns = patterns('',
5 # /boards/
6 url(r'^$', views.index, name='index'),
7 # /boards/board_name/
8 url(r'^(?P<board_name>\w+)/$', views.board, name='board'),
9 # /boards/board_name/thread_id/
10 url(r'^(?P<board_name>\w+)/(?P<thread_id>\w+)/$', views.thread,
11 name='thread'),
12 # /boards/board_name/post/
13 url(r'^(?P<board_name>\w+)/post.html$', views.post,
14 name='post'),
15 )
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
@@ -0,0 +1,49 b''
1 from django.http import HttpResponse
2 from django.shortcuts import render
3
4 from boards.models import Board, Thread, Post
5
6 def index(request):
7 return HttpResponse('Imageboard, motherfucker! Do you post to it?!')
8
9 def board(request, board_name):
10 board = []
11 threads = []
12
13 boards = Board.objects.filter(name=board_name)
14 if len(boards) > 0:
15 board = boards[0]
16
17 if board != []:
18 threads = Thread.objects.filter(board=board)
19
20 context = {
21 'board': board,
22 'threads': threads,
23 }
24
25 return render(request, 'boards/board.html', context)
26
27 def thread(request, board_name, thread_id):
28 thread = []
29 posts = []
30
31 threads = Thread.objects.filter(id=thread_id)
32 if len(threads) > 0:
33 thread = threads[0]
34 posts = Post.objects.filter(thread=thread)
35
36 context = {
37 'thread': thread,
38 'posts': posts,
39 }
40
41 return render(request, 'boards/thread.html', context)
42
43 def post(request):
44 title = request.POST['title']
45 text = request.POST['text']
46
47 image = request.POST['image']
48
49 post = Post.objects.create_post(title=title, text=text, image=image)
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100755, binary diff hidden
NO CONTENT: new file 100755, binary diff hidden
@@ -0,0 +1,10 b''
1 #!/usr/bin/env python
2 import os
3 import sys
4
5 if __name__ == "__main__":
6 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "neboard.settings")
7
8 from django.core.management import execute_from_command_line
9
10 execute_from_command_line(sys.argv)
1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
@@ -0,0 +1,156 b''
1 # Django settings for neboard project.
2
3 DEBUG = True
4 TEMPLATE_DEBUG = DEBUG
5
6 ADMINS = (
7 # ('Your Name', 'your_email@example.com'),
8 )
9
10 MANAGERS = ADMINS
11
12 DATABASES = {
13 'default': {
14 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
15 'NAME': 'database.db', # Or path to database file if using sqlite3.
16 'USER': '', # Not used with sqlite3.
17 'PASSWORD': '', # Not used with sqlite3.
18 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
19 'PORT': '', # Set to empty string for default. Not used with sqlite3.
20 }
21 }
22
23 # Local time zone for this installation. Choices can be found here:
24 # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
25 # although not all choices may be available on all operating systems.
26 # In a Windows environment this must be set to your system time zone.
27 TIME_ZONE = 'Europe/Kiev'
28
29 # Language code for this installation. All choices can be found here:
30 # http://www.i18nguy.com/unicode/language-identifiers.html
31 LANGUAGE_CODE = 'en-us'
32
33 SITE_ID = 1
34
35 # If you set this to False, Django will make some optimizations so as not
36 # to load the internationalization machinery.
37 USE_I18N = True
38
39 # If you set this to False, Django will not format dates, numbers and
40 # calendars according to the current locale.
41 USE_L10N = True
42
43 # If you set this to False, Django will not use timezone-aware datetimes.
44 USE_TZ = True
45
46 # Absolute filesystem path to the directory that will hold user-uploaded files.
47 # Example: "/home/media/media.lawrence.com/media/"
48 MEDIA_ROOT = ''
49
50 # URL that handles the media served from MEDIA_ROOT. Make sure to use a
51 # trailing slash.
52 # Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
53 MEDIA_URL = ''
54
55 # Absolute path to the directory static files should be collected to.
56 # Don't put anything in this directory yourself; store your static files
57 # in apps' "static/" subdirectories and in STATICFILES_DIRS.
58 # Example: "/home/media/media.lawrence.com/static/"
59 STATIC_ROOT = ''
60
61 # URL prefix for static files.
62 # Example: "http://media.lawrence.com/static/"
63 STATIC_URL = '/static/'
64
65 # Additional locations of static files
66 STATICFILES_DIRS = (
67 # Put strings here, like "/home/html/static" or "C:/www/django/static".
68 # Always use forward slashes, even on Windows.
69 # Don't forget to use absolute paths, not relative paths.
70 )
71
72 # List of finder classes that know how to find static files in
73 # various locations.
74 STATICFILES_FINDERS = (
75 'django.contrib.staticfiles.finders.FileSystemFinder',
76 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
77 # 'django.contrib.staticfiles.finders.DefaultStorageFinder',
78 )
79
80 # Make this unique, and don't share it with anybody.
81 SECRET_KEY = '@1rc$o(7=tt#kd+4s$u6wchm**z^)4x90)7f6z(i&amp;55@o11*8o'
82
83 # List of callables that know how to import templates from various sources.
84 TEMPLATE_LOADERS = (
85 'django.template.loaders.filesystem.Loader',
86 'django.template.loaders.app_directories.Loader',
87 # 'django.template.loaders.eggs.Loader',
88 )
89
90 MIDDLEWARE_CLASSES = (
91 'django.middleware.common.CommonMiddleware',
92 'django.contrib.sessions.middleware.SessionMiddleware',
93 'django.middleware.csrf.CsrfViewMiddleware',
94 'django.contrib.auth.middleware.AuthenticationMiddleware',
95 'django.contrib.messages.middleware.MessageMiddleware',
96 # Uncomment the next line for simple clickjacking protection:
97 # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
98 )
99
100 ROOT_URLCONF = 'neboard.urls'
101
102 # Python dotted path to the WSGI application used by Django's runserver.
103 WSGI_APPLICATION = 'neboard.wsgi.application'
104
105 TEMPLATE_DIRS = (
106 # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
107 # Always use forward slashes, even on Windows.
108 # Don't forget to use absolute paths, not relative paths.
109 'templates',
110 )
111
112 INSTALLED_APPS = (
113 'django.contrib.auth',
114 'django.contrib.contenttypes',
115 'django.contrib.sessions',
116 'django.contrib.sites',
117 'django.contrib.messages',
118 'django.contrib.staticfiles',
119 # Uncomment the next line to enable the admin:
120 'django.contrib.admin',
121 # Uncomment the next line to enable admin documentation:
122 # 'django.contrib.admindocs',
123 'boards',
124 )
125
126 # A sample logging configuration. The only tangible logging
127 # performed by this configuration is to send an email to
128 # the site admins on every HTTP 500 error when DEBUG=False.
129 # See http://docs.djangoproject.com/en/dev/topics/logging for
130 # more details on how to customize your logging configuration.
131 LOGGING = {
132 'version': 1,
133 'disable_existing_loggers': False,
134 'filters': {
135 'require_debug_false': {
136 '()': 'django.utils.log.RequireDebugFalse'
137 }
138 },
139 'handlers': {
140 'mail_admins': {
141 'level': 'ERROR',
142 'filters': ['require_debug_false'],
143 'class': 'django.utils.log.AdminEmailHandler'
144 }
145 },
146 'loggers': {
147 'django.request': {
148 'handlers': ['mail_admins'],
149 'level': 'ERROR',
150 'propagate': True,
151 },
152 }
153 }
154
155 # Custom imageboard settings
156 MAX_POSTS_PER_THREAD = 100
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
@@ -0,0 +1,18 b''
1 from django.conf.urls import patterns, include, url
2
3 # Uncomment the next two lines to enable the admin:
4 from django.contrib import admin
5 admin.autodiscover()
6
7 urlpatterns = patterns('',
8 # Examples:
9 # url(r'^$', 'neboard.views.home', name='home'),
10 # url(r'^neboard/', include('neboard.foo.urls')),
11
12 # Uncomment the admin/doc line below to enable admin documentation:
13 # url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
14
15 # Uncomment the next line to enable the admin:
16 url(r'^admin/', include(admin.site.urls)),
17 url(r'^boards/', include('boards.urls')),
18 )
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
@@ -0,0 +1,28 b''
1 """
2 WSGI config for neboard project.
3
4 This module contains the WSGI application used by Django's development server
5 and any production WSGI deployments. It should expose a module-level variable
6 named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover
7 this application via the ``WSGI_APPLICATION`` setting.
8
9 Usually you will have the standard Django WSGI application here, but it also
10 might make sense to replace the whole Django WSGI application with a custom one
11 that later delegates to the Django one. For example, you could introduce WSGI
12 middleware here, or combine a Django application with an application of another
13 framework.
14
15 """
16 import os
17
18 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "neboard.settings")
19
20 # This application object is used by any WSGI server configured to use this
21 # file. This includes Django's development server, if the WSGI_APPLICATION
22 # setting points here.
23 from django.core.wsgi import get_wsgi_application
24 application = get_wsgi_application()
25
26 # Apply WSGI middleware here.
27 # from helloworld.wsgi import HelloWorldApplication
28 # application = HelloWorldApplication(application)
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
@@ -0,0 +1,17 b''
1 {% load url from future %}
2
3 {% if board %}
4 You see a <b>{{ board.name }}</b> board here. Its name is {{ board.description }}.
5 This board has the following threads:
6
7 <table>
8 {% for thread in threads %}
9 <tr><td>
10 <a href="{% url 'thread' board.name thread.id %}">{{ thread.id }}</a>
11 </td></tr>
12 {% endfor %}
13 </table>
14
15 {% else %}
16 You see no board here.
17 {% endif %}
@@ -0,0 +1,16 b''
1 {% extends 'posting_general.html' %}
2 {% load url from future %}
3
4 {% block posts %}
5 {% if thread %}
6 <table>
7 {% for post in posts %}
8 <tr><td>
9 {{ thread.text }}
10 </td></tr>
11 {% endfor %}
12 </table>
13 {% else %}
14 You see no thread here.
15 {% endif %}
16 {% endblock posts %}
@@ -0,0 +1,8 b''
1 <html>
2 <body>
3 <div id="postform">
4 </div>
5 <div id="posts">
6 </div>
7 </body>
8 </html>
General Comments 0
You need to be logged in to leave comments. Login now