首先新建一个BBSProject项目,在建一个app,把app导入到项目中。
在项目BBSProject中的settings.py中,
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01',#导入app01
]
url设置,在BBSProject的urls里导入app01中的views,
from django.conf.urls import url
from django.contrib import admin
from app01 import views#导入app01中的views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', views.index),#设置默认首页访问页面
]
在访问index的时候返回的结果是,在app01中的views中设置的index函数。
#_*_coding:utf-8_*_
from django.shortcuts import render,HttpResponse
# Create your views here.
def index(request):
return HttpResponse(u"欢迎访问吴老二博客")
测试简单页面
在做一个bbs之前首先要考虑的是数据库的框架,在一个bbs中需要的内容,还有就是数据库之间的的联用一定要清晰。
注:一个bbs首先要有用户,要有内容,不同的板块,还要有评论,点赞还有就是用户组。
#_*_coding:utf-8_*_ from __future__ import unicode_literals from django.db import models from django.contrib.auth.models import User '''用户组表,用户组名称不能相同,长度为64,返回用户组名 ''' class UserGroup(models.Model): name = models.CharField(max_length=64,unique=True) def __unicode__(self): return self.name '''用户信息表,包括用户名,用户组, ''' class UserProfile(models.Model): user = models.OneToOneField(User) name = models.CharField(max_length=32) groups = models.ManyToManyField(UserGroup) def __unicode__(self): return self.name ''' 帖子板块,长度.板块不能重复.用户权限 ''' class Category(models.Model): name = models.CharField(max_length=64,unique=True) admin = models.ManyToManyField(UserProfile) def __unicode__(self): return self.name '''帖子数据库表,标题,需要设置标题长度,标题不能重复.帖子隶属于板块,帖子插入的图片存储位置,内容以及优先级,帖子内容长度,帖子发布者需要联用用户列表, 如果用户列表在帖子列表下面需要加双引号. ''' class Article(models.Model): title = models.CharField(u"文章标题",max_length=255,unique=True) categroy = models.ForeignKey(Category,verbose_name=u"板块") head_img = models.ImageField(upload_to="uploads") summary = models.CharField(max_length=255) content = models.TextField(u"内容") author = models.ForeignKey(UserProfile) publish_date = models.DateTimeField(auto_now=True) hidden = models.BooleanField(default=True) priority = models.IntegerField(u"优先级",default=1000) def __unicode__(self): return "<%s, author:%s>" %(self.title,self.author) ''' 评论数据库表,评论的帖子需要联用帖子列表,评论者需要调用用户表,评论内容 ''' class Comment(models.Model): article = models.ForeignKey(Article) user = models.ForeignKey(UserProfile) parent_comment = models.ForeignKey('self',related_name='p_comment',blank=True,null=True) comment = models.TextField(max_length=1000) date = models.DateTimeField(auto_now=True) def __unicode__(self): return "<%s, user:%s>" %(self.comment,self.user) '''点赞表点赞时间,点赞的帖子,和点赞者''' class ThumbUp(models.Model): article = models.ForeignKey(Article) user = models.ForeignKey(UserProfile) date = models.DateTimeField(auto_now=True) def __unicode__(self): return "<user:%s>" %(self.user)
建好数据库需要同步一下:
python manage.py makemigrations python manage.py migrate
开始写页面返回views
#_*_coding:utf-8_*_ from django.shortcuts import render,HttpResponseRedirect import models from django.core.exceptions import ObjectDoesNotExist from django.contrib.auth import authenticate,login,logout from forms import ArticleForm,handle_uploaded_file # Create your views here. def index(request): '''首页''' articles = models.Article.objects.all() return render(request,'index.html',{'articles': articles}) def category(request,category_id): '''二级分类''' articles = models.Article.objects.filter(categroy_id=category_id) return render(request,'index.html',{'articles': articles}) def article_detail(request,article_id): '''帖子内容''' try: article_obj = models.Article.objects.get(id=article_id) except ObjectDoesNotExist as e: return render(request,'404.html',{'err_msg':u"文章不存在!"}) return render(request,'article.html', {'article_obj':article_obj}) def acc_logout(request): '''退出登陆''' logout(request) return HttpResponseRedirect('/') def acc_login(request): '''登陆''' print(request.POST) err_msg ='' if request.method == "POST": print('user authention...') username = request.POST.get('username') password = request.POST.get('password') user = authenticate(username=username,password=password) if user is not None: login(request,user) return HttpResponseRedirect('/') else: err_msg = "Wrong username or password!" return render(request,'login.html',{'err_msg':err_msg}) def new_article(request): '''最新帖子''' if request.method == 'POST': print(request.POST) form = ArticleForm(request.POST,request.FILES) if form.is_valid(): print("--form data:",form.cleaned_data) form_data = form.cleaned_data form_data['author_id'] = request.user.userprofile.id new_img_path = handle_uploaded_file(request,request.FILES['head_img']) form_data['head_img'] = new_img_path new_article_obj = models.Article(**form_data) new_article_obj.save() return render(request,'new_article.html',{'new_article_obj':new_article_obj}) else: print('err:',form.errors) category_list = models.Category.objects.all() return render(request,'new_article.html', {'categroy_list':category_list})
路径urls
#_*_coding:utf-8_*_
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$',views.index, name="index" ),
url(r'^category/(d+)/$',views.category,name="category" ),
url(r'^article/(d+)/$',views.article_detail,name="article_detail"),
url(r'^article/new/$',views.new_article,name="new_article"),
url(r'account/logout/',views.acc_logout,name='logout'),
url(r'account/login/',views.acc_login,name='login'),
]
可以登陆管理员后台建立板块和用户,发布帖子,帖子存放路径需要新建一个forms在app01里。
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from django import forms
import os
class ArticleForm(forms.Form):
'''帖子路径包括标题,内容作者,图片'''
title = forms.CharField(max_length=255,min_length=5)
summary = forms.CharField(max_length=255,min_length=5)
categroy_id = forms.IntegerField()
head_img = forms.ImageField()
content = forms.CharField(min_length=10)
def handle_uploaded_file(request,f):
'''帖子图片存储路径'''
base_img_upload_path = 'statics/imgs'
user_path = "%s/%s" %(base_img_upload_path,request.user.userprofile.id)
if not os.path.exists(user_path):
os.mkdir(user_path)
with open("%s/%s" %(user_path,f.name), 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)
return "/static/imgs/%s/%s" %(request.user.userprofile.id,f.name)
关于帖子的评论需要考虑级别,在app01里新建一个tree_search_test评论函数。
#!/usr/bin/env python # -*- coding:utf-8 -*- '''评论''' data = [ (None,'A'), ('A','A1'), ('A','A1-1'), ('A1','A2'), ('A1-1','A2-3'), ('A2-3','A3-4'), ('A1','A2-2'), ('A2','A3'), ('A2-2','A3-3'), ('A3','A4'), (None,'B'), ('B','B1'), ('B1','B2'), ('B1','B2-2'), ('B2','B3'), (None,'C'), ('C','C1'), ] def tree_search(d_dic,parent,son): for k,v_dic in d_dic.items(): if k == parent: #find your parent d_dic[k][son] = {} print("find parent of :", son) return else: # might in the deeper layer print("going to furhter layer...") tree_search(d_dic[k],parent,son) data_dic = {} for item in data: parent,son = item if parent is None:# has no parent data_dic[son] ={} else: # looking for its parent tree_search(data_dic,parent,son) for k,v in data_dic.items(): print(k,v ) ''' data_dic = { 'A': { 'A1': { 'A2':{ 'A3':{ 'A4':{} } }, 'A2-2':{ 'A3-3':{} } } }, 'B':{ 'B1':{ 'B2':{ 'B3':{} }, 'B2-2':{} } }, 'C':{ 'C1':{} } }'''
一下是前台页面的处理,首先要设置语言和路径,在settings里设置。
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.9/howto/static-files/
STATIC_URL = '/static/'
STATIC_URL = '/static/'
STATICFILES_DIRS = (
"%s/%s" %(BASE_DIR, "statics"),
# "%s/%s" %(BASE_DIR, ""), #static/uploads/uploads/
)
html文件可以在下面下载。
index的导航部分
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li ><a href="{% url 'index' %}">综合区</a></li>
<li><a href="{% url 'category' 1 %}">欧美专区</a></li>
<li><a href="{% url 'category' 2 %}">日韩专区</a></li>
<li><a href="{% url 'category' 3 %}">河北专区</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
{% if request.user.is_authenticated %}
<li class="dropdown">
<a href="http://v3.bootcss.com/examples/navbar-fixed-top/#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{{ request.user.userprofile.name }} <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="{% url 'new_article' %}">发贴</a></li>
<li><a href="http://v3.bootcss.com/examples/navbar-fixed-top/#">Another action</a></li>
<li><a href="http://v3.bootcss.com/examples/navbar-fixed-top/#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li class="dropdown-header">Nav header</li>
<li><a href="http://v3.bootcss.com/examples/navbar-fixed-top/#">Separated link</a></li>
<li><a href="{% url 'logout' %}">注销</a></li>
</ul>
</li>
{% else %}
<li><a href="{% url 'login'%}">注册登录</a></li>
{% endif %}
</ul>
</div>
导航下分帖子展示和其他板块
<div class="container">
{% block page-container %}
<div class="row">
<div class="col-md-8 left-content-panel">
<div class="content-box">
{% for article in articles reversed %}
<div class="article-box row">
<div class="article-head-img col-md-3">
<img src="{{ article.head_img }}">
</div>
<div class="article-summary col-md-8">
<h4><a href="{% url 'article_detail' article.id %}">{{ article.title }}</a></h4>
<div class="article-attr">
<ul class="list-inline">
<li>{{ article.author.name }}</li>
<li>{{ article.publish_date }}</li>
<li>thumbup:{{ article.thumbup_set.select_related.count }}</li>
<li>comments:{{ article.comment_set.select_related.count }}</li>
</ul>
</div>
<p>{{ article.summary }}</p>
</div>
</div>
<hr >
{% endfor %}
</div>
</div>
<div class="col-md-4 right-sidebar">
bar
</div>
</div>
{% endblock %}
</div>
js的调用
<script src="/static/bootstrap/js/jquery-2.1.4.js"></script>
<script src="/static/bootstrap/js/bootstrap.min.js"></script>
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="/static/bootstrap/js/ie10-viewport-bug-workaround.js"></script>
<script type="text/javascript">
$(document).ready(function(){
var menus = $("#navbar a[href='{{ request.path }}']")[0];
$(menus).parent().addClass("active");
$(menus).parent().siblings().removeClass("active");
//console.log(menus);
});
</script>
{% block bottom-js %}
{% endblock %}
登陆页面
{% extends 'index.html' %}
{% block page-container %}
<div class="col-md-4">
<form class="form-signin" action="{% url 'login' %}" method="post">{% csrf_token %}
<h2 class="form-signin-heading">Please sign in</h2>
<label for="inputEmail" class="sr-only">用户名</label>
<input type="text" id="" name="username" class="form-control" placeholder="username" required="" autofocus="">
<label for="inputPassword" class="sr-only">Password</label>
<input type="password" name="password" id="inputPassword" class="form-control" placeholder="Password" required="">
<div class="checkbox">
<label>
<input type="checkbox" value="remember-me"> Remember me
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
<p style="color:red;">{{ err_msg }}</p>
</form>
</div>
{% endblock %}
最新帖子
{% extends 'index.html' %}
{% block head-js %}
<script src="/static/plugins/ckeditor/ckeditor.js"></script>
{% endblock %}
{% block page-container %}
<div class="new-article">
{% if new_article_obj %}
<h3>文章<{{ new_article_obj.title }}>已发布,<a href="{% url 'article_detail' new_article_obj.id %}"> 点我查看</a></h3>
{% else %}
<form enctype="multipart/form-data" method="post" action="{% url 'new_article' %}">{% csrf_token %}
<input name="title" type="text" class="form-control" placeholder="文章标题">
<select name="categroy_id" class="form-control">
{% for category in categroy_list %}
<option value="{{ category.id }}">{{ category.name }}</option>
{% endfor %}
</select>
<input name="summary" type="text" class="form-control" placeholder="一句话文章中心思想...">
<input type="file" name="head_img">必选文章标题图片
<textarea id="ck-editor" name="content" class="form-control" rows="3"></textarea>
<br/>
<button type="submit" class="btn btn-success pull-right">发贴</button>
</form>
{% endif %}
</div>
{% endblock %}
{% block bottom-js %}
<script>
CKEDITOR.replace( 'ck-editor' );
CKEDITOR.editorConfig = function( config ) {
//config.language = 'es';
config.uiColor = '#F7B42C';
config.height = 500;
config.toolbarCanCollapse = true;
};
</script>
{% endblock %}
所有帖子
{% extends 'index.html' %}
{% load custom_tags %}
{% block page-container %}
<div class="article-detail">
<h4>{{ article_obj.title }}</h4>
<p>{{ article_obj.content|safe }}</p>
<hr/>
{% build_comment_tree article_obj.comment_set.select_related %}
</div>
{% endblock %}
报错404
{% extends 'index.html' %}
{% block page-container %}
<h1 style="font-size: 200px">404</h1>
<h3>{{ err_msg }}</h3>
{% endblock %}
以上是一个简单的bbs的搭建和制作,参考文件
webqq聊天室
webqq聊天室就给予上面的bbs制作吧,首先是数据库
在app01的数据库的用户信息表中新建朋友表。
class UserProfile(models.Model):
'''
用户信息表,包括用户名,用户组,
'''
user = models.OneToOneField(User)
name = models.CharField(max_length=32)
groups = models.ManyToManyField('UserGroup')
friends = models.ManyToManyField('self', related_name='my_friends')#新加的朋友表
def __unicode__(self):
return self.name
新建一个webqq项目,数据库中新建聊天组。
from __future__ import unicode_literals
from django.db import models
from app01.models import UserProfile
# Create your models here.
class QQGroup(models.Model):
name = models.CharField(max_length=64,unique=True)
description = models.CharField(max_length=255,default="nothing...")
members = models.ManyToManyField(UserProfile,blank=True)
admins = models.ManyToManyField(UserProfile,related_name='group_admins')
max_member_nums = models.IntegerField(default=200)
def __unicode__(self):
return self.name
聊天组的views
#_*_coding:utf-8_*_ from django.shortcuts import render,HttpResponse from webqq import models import json,Queue,time from django.contrib.auth.decorators import login_required#登录判断 # Create your views here. GLOBAL_MQ = {} @login_required def dashboard(request): return render(request,'webqq/dashboard.html') '''聊天页面函数返回聊天页面 ''' @login_required def contacts(request): contact_dic = { #'contact_list': [], #'group_list': [], } contacts = request.user.userprofile.friends.select_related().values('id','name') contact_dic['contact_list']= list(contacts) groups = request.user.userprofile.qqgroup_set.select_related().values("id",'name','max_member_nums') contact_dic['group_list'] = list(groups) print(contact_dic) return HttpResponse(json.dumps(contact_dic)) '''好有聊天,以及群组聊天 ''' @login_required def new_msg(request): if request.method == 'POST': print('-->',request.POST.get('data')) data = json.loads(request.POST.get('data')) send_to = data['to'] msg_from = data["from"] contact_type = data['contact_type'] data['timestamp'] = time.time() if contact_type == 'group_contact': group_obj = models.QQGroup.objects.get(id=send_to) for member in group_obj.members.select_related(): if str(member.id) not in GLOBAL_MQ: GLOBAL_MQ[str(member.id)] = Queue.Queue() if str(member.id) != msg_from: GLOBAL_MQ[str(member.id)].put(data) else: if send_to not in GLOBAL_MQ: GLOBAL_MQ[send_to] = Queue.Queue() GLOBAL_MQ[send_to].put(data) return HttpResponse(GLOBAL_MQ[send_to].qsize()) else:#recv msgs request_user = str(request.user.userprofile.id) msg_lists = [] print(GLOBAL_MQ,request_user) if request_user in GLOBAL_MQ: print("hehe") stored_msg_nums = GLOBAL_MQ[request_user].qsize() if stored_msg_nums ==0: #no new msgs try: print("