BogoToBogo
  • Home
  • About
  • Big Data
  • Machine Learning
  • AngularJS
  • Python
  • C++
  • go
  • DevOps
  • Kubernetes
  • Algorithms
  • More...
    • Qt 5
    • Linux
    • FFmpeg
    • Matlab
    • Django 1.8
    • Ruby On Rails
    • HTML5 & CSS

Forums on a Shared Host

django.png




Bookmark and Share





bogotobogo.com site search:




Note

In this chapter, we will setup initial forum pages.

We can see the actual implementation via BoGo Forums.

Some of the screen shots are:



Forums Home (http://www.bogotobogo.com/dj/forums)

forums_list.png

Python Forum (http://www.bogotobogo.com/dj/forums/forum/10/)

Python_Forum.png

Thread view of the Python Forum (http://www.bogotobogo.com/dj/forums/thread/12/)

Python_Thread_View.png

Reply to a thread of the Python Forum (http://www.bogotobogo.com/dj/forums/post/reply/12/)

Reply_to_Thread.png

Starting a new thread of the Python Forum (http://www.bogotobogo.com/dj/forums/post/new_thread/10/)

Starting_A_New_Thread.png

User Registration (http://www.bogotobogo.com/dj/accounts/register/)

User_Register.png



To Do List

More things to be done (some of the sources are not completed)

  1. Email activation - sending email / authentication via email / recovery of a password
  2. User profile editing including user avatar setting




Creating forum and registration apps

Our forum consists of two apps:

$ python manage.py startapp forum
$ python manage.py startapp registration






Apps' Tree structures

forum:

forum_tree.png

registration:

Registration_Tree.png



Static files

As we can see from the trees, there are some static files, and they are initially stored in each app's static directory under relevant sub-directories. Then we issue collectstatic command (see Managing (Deploying) Static files (CSS, Images, Javascript) on Shared Host):

$ pwd
/home2/bogotob1/djangoproject

$ python manage.py collectstatic

Note that we need to set the STATIC_ROOT to the directory from which we like to serve these files. So, when we do collectstatic, it will copy all files from our static folders into the STATIC_ROOT directory.I n my case, it is:

STATIC_ROOT = "/home2/bogotob1/www/dj/static/"




settings.py
INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'registration',
    'djangoapp',
    'taggit',
    'blog',
    'forum',
    'myapp',
)

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

ROOT_URLCONF = 'djangoproject.urls'

...
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'name',
        'USER': 'user',
        'PASSWORD': 'password',
        'HOST': 'localhost',   # Or an IP Address that your DB is hosted on
        'PORT': '3306',
    }




forum/models.py
from django.db import models
from django.contrib.auth.models import User
from django.contrib import admin
from string import join
from djangoproject.settings import MEDIA_ROOT
from django.db.models.signals import post_save

class Forum(models.Model):
    title = models.CharField(max_length=60)
    def __unicode__(self):
        return self.title

    def num_posts(self):
        posts = sum([t.num_posts() for t in self.thread_set.all()])
        return posts

    def last_post(self):
        if self.thread_set.count():
            last = None
            for t in self.thread_set.all():
                l = t.last_post()
                if l:
                    if not last: last = l
                    elif l.created > last.created: last = l
            return last

class Thread(models.Model):
    title = models.CharField(max_length=60)
    created = models.DateTimeField(auto_now_add=True)
    creator = models.ForeignKey(User, blank=True, null=True)
    forum = models.ForeignKey(Forum)

    def __unicode__(self):
        return unicode(self.creator) + " - " + self.title

    def num_posts(self):
        return self.post_set.count()

    def num_replies(self):
        return self.post_set.count() - 1

    def last_post(self):
        if self.post_set.count():
            return self.post_set.order_by("created")[0]

class Post(models.Model):
    title = models.CharField(max_length=60)
    created = models.DateTimeField(auto_now_add=True)
    creator = models.ForeignKey(User, blank=True, null=True)
    thread = models.ForeignKey(Thread)
    body = models.TextField(max_length=10000)

    def __unicode__(self):
        return u"%s - %s - %s" % (self.creator, self.thread, self.title)

    def short(self):
        return u"%s - %s\n%s" % (self.creator, self.title, self.created.strftime("%b %d, %I:%M %p"))

    short.allow_tags = True

    def profile_data(self):
        p = self.creator.userprofile_set.all()[0]
        return p.posts, p.avatar

class UserProfile(models.Model):
    avatar = models.ImageField("Profile Pic", upload_to="images/", blank=True, null=True)
    posts = models.IntegerField(default=0)
    user = models.ForeignKey(User, unique=True)

    def __unicode__(self):
        return unicode(self.user)


### Admin
class ProfileAdmin(admin.ModelAdmin):
    list_display = ["user"]

class ForumAdmin(admin.ModelAdmin):
    pass

class ThreadAdmin(admin.ModelAdmin):
    list_display = ["title", "forum", "creator", "created"]
    list_filter = ["forum", "creator"]

class PostAdmin(admin.ModelAdmin):
    search_fields = ["title", "creator"]
    list_display = ["title", "thread", "creator", "created"]


def create_user_profile(sender, **kwargs):
    """When creating a new user, make a profile for him or her."""
    u = kwargs["instance"]
    if not UserProfile.objects.filter(user=u):
        UserProfile(user=u).save()

post_save.connect(create_user_profile, sender=User)

Then, to add tables, we need to run:

$ python manage.py syncdb




forum/views.py
from django.shortcuts import render

from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User


# Create your views here.
from django.core.urlresolvers import reverse
from djangoproject.settings import MEDIA_ROOT, MEDIA_URL

from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import get_object_or_404, render_to_response
from django.core.context_processors import csrf
from django.core.paginator import Paginator, InvalidPage, EmptyPage
from django.forms import ModelForm
from django.core.urlresolvers import reverse

from forum.models import *

class ProfileForm(ModelForm):
    class Meta:
        model = UserProfile
        exclude = ["posts", "user"]

@login_required
def profile(request, pk):
    """Edit user profile."""
    profile = UserProfile.objects.get(user=pk)
    img = None

    if request.method == "POST":
        pf = ProfileForm(request.POST, request.FILES, instance=profile)
        if pf.is_valid():
            pf.save()
            # resize and save image under same filename
            imfn = pjoin(MEDIA_ROOT, profile.avatar.name)
            im = PImage.open(imfn)
            im.thumbnail((160,160), PImage.ANTIALIAS)
            im.save(imfn, "JPEG")
    else:
        pf = ProfileForm(instance=profile)

    if profile.avatar:
        img = "/media/" + profile.avatar.name
    return render_to_response("forum/profile.html", add_csrf(request, pf=pf, img=img))

def save_profile(request, pk):
    """Edit user profile."""
    profile = UserProfile.objects.get(user=pk)
    img = None

    if request.method == "POST":
        pf = ProfileForm(request.POST, request.FILES, instance=profile)
        if pf.is_valid():
            pf.save()
            # resize and save image under same filename
            imfn = pjoin(MEDIA_ROOT, profile.avatar.name)
            im = PImage.open(imfn)
            im.thumbnail((160,160), PImage.ANTIALIAS)
            im.save(imfn, "JPEG")
    else:
        pf = ProfileForm(instance=profile)

    if profile.avatar:
        img = "/media/" + profile.avatar.name
    return render_to_response("forum/profile.html", add_csrf(request, pf=pf, img=img))

def mk_paginator(request, items, num_items):
    """Create and return a paginator."""
    paginator = Paginator(items, num_items)
    try: page = int(request.GET.get("page", '1'))
    except ValueError: page = 1

    try:
        items = paginator.page(page)
    except (InvalidPage, EmptyPage):
        items = paginator.page(paginator.num_pages)
    return items

def main(request):
    """Main listing."""
    forums = Forum.objects.all()
    return render_to_response("forum/list.html", dict(forums=forums, user=request.user)) 


class ThreadAdmin(admin.ModelAdmin):
    list_display = ["title", "forum", "creator", "created"]
    list_filter = ["forum", "creator"]

class PostAdmin(admin.ModelAdmin):
    search_fields = ["title", "creator"]
    list_display = ["title", "thread", "creator", "created"]

@login_required
def post(request, ptype, pk):
    """Display a post form."""
    action = reverse("forum.views.%s" % ptype, args=[pk])
    #t = Thread.objects.get(pk=pk)
    #f = Forum.objects.get(pk=t.forum.pk)
    if ptype ==  "new_thread":
        f = Forum.objects.get(pk=pk)
        title = f.title + " Forum  -  Start New Topic"
        subject = ''
    elif ptype == "reply":
        t = Thread.objects.get(pk=pk)
        f = Forum.objects.get(pk=t.forum.pk)
        title = f.title + " Forum  -  Reply"
        subject = "Re: " + Thread.objects.get(pk=pk).title

    return render_to_response("forum/post.html", add_csrf(request, subject=subject, action=action,
 title=title))

def forum(request, pk):
    """Listing of threads in a forum."""
    threads = Thread.objects.filter(forum=pk).order_by("-created")
    threads = mk_paginator(request, threads, 20)
    forum = Forum.objects.get(pk=pk)
    return render_to_response("forum/forum.html", add_csrf(request, threads=threads, pk=pk, forum=forum))

def thread(request, pk):
#def thread(request,forum_pk,  pk):
    """Listing of posts in a thread."""
    posts = Post.objects.filter(thread=pk).order_by("created")
    posts = mk_paginator(request, posts, 15)
    t = Thread.objects.get(pk=pk)
    f = Forum.objects.get(pk=t.forum.pk)
    return render_to_response("forum/thread.html", add_csrf(request, posts=posts, pk=pk, 
                                                           forum_title=f.title,
                                                           thread_title=t.title,
                                                           forum_pk=t.forum.pk, media_url=MEDIA_URL))

def add_csrf(request, **kwargs):
    """Add CSRF to dictionary."""
    d = dict(user=request.user, **kwargs)
    d.update(csrf(request))
    return d

@login_required
def new_thread(request, pk):
    """Start a new thread."""
    p = request.POST
    if p["subject"] and p["body"]:
        forum = Forum.objects.get(pk=pk)
        thread = Thread.objects.create(forum=forum, title=p["subject"], creator=request.user)
        Post.objects.create(thread=thread, title=p["subject"], body=p["body"], creator=request.user)
        increment_post_counter(request)
    return HttpResponseRedirect(reverse("forum.views.forum", args=[pk]))

@login_required
def reply(request, pk):
    """Reply to a thread."""
    p = request.POST
    if p["body"]:
        thread = Thread.objects.get(pk=pk)
        post = Post.objects.create(thread=thread, title=p["subject"], body=p["body"],
            creator=request.user)
    return HttpResponseRedirect(reverse("forum.views.thread", args=[pk]) + "?page=last")

def increment_post_counter(request):
    profile = request.user.userprofile_set.all()[0]
    profile.posts += 1
    profile.save()

@login_required
def new_thread(request, pk):
    """Start a new thread."""
    p = request.POST
    if p["subject"] and p["body"]:
        forum = Forum.objects.get(pk=pk)
        thread = Thread.objects.create(forum=forum, title=p["subject"], creator=request.user)
        Post.objects.create(thread=thread, title=p["subject"], body=p["body"], creator=request.user)
        increment_post_counter(request)
    return HttpResponseRedirect(reverse("forum.views.forum", args=[pk]))


def mytest(request, pk):
    profile = UserProfile.objects.get(user=pk)
    p = request.POST
    return render_to_response("forum/mytest.html", {})

class ForumAdmin(admin.ModelAdmin):
    pass




forum/urls.py

Forum app urls:

from django.conf.urls import patterns, include, url


urlpatterns = patterns('forum.views',
    url(r'^$', 'main'),
    url(r'^forum/(\d+)/$', 'forum'),
    url(r'^thread/(\d+)/$', 'thread'),
    url(r"^post/(new_thread|reply)/(\d+)/$", "post"),
    url(r"^reply/(\d+)/$", "reply"),
    url(r"^new_thread/(\d+)/$", "new_thread"),
    url(r"^profile/(\d+)/$", "profile"),
    url(r"^save_profile/(\d+)/$", "save_profile"),
    url(r"^mytest/(\d+)/$", "mytest"),
)




registration/urls.py

Registration app urls:

from django.conf.urls import patterns, include, url

urlpatterns = patterns('registration.views',
    url(r'^logout/$', 'logout'),
    url(r'^login/$', 'login'),
    url(r'^register/$', 'register_user'),
    url(r'^register_success/$', 'register_success'),
    url(r'^auth/$', 'auth_view'),
    url(r'^loggedin/$', 'loggedin'),
    url(r'^invalid/$', 'invalid_login'),
)




djangoproject/djangoproject//urls.py

Project urls:

from django.conf.urls import patterns, include, url

from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',

    # user authentication urls
    #url(r'^accounts/', include('djangoapp.urls')),

    # user registration urls
    url(r'^accounts/', include('registration.urls')),

    # admin
    url(r'^admin/', include(admin.site.urls)),

    # blog
    url(r'^blogs/', include('blog.urls')),

    # forum
    url(r'^forums/', include('forum.urls')),

    # django default
    url(r'^$', 'djangoapp.views.home', name='home'),

    # myapp - image upload
    url(r'^myapp/', include('myapp.urls')),
)




registration/views.py
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from django.contrib import auth
from django.core.context_processors import csrf
from django.contrib.auth.forms import UserCreationForm

# Create your views here.

def logout(request):
    auth.logout(request)
    return render_to_response("logout.html")

def login(request):
    c = {}
    c.update(csrf(request))
    return render_to_response("login.html", c)

def auth_view(request):
    '''
    username = request.POST.get('username', '')
    password = request.POST.get('password', '')
    '''
    username = request.POST['username']
    password = request.POST['password']
    user = auth.authenticate(username=username, password=password)

    if user is not None:
        auth.login(request, user)
        return HttpResponseRedirect('/dj/accounts/loggedin')
    else:
        return HttpResponseRedirect('/dj/accounts/invalid')

def loggedin(request):
    return render_to_response('loggedin.html',
                               {'full_name': request.user.username})

def invalid_login(request):
    return render_to_response('invalid_login.html')

def register_user(request):
    # 2nd time around
    if request.method == 'POST':
        # form = MyRegistrationForm(request.POST)
        form = UserCreationForm(request.POST)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect('/dj/accounts/register_success')

    # 1st time visit
    args = {}
    args.update(csrf(request))

    # form with no input
    # args['form'] = MyRegistrationForm()
    args['form'] = UserCreationForm()
    print args

    # passing form
    return render_to_response('register.html', args)

def register_success(request):
    return render_to_response('register_success.html')




Source files

All files including templates are available: forum.tar.gz and registration.tar.gz.












Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization

YouTubeMy YouTube channel

Sponsor Open Source development activities and free contents for everyone.

Thank you.

- K Hong







Django 1.8



Introduction - Install Django and Project Setup

Creating and Activating Models

Hello World A - urls & views

Hello World B - templates

Hello World C - url dispatcher

Hello World D - Models and SQLite Database

MVC - Hello World

Hello World on a Shared Host A

Hello World on a Shared Host B

Hello World - Admin Site Setup

virtualenv

Creating test project on virtualenv

Test project's settings.py

Creating Blog app and setting up models

Blog app - syncdb A

Blog app - syncdb B

Blog app - views and urls

Blog app - templates

Blog app - class based templates

Image upload sample code - local host

Authentication on Shared Host using FastCGI

User Registration on Shared Host A

User Registration with a Customized Form on Shared Host B

Blogs on Shared Host

Serving Django app with uWSGI and Nginx

Image upload sample code - shared host

Managing (Deploying) Static files (CSS, Images, Javascript) on Shared Host

Forum application on a Shared Host

Django Python Social Auth : Getting App ID (OAuth2) - Facebook, Twitter, and Google

Django: Python social auth, Facebook, Twitter, and Google Auth

Django: Python social auth, Facebook, Twitter, and Google Auth with Static files

...

Django 1.8 hosted on Linode VPS ==>

1. Setup CentOS 7 hosted on VPS

1B. Setup CentOS 7 hosted on VPS (multi-domain hosting setup) - Name server and Zone File settings (from GoDaddy to Linode)

2. ssh login and firewall

3. Apache Install

4. Install and Configure MariaDB Database server & PHP

5. Install and Configure Django

6. Model

7. Model 2 : populate tables, list_display, and search_fields

8. Model 3 (using shell)

9. Views (templates and css)

10. Views 2 (home page and more templates)

11. TinyMCE

12. TinyMCE 2

13. ImageField/FileField : Serving image/video files uploaded by a user

14. User Authentication 1 (register & forms)

15. User Authentication 2 (login / logout)

16. User Authentication 3 (password reset) - Sent from Email (gmail) setup etc.

17. User Authentication 4 (User profile & @login_required decorator)

18. User Authentication 5 (Facebook login)

19. User Authentication 6 (Google login)

20. User Authentication 7 (Twitter login)

21. User Authentication 8 (Facebook/Google/Twitter login buttons)

22. Facebook open graph API timeline fan page custom tab 1

23. Facebook Open Graph API Timeline Fan Page Custom Tab 2 (SSL certificate setup)

24. Facebook open graph API timeline fan page custom tab 3 (Django side - urls.py, settings.py, and views.py)

...

A sample production site Django 1.8.7: sfvue.com / einsteinish.com ==>

A sample production app (sfvue.com) with virtualenv and Apache

2. Upgrading to Django 1.8.7 sfvue.com site sample with virtualenv and Apache

(*) Django 1.8.7 einsteinish.com site - errors and fixes

Django 1.8.12 pytune.com site - local with Apache mod_wsgi

Django 1.8.12 pytune.com site - local with Nginx and uWSGI

Django 1.8.12 pytune.com site - deploy to AWS with Nginx and uWSGI

Django Haystack with Elasticsearch and Postgres

Django Compatibility Cheat Sheet

Sponsor Open Source development activities and free contents for everyone.

Thank you.

- K Hong






Python tutorial



Python Home

Introduction

Running Python Programs (os, sys, import)

Modules and IDLE (Import, Reload, exec)

Object Types - Numbers, Strings, and None

Strings - Escape Sequence, Raw String, and Slicing

Strings - Methods

Formatting Strings - expressions and method calls

Files and os.path

Traversing directories recursively

Subprocess Module

Regular Expressions with Python

Regular Expressions Cheat Sheet

Object Types - Lists

Object Types - Dictionaries and Tuples

Functions def, *args, **kargs

Functions lambda

Built-in Functions

map, filter, and reduce

Decorators

List Comprehension

Sets (union/intersection) and itertools - Jaccard coefficient and shingling to check plagiarism

Hashing (Hash tables and hashlib)

Dictionary Comprehension with zip

The yield keyword

Generator Functions and Expressions

generator.send() method

Iterators

Classes and Instances (__init__, __call__, etc.)

if__name__ == '__main__'

argparse

Exceptions

@static method vs class method

Private attributes and private methods

bits, bytes, bitstring, and constBitStream

json.dump(s) and json.load(s)

Python Object Serialization - pickle and json

Python Object Serialization - yaml and json

Priority queue and heap queue data structure

Graph data structure

Dijkstra's shortest path algorithm

Prim's spanning tree algorithm

Closure

Functional programming in Python

Remote running a local file using ssh

SQLite 3 - A. Connecting to DB, create/drop table, and insert data into a table

SQLite 3 - B. Selecting, updating and deleting data

MongoDB with PyMongo I - Installing MongoDB ...

Python HTTP Web Services - urllib, httplib2

Web scraping with Selenium for checking domain availability

REST API : Http Requests for Humans with Flask

Blog app with Tornado

Multithreading ...

Python Network Programming I - Basic Server / Client : A Basics

Python Network Programming I - Basic Server / Client : B File Transfer

Python Network Programming II - Chat Server / Client

Python Network Programming III - Echo Server using socketserver network framework

Python Network Programming IV - Asynchronous Request Handling : ThreadingMixIn and ForkingMixIn

Python Coding Questions I

Python Coding Questions II

Python Coding Questions III

Python Coding Questions IV

Python Coding Questions V

Python Coding Questions VI

Python Coding Questions VII

Python Coding Questions VIII

Python Coding Questions IX

Python Coding Questions X

Image processing with Python image library Pillow

Python and C++ with SIP

PyDev with Eclipse

Matplotlib

Redis with Python

NumPy array basics A

NumPy Matrix and Linear Algebra

Pandas with NumPy and Matplotlib

Celluar Automata

Batch gradient descent algorithm

Longest Common Substring Algorithm

Python Unit Test - TDD using unittest.TestCase class

Simple tool - Google page ranking by keywords

Google App Hello World

Google App webapp2 and WSGI

Uploading Google App Hello World

Python 2 vs Python 3

virtualenv and virtualenvwrapper

Uploading a big file to AWS S3 using boto module

Scheduled stopping and starting an AWS instance

Cloudera CDH5 - Scheduled stopping and starting services

Removing Cloud Files - Rackspace API with curl and subprocess

Checking if a process is running/hanging and stop/run a scheduled task on Windows

Apache Spark 1.3 with PySpark (Spark Python API) Shell

Apache Spark 1.2 Streaming

bottle 0.12.7 - Fast and simple WSGI-micro framework for small web-applications ...

Flask app with Apache WSGI on Ubuntu14/CentOS7 ...

Selenium WebDriver

Fabric - streamlining the use of SSH for application deployment

Ansible Quick Preview - Setting up web servers with Nginx, configure enviroments, and deploy an App

Neural Networks with backpropagation for XOR using one hidden layer

NLP - NLTK (Natural Language Toolkit) ...

RabbitMQ(Message broker server) and Celery(Task queue) ...

OpenCV3 and Matplotlib ...

Simple tool - Concatenating slides using FFmpeg ...

iPython - Signal Processing with NumPy

iPython and Jupyter - Install Jupyter, iPython Notebook, drawing with Matplotlib, and publishing it to Github

iPython and Jupyter Notebook with Embedded D3.js

Downloading YouTube videos using youtube-dl embedded with Python

Machine Learning : scikit-learn ...

Django 1.6/1.8 Web Framework ...









Contact

BogoToBogo
contactus@bogotobogo.com

Follow Bogotobogo

About Us

contactus@bogotobogo.com

YouTubeMy YouTube channel
Pacific Ave, San Francisco, CA 94115

Pacific Ave, San Francisco, CA 94115

Copyright © 2024, bogotobogo
Design: Web Master