一、涉及表结构

web\model.py(首选需要注意表结构的设计,如果表结构设计出来了,软件的架构也就基本出来了)

#!/usr/bin/env python
# _*_ coding:utf- _*_
from django.db import models # Create your models here.
from django.contrib.auth.models import User #导入django自带的用户认证表 class Article(models.Model):
'''文章帖子'''
title = models.CharField(u'文章标题',max_length=,unique=True) #帖子不可以重名,可以加注释,在admin中展示内容为'文章标题'
category=models.ForeignKey("Category",verbose_name=u'板块') #发布板块,必须加引号,因为Category是在下面的,加引号可以通过反射的方式进行查找,不会找不到;如果注释不是放在第一个位置,那么就需要使用verbose_name
head_img = models.ImageField(upload_to="uploads") #传文件,默认会传到当前项目的根目录下面,通过upload_to指定传送到的目录
summary=models.CharField(max_length=)
content=models.TextField(u'内容') #因为文章中会存很多的内容,所以不能够使用charfiled规定最大长度,使用TextField可以不指定长度
author=models.ForeignKey("UserProfile")
public_date=models.DateTimeField(auto_now=True) #自动创建日期,auto_now_add表示每一次更新的时间,auto_now表示每一次创建的时间
hidden=models.BooleanField(default=True) #是否影藏
priority=models.IntegerField(u'优先级',default=) #有些帖子长期可以置顶,通过优先级实现
def __unicode__(self): #设置默认返回值,在admin中对于增加的每一条数据就会显示return的结果
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) #以自己的表为外键关联的表,可以为自己的表名或者为self,django会在自己的表中多创建一个字段,related_name必须给出,否则会报错;
# blank=True表示admin中可以为空,null=True表示在数据库表中可以为空
comment=models.TextField(max_length=) #评论的内容,可以有最大数量限制
date=models.DateTimeField(auto_now=True)
def __unicode__(self):
return "<%s,user:%s>" %(self.comment,self.user)
'''
parent self son
Null null
null
null
null
每一条评论只需要关注自己和自己的第一条子评论,就是多了一个字段,SQL不支持,是通过代码级别实现的
'''
'''
python manage.py migrate 只会创建django自己的数据库表
第二次 会创建用户自定义的数据库表
'''
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 class Category(models.Model):
'''板块'''
name=models.CharField(max_length=,unique=True)
admin=models.ManyToManyField("UserProfile")
def __unicode__(self):
return self.name class UserProfile(models.Model):
'''账户信息表'''
user=models.OneToOneField(User) #继承自带的User表,但是原生的user表中的字段较少,可以继承之后可以扩展字段;
只能使用onetoone,否则就会使得多个用户同时关联一个账户onetoone是在代码层面进行限制的,其实就是将两张表进行拼接了
name = models.CharField(max_length=)
groups=models.ManyToManyField('UserGroup')
def __unicode__(self):
return self.name class UserGroup(models.Model):
'''用户组'''
name =models.CharField(max_length=,unique=True)
def __unicode__(self):
return self.name

使用admin管理数据库

from django.contrib import admin

# Register your models here.
class CategroyAdmin(admin.ModelAdmin):
list_display = ('id','name')
class CommentAdmin(admin.ModelAdmin):
list_display = ('id','parent_comment','comment','date')
class ArticleAdmin(admin.ModelAdmin):
list_display = ('id','title','author','hidden','public_date') #注意list_display中的字段。一定需要和数据库张的匹配,否则会报错
import models
admin.site.register(models.Article,ArticleAdmin)
admin.site.register(models.Category,CategroyAdmin)
admin.site.register(models.Comment,CommentAdmin)
admin.site.register(models.ThumbUp)
admin.site.register(models.UserProfile)
admin.site.register(models.UserGroup)

显示结果是这样的

创建两张表

mysql> show tables;
+-----------------------------+
| Tables_in_stupid_jumpserver |
+-----------------------------+
| host |
| host_user |
+-----------------------------+
rows in set (0.00 sec) mysql> desc host;
+----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+-------------+------+-----+---------+----------------+
| id | int() | NO | PRI | NULL | auto_increment |
| hostname | varchar() | NO | UNI | NULL | |
| ip_addr | varchar() | NO | UNI | NULL | |
| port | int() | YES | | NULL | |
+----------+-------------+------+-----+---------+----------------+
rows in set (0.00 sec) mysql> desc host_user;
+-----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+----------------+
| id | int() | NO | PRI | NULL | auto_increment |
| host_id | int() | YES | MUL | NULL | |
| auth_type | varchar() | YES | | NULL | |
| username | varchar() | NO | UNI | NULL | |
| password | varchar() | YES | | NULL | |
+-----------+--------------+------+-----+---------+----------------+
rows in set (0.00 sec) 其中:PRI表示主键,MUL表示外键,UNI表示该值是唯一的;

向表中插入数据

mysql> select * from host;
+----+-----------+----------+------+
| id | hostname | ip_addr | port |
+----+-----------+----------+------+
| | h2 | 10.0.0.2 | |
| | localhost | 10.0.0.1 | |
| | h3 | 10.0.0.3 | |
| | h5 | 10.0.0.5 | |
+----+-----------+----------+------+
rows in set (0.00 sec) mysql> select * from host_user;
+----+---------+-----------+----------+----------+
| id | host_id | auth_type | username | password |
+----+---------+-----------+----------+----------+
| | | ssh | charles | |
| | | ssh | root | |
| | | ssh | ul | |
| | NULL | ssh | Rain | |
+----+---------+-----------+----------+----------+
rows in set (0.01 sec)

两张表通过外键做关联查询

inner join表示取两者的交集
mysql> select * from host_user inner join host on host_user.host_id=host.id;
+----+---------+-----------+----------+----------+----+-----------+----------+------+
| id | host_id | auth_type | username | password | id | hostname | ip_addr | port |
+----+---------+-----------+----------+----------+----+-----------+----------+------+
| | | ssh | charles | | | h2 | 10.0.0.2 | |
| | | ssh | root | | | localhost | 10.0.0.1 | |
| | | ssh | ul | | | h3 | 10.0.0.3 | |
+----+---------+-----------+----------+----------+----+-----------+----------+------+
rows in set (0.00 sec) left join
mysql> select * from host_user left join host on host_user.host_id=host.id;
+----+---------+-----------+----------+----------+------+-----------+----------+------+
| id | host_id | auth_type | username | password | id | hostname | ip_addr | port |
+----+---------+-----------+----------+----------+------+-----------+----------+------+
| | | ssh | charles | | | h2 | 10.0.0.2 | |
| | | ssh | root | | | localhost | 10.0.0.1 | |
| | | ssh | ul | | | h3 | 10.0.0.3 | |
| | NULL | ssh | Rain | | NULL | NULL | NULL | NULL |
+----+---------+-----------+----------+----------+------+-----------+----------+------+
rows in set (0.00 sec) right join
mysql> select * from host_user right join host on host_user.host_id=host.id;
+------+---------+-----------+----------+----------+----+-----------+----------+------+
| id | host_id | auth_type | username | password | id | hostname | ip_addr | port |
+------+---------+-----------+----------+----------+----+-----------+----------+------+
| | | ssh | charles | | | h2 | 10.0.0.2 | |
| | | ssh | root | | | localhost | 10.0.0.1 | |
| | | ssh | ul | | | h3 | 10.0.0.3 | |
| NULL | NULL | NULL | NULL | NULL | | h5 | 10.0.0.5 | |
+------+---------+-----------+----------+----------+----+-----------+----------+------+
rows in set (0.00 sec)

二、利用admin来管理数据库以及创建数据库表的字段

from django.contrib import admin
import models
# Register your models here.
class CategroyAdmin(admin.ModelAdmin):
list_display = ('id','name')
class ArticleAdmin(admin.ModelAdmin):
list_display = ('id','title','author','hidden','publish_date') #创建表字段 class CommentAdmin(admin.ModelAdmin):
list_display = ('id','parent_comment','comment','date')
admin.site.register(models.Article,ArticleAdmin)
admin.site.register(models.Category,CategroyAdmin)
admin.site.register(models.Comment,CommentAdmin)
admin.site.register(models.ThumbUp)
admin.site.register(models.UserProfile)
admin.site.register(models.UserGroup)

二、静态文件配置

settings.py

STATIC_URL = '/static/'    #静态文件的前缀,相当于一个别名,是一个入口的存在,通过这个入口可以找到所有STATICFILES_DIRS中的静态文件
STATICFILES_DIRS=( #可以存多个静态文件的路径,在调用静态路径的时候,静态文件都会在指定的各个目录下面找
"%s%s" %(BASE_DIR,'statics'),
#os.path.join(BASE_DIR,'static'),
)

index.html

    <link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet">

    <!-- Custom styles for this template -->
<link href="/static/bootstrap/css/navbar-fixed-top.css" rel="stylesheet">
<link href="/static/bootstrap/css/custom.css" rel="stylesheet">

三、利用url传递参数页面的自动切换

from django.conf.urls import include, url
from django.contrib import admin
from web import views urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^$',views.index, name="index" ),
url(r'^category/(\d+)/$',views.category,name="category" ), #通过不同的数字引用不同的urls
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'),
]

urls

          <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>

index.html

对于点击的标签,增加active属性

index.html   对于每一个标签,被选中的时候,应该添加active属性,

        $(document).ready(function(){
var menus = $("#navbar a[href='{{ request.path }}']")[]; //返回的是列表,在js中引用template的变量,request.path表示请求的路径,因为在点击的时候回切换页面,如果页面不切换,可以直接找到 #nvabar li来实现
$(menus).parent().addClass("active");
$(menus).parent().siblings().removeClass("active");
//console.log(menus);
});

三、实现用户登录和注销

      <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>

index.html

from django.conf.urls import include, url
from django.contrib import admin
from web import views urlpatterns = [
url(r'^admin/', include(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'),
]

urls

from django.contrib.auth import authenticate,login,logout
def acc_logout(request):
logout(request) #直接调用django自己的logout函数
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})

views

views.py

#!/usr/bin/env python
#! _*_ coding:utf- _*_
from django.shortcuts import render
from web import models
from django.core.exceptions import ObjectDoesNotExist
from web import forms
# Create your views here. def index(request):
articles=models.Article.objects.all()
return render(request,'index.html',{'articles':articles}) def category(request,category_id):
print "-->",category_id
articles=models.Article.objects.filter(category_id=category_id) #根据各个板块的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'xxxxx'})
return render(request,'article.html',{'article_obj':article_obj}) def new_article(request):
if request.method=='POST':
print request.POST
form=forms.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 #author_id必须写,否则数据库会报错,request.user表示当前请求登录的用户
new_img_path=forms.handle_uploaded_file(request,request.FILES.id)
form_data['head_img']=new_img_path
new_article_obj=models.Article(**form_data)
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',{'category_list':category_list})
def acc_logout(request):
pass def acc_login(request):
pass

四、CSRF

{% extends 'index.html' %}

{% block page-container %}

<div class="col-md-4">
<form class="form-signin" action="{% url 'login' %}" method="post">{% csrf_token %} //必须加{% 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 %}

login.html

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}) #使用csrf,视图中必须使用render

views.py

五、实现用户登录

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) #authenticate函数会自动到数据库取用户数据进行验证
if user is not None: #函数没有取到值就会返回None
login(request,user)
return HttpResponseRedirect('/')
else:
err_msg = "Wrong username or password!"
return render(request,'login.html',{'err_msg':err_msg}) #使用csrf,视图中必须使用render

http://ueditor.baidu.com/website/  百度插件,但是不支持python,网站已经有人通过修改支持django了,可以try一下;

http://ckeditor.com/demo   非常好用的插件,支持python,使用full featured版本,比较全

六、后台通过forms对表单进行验证

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表示文章是否创建成功
new_article_obj.save() #这样比model.Article.object.all(**form_data)创建有好处,可以之间通过new_article_obj.元素在html中显示内容是否创建成功
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})

views.py

{% 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=""></textarea> <br/>
<button type="submit" class="btn btn-success pull-right">发贴</button> </form>
{% endif %}
</div>
{% endblock %}

new_article.html

forms.py

#!/usr/bin/env python
# -*- coding:utf- -*-
from django import forms
import os
class ArticleForm(forms.Form):
title=forms.CharField(max_length=,min_length=)
summary=forms.CharField(max_length=,min_length=)
category_id=forms.ImageField()
content=forms.CharField(min_length=) def handle_uploaded_file(request,f): #将request.FILES传送进来
base_img_upload_path='static/img'
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(): #chunk内部其实就是yield方法
destination.write(chunk)
return "/static/imgs/%s/%s" %(request.user.userprofile.id,f.name)

七、评论树的实现

#!/usr/bin/env python
# -*- coding:utf- -*-
'''通过递归的方式将data中的数据按照层级的关系存入新的字典中'''
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 #item代表两个值
if parent is None:# has no parent #判断parents是否为空
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':{}
} }'''
'''多级评论树的实现,是将data转换为下面类型的字典'''

对于前段template来说,只能有for循环,无法实现上述的递归,只能通过simple_tag返回html字符串

custom_tags.py

#!/usr/bin/env python
# -*- coding:utf- -*-
from django import template register = template.Library() def tree_search(d_dic,comment_obj):
for k,v_dic in d_dic.items():
if k == comment_obj.parent_comment: #find parent
d_dic[k][comment_obj] = {}
return
else: #going deeper....;
tree_search(d_dic[k],comment_obj) def generate_comment_html(sub_comment_dic,margin_left_val):
html = ""
for k,v_dic in sub_comment_dic.items():
html += "<div style='margin-left:%spx' class='comment-node'>" % margin_left_val + k.comment + "</div>"
if v_dic:
html += generate_comment_html(v_dic,margin_left_val+)
return html
@register.simple_tag
def build_comment_tree(comment_list):
#print("commment_list:",comment_list) comment_dic = {}
for comment_obj in comment_list:
if comment_obj.parent_comment is None:#no parent
comment_dic[comment_obj] ={}
else: #has farther ,
tree_search(comment_dic,comment_obj) # tree is built # pin html str
html = "<div class='comment-box'>"
margin_left =
for k,v in comment_dic.items():
print(k,v )
html += "<div class='comment-node'>" + k.comment + "</div>"
html += generate_comment_html(v,margin_left+) html += "</div>"
return html

aticle.html

{% 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 %} //通过article找到评论表的的评论
</div>
{% endblock %}

index.html

<!DOCTYPE html>
<!-- saved from url=()http://v3.bootcss.com/examples/navbar-fixed-top/ -->
<html lang="zh-CN"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<meta name="description" content="">
<meta name="author" content="">
<link rel="icon" href="http://v3.bootcss.com/favicon.ico"> <title>Oldboy BBS</title> <!-- Bootstrap core CSS -->
<link href="/static/bootstrap/css/bootstrap.min.css" rel="stylesheet"> <!-- Custom styles for this template -->
<link href="/static/bootstrap/css/navbar-fixed-top.css" rel="stylesheet">
<link href="/static/bootstrap/css/custom.css" rel="stylesheet">
{% block head-js %}
{% endblock %}
</head> <body> <!-- Fixed navbar -->
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="http://v3.bootcss.com/examples/navbar-fixed-top/#">电影</a>
</div>
<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><!--/.nav-collapse -->
</div>
</nav> <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> //thumbup的article的字段的外键关联到article表,通过
article.thumbup_set.select_related来反向找到原表的字段(一对多),为列表类型, 
<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> <!-- /container --> <!-- Bootstrap core JavaScript ================================================== --> <!-- Placed at the end of the document so the pages load faster --> <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  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 }}']")[]; //返回的是列表,在js中引用template的变量,request.path表示请求的路径,因为在点击的时候回切换页面,如果页面不切换,可以直接找到 #nvabar li来实现 $(menus).parent().addClass("active"); $(menus).parent().siblings().removeClass("active"); //console.log(menus);  }); </script> {% block bottom-js %} {% endblock %} </body></html>

new_article.html

{% 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=""></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 = ;
config.toolbarCanCollapse = true;
};
</script>
{% endblock %}

八、图片文件上传之后无法根据上传的路径显示的问题

图片会上传到我们指定的upload_to路径下面;

class Article(models.Model):
'''文章帖子'''
title = models.CharField(u'文章标题',max_length=,unique=True) #帖子不可以重名,可以加注释,在admin中展示内容为'文章标题'
category=models.ForeignKey("Category",verbose_name=u'板块') #发布板块,必须加引号,因为Category是在下面的,加引号可以通过反射的方式进行查找,不会找不到;如果注释不是放在第一个位置,那么就需要使用verbose_name
head_img = models.ImageField(upload_to="uploads")

但是该路径html无法找到,看下图:

如果在settings中指定该静态文件路径,依然找不到,因为会去/static/uploads/uploads去找,使用下面的路径就可以找到:

STATICFILES_DIRS=(               #可以存多个静态文件的路径,在调用静态路径的时候,静态文件都会在指定的各个目录下面找
"%s%s" %(BASE_DIR,'statics'),
'uploads'
#os.path.join(BASE_DIR,'static'),
)

开发BBS论坛的更多相关文章

  1. Python开发一个简单的BBS论坛

    项目:开发一个简单的BBS论坛 需求: 整体参考“抽屉新热榜” + “虎嗅网” 实现不同论坛版块 帖子列表展示 帖子评论数.点赞数展示 在线用户展示 允许登录用户发贴.评论.点赞 允许上传文件 帖子可 ...

  2. Java,面试题,简历,Linux,大数据,常用开发工具类,API文档,电子书,各种思维导图资源,百度网盘资源,BBS论坛系统 ERP管理系统 OA办公自动化管理系统 车辆管理系统 各种后台管理系统

    Java,面试题,简历,Linux,大数据,常用开发工具类,API文档,电子书,各种思维导图资源,百度网盘资源BBS论坛系统 ERP管理系统 OA办公自动化管理系统 车辆管理系统 家庭理财系统 各种后 ...

  3. Python之路【第十八篇】Django小项目简单BBS论坛部分内容知识点

    开发一个简单的BBS论坛 项目需求: 整体参考“抽屉新热榜” + “虎嗅网” 实现不同论坛版块 帖子列表展示 帖子评论数.点赞数展示 在线用户展示 允许登录用户发贴.评论.点赞 允许上传文件 帖子可被 ...

  4. python 学习笔记二十 django项目bbs论坛

    项目:开发一个简单的BBS论坛 需求: 整体参考“抽屉新热榜” + “虎嗅网” 实现不同论坛版块 帖子列表展示 帖子评论数.点赞数展示 在线用户展示 允许登录用户发贴.评论.点赞 允许上传文件 帖子可 ...

  5. Python之路,Day17 - 分分钟做个BBS论坛

    Python之路,Day17 - 分分钟做个BBS论坛   本节内容: 项目:开发一个简单的BBS论坛 需求: 整体参考"抽屉新热榜" + "虎嗅网" 实现不同 ...

  6. Django小项目简单BBS论坛

    开发一个简单的BBS论坛 项目需求: 1 整体参考"抽屉新热榜" + "虎嗅网" 2 实现不同论坛版块 3 帖子列表展示 4 帖子评论数.点赞数展示 5 在线用 ...

  7. 开源BBS论坛软件推荐

    七款开源BBS论坛软件推荐(1) 本文介绍了七个开源的BBS论坛软件(在英文界一般叫做Forum).可能国内的朋友们比较熟悉Discuz!和PHPwind,但其实我们的选择还是很多的,而且下面介绍的这 ...

  8. 聚焦“云开发圆桌论坛”,大前端Serverless大佬们释放了这些讯号!

    4月14日,由云加社区举办的TVP&腾讯云技术交流日云开发专场,暨"腾讯云-云开发圆桌论坛"在北京.深圳两地同步举行. 当天下午,一场主题为"基于大前端和node ...

  9. python第一百三十天 ---简单的BBS论坛

    简单的BBS论坛 实现功能 git仓库地址:https://github.com/uge3/BBS 1.整体参考“抽屉新热榜” + “博客园” 2.实现不同论坛版块 3.帖子列表展示 4.个人博客主页 ...

随机推荐

  1. MySql数据库索引原理

    写在前面:索引对查询的速度有着至关重要的影响,理解索引也是进行数据库性能调优的起点.考虑如下情况,假设数据库中一个表有10^6条记录,DBMS的页面大小为4K,并存储100条记录.如果没有索引,查询将 ...

  2. 自动选中div中的文字

    <html> <head> <title></title> <script type="text/javascript" de ...

  3. mysql系统库INFORMATION_SCHEMA,MySQL,TEST,mysql系统表的作用

    本文简要说明了MySQL数据库安装好后自带的INFORMATION_SCHEMA,MySQL,TEST三个数据库的用途. 第一个数据库INFORMATION_SCHEMA: 提供了访问数据库元数据的方 ...

  4. [Spring MVC] - SpringMVC的各种参数绑定方式

    SpringMVC的各种参数绑定方式 1. 基本数据类型(以int为例,其他类似):Controller代码: @RequestMapping("saysth.do") publi ...

  5. [Java] - 格式字符串替换方法

    Java 字符串格式替换方法有两种,一种是使用String.format(...),另一种是使用MessageFormat.format(...) 如下: import java.text.Messa ...

  6. filter and listener

    Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层. 使用 Serv ...

  7. 解决Linux性能问题的前60秒

    为了解决性能问题,你登入了一台Linux服务器,在最开始的一分钟内需要查看什么? 在Netflix我们有一个庞大的EC2 Linux集群,还有非常多的性能分析工具来监控和调查它的性能.其中包括用于云监 ...

  8. 53. Maximum Subarray

    Find the contiguous subarray within an array (containing at least one number) which has the largest ...

  9. [HTML5]a标签禁止嵌套使用

    a标签内部不可再写a标签,否则会与父a标签解析到同一级.

  10. Spring AOP 完成日志记录

    Spring AOP 完成日志记录 http://hotstrong.iteye.com/blog/1330046