BBS

準備css

  新建工程html

    django-admin startproject BBS前端

  新建appnode

    python3 manage.py startapp bbspython

設計表結構數據庫

from django.db import models

# Create your models here.
from django.db import models
from django.contrib.auth.models import User

# Create your models here.



class UserProifle(models.Model):
    user = models.OneToOneField(User)
    name = models.CharField(max_length=32)
    def __str__(self):
        return self.name

class Article(models.Model):
    """文章表"""
    title = models.CharField(max_length=128,unique=True)
    author = models.ForeignKey("UserProifle")
    category = models.ForeignKey("Category")
    pub_date = models.DateTimeField(auto_now_add=True,auto_created=True)
    tags = models.ManyToManyField("Tag", null=True)
    body = models.TextField(max_length=100000)
    head_img = models.ImageField(upload_to="uploads")
    status_choices = ((0,'草稿'),(1,'發佈'),(2,'隱藏'))
    priority = models.SmallIntegerField(default=1000,verbose_name="優先級")

    def __str__(self):
        return self.title

class Category(models.Model):
    """板塊"""
    name = models.CharField(max_length=64,unique=True)
    set_as_top_menu = models.BooleanField(default=True)

    def __str__(self):
        return self.name


class Tag(models.Model):
    """標籤表"""
    name = models.CharField(max_length=64, unique=True)
    def __str__(self):
        return self.name

class Comment(models.Model):
    """評論"""
    article = models.ForeignKey("Article")
    p_node = models.ForeignKey("Comment",null=True,blank=True,related_name='my_child_comment')

    user = models.ForeignKey("UserProifle")
    date = models.DateTimeField(auto_now_add=True)
    comment = models.TextField(max_length=1024)


    def __str__(self):
        return self.comment

class Like(models.Model):
    """點贊"""
    article = models.ForeignKey("Article")
    user = models.ForeignKey("UserProifle")
    date = models.DateTimeField(auto_now_add=True)


class PrivateMail(models.Model):
    """私信"""
    pass

評論自關聯,須要加上related_name,null=True默承認覺得空,可是在django中須要加上blank=Truedjango

admin

django amdin是django提供的一個後臺管理頁面,該管理頁面提供完善的html和css,使得你在經過Model建立完數據庫表以後,就能夠對數據進行增刪改查,而使用django admin 則須要如下步驟:bootstrap

  • 建立後臺管理員
  • 配置url
  • 註冊和配置django admin後臺管理頁面

一、建立後臺管理員app

1
python manage.py createsuperuser

二、配置後臺管理urlpost

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

三、註冊和配置django admin 後臺管理頁面

a、在admin中執行以下配置

1
2
3
4
5
6
7
8
from  django.contrib  import  admin
  
from  bbs  import   models
  
admin.site.register(models.UserProfile)
admin.site.register(models.Article)
admin.site.register(models.Comments)
admin.site.register(models.Category)

b、設置數據表名稱

1
2
3
4
5
6
class  UserType(models.Model):
     name  =  models.CharField(max_length = 50 )
  
     class  Meta:
         verbose_name  =  '用戶類型'
         verbose_name_plural  =  '用戶類型'

c、打開表以後,設定默認顯示,須要在model中做以下配置

1
2
3
4
5
class  UserType(models.Model):
     name  =  models.CharField(max_length = 50 )
  
     def  __unicode__( self ):
         return  self .name
1
2
3
4
5
6
7
8
9
10
11
12
from  django.contrib  import  admin
  
from  app01  import   models
  
class  UserInfoAdmin(admin.ModelAdmin):
     list_display  =  ( 'username' 'password' 'email' )
  
  
admin.site.register(models.UserType)
admin.site.register(models.UserInfo,UserInfoAdmin)
admin.site.register(models.UserGroup)
admin.site.register(models.Asset)

d、爲數據表添加搜索功能

1
2
3
4
5
6
7
8
9
10
11
12
from  django.contrib  import  admin
  
from  app01  import   models
  
class  UserInfoAdmin(admin.ModelAdmin):
     list_display  =  ( 'username' 'password' 'email' )
     search_fields  =  ( 'username' 'email' )
  
admin.site.register(models.UserType)
admin.site.register(models.UserInfo,UserInfoAdmin)
admin.site.register(models.UserGroup)
admin.site.register(models.Asset)

 

bootstrap

  bootstrap的三個文件夾css fonts js放入statics目錄下

  好看的頁面下載所有到本地,會有個文件夾,包含了這個頁面所用到的css,js,放入statics下的css和js目錄下,下載下來的html頁面中的css,js的引用路徑須要換一下

 

頁面有不一樣的板塊,點擊板塊高亮而且顯示對應板塊下的文章

不一樣板塊的都是同一模板html,只是顯示的url不一樣,根據urls.py裏面的別名作

html :{% url 'category' i.id%} --category是urls.py的name

urls.py: url(r'^category/(\d+)/$',views.category,name='category') --前一個category是點擊板塊時顯示的url

點擊板塊顯示文章而且高亮

<li><a href="{% url 'category' i.id %}">{{ i.name }}</a></li>
views.py拿到這個id後去文章表中取出板塊對應的文章
前端頁面request.path獲得當前頁面的地址,經過js加上active,這段js須要寫在base.html中

圖標base
<link href="http://libs.baidu.com/fontawesome/4.0.3/css/font-awesome.css" rel="stylesheet">

head_img
simple_tag
上傳的圖片找不到須要進行如下步驟
app下新建templatetags目錄
目錄下新建xxoo.py
from django import template

register = template.Library()
@register.simple_tag

def truncate_upload_img(img_src):
    return img_src.name.lstrip('/uploads/')

前端頁面引用的時候

<img src="/static/{% truncate_upload_img i.head_img %}"

分頁

views.py

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

paginator = Paginator(articles, 5)  # Show 5 contacts per page
page = request.GET.get('page')url中傳來的?page
try:
objs = paginator.page(page)
except PageNotAnInteger:
objs = paginator.page(1)
except EmptyPage:
objs = paginator.page(paginator.num_pages)
return render(request,'index.html',{'category':categories,'article':objs})

simple_tag

def paginator_btn(article,page):
    current_page = article.number
    if abs(current_page-page)<3:
        ele = """<li><a href="?page={page}">{page}</a></li>""".format(page=page)
        return mark_safe(ele)
    return ''

 

html 

            <nav aria-label="...">
              <ul class="pagination">
                <li class="disabled"><a href="#" aria-label="Previous"><span aria-hidden="true">&laquo;</span></a></li>
                {% for page in article.paginator.page_range %}
                  {% if article.number == page %}
                    <li class="active"><a href="?page={{ page }}">{{ page }}<span class="sr-only">(current)</span></a></li>
                    {% else %}
                        {% paginator_btn article page %}
                    {% endif %}
                {% endfor %}
              </ul>
            </nav>
發佈文章ckeditor
用modelform
forms.py

from django import forms
from app01 import models

class NewArticleForm(forms. ModelForm):
  #修改modelform的new方法,給字段加樣式
def __new__(cls, *args, **kwargs): for field_name in cls.base_fields: field = cls.base_fields[field_name] attr_dic = {'class':'form-control'} field.widget.attrs.update(attr_dic) return forms.ModelForm.__new__(cls)#還須要在調用下modelform原來的new方法 class Meta: model = models.Article fields = "__all__" exclude = ('priority','author')

 


html
由於有圖片,因此form裏面加上enctype='multipart/form-data'
{% extends 'index.html' %}
{% block extra_source %}
    <script src="/static/plugins//ckeditor/ckeditor.js"></script>
{% endblock %}
{% block container %}
    <form method="post" enctype="multipart/form-data">

        {% for field in form %}
            <div class="form-group">
                <label  class="col-sm-2 control-label">{{ field.name }}</label>
                <div class="col-sm-10">
                  {{ field }}
                    <span style="color: red">{{ field.errors }}</span>
                  <span style="color: red">{{ field.errors }}</span>
                </div>
            </div>

        {% endfor %}
        <input type="submit" class="col-lg-offset-5 btn btn-sm btn-success" value="提交">
    </form>

            <script>
                // Replace the <textarea id="editor1"> with a CKEditor
                // instance, using default configuration.
                CKEDITOR.replace( 'id_body' );
            </script>
{% endblock %}

views.py

def new_article(request):
    if request.method == 'POST':
        form = forms.NewArticleForm(data=request.POST,files=request.FILES)

        if form.is_valid():
            print(request.user.id)
            form.cleaned_data['author_id'] = request.user.id
            tags = form.cleaned_data.pop('tags')
            obj = models.Article(**form.cleaned_data)
            obj.save()
            obj.tags.add(*tags)
            obj.save()
            return HttpResponse('''<h3><a href="/article/%s/">%s</a></h3>''' % (obj.id,obj.title) )
    elif request.method == 'GET':
        form = forms.NewArticleForm()
    return render(request,'new_article.html',{'form':form})

*文章和tag是多對多的關係,只能先create對象,再add tags

*由於添加modelform中去了author,因此只能在form.cleaned_data字典裏面加上author_id,request.user.id就是當前用戶的id

*{{article.body | safe}}

 

用戶登陸認證

 

from django.contrib.auth import authenticate,login,logout
from django.contrib.auth.decorators import login_required#django自帶的裝飾器

def account(request):
error={}
if request.method == 'GET':
return render(request,'login.html')
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(username=username,password=password)
  #若是認證成功,user是個對象
if user:
login(request,user)#若是認證成功,須要再login一下才能顯示當前用戶
return redirect(request.GET.get('next') or '/category/all')
else:
error = {'error':'wrong username or password'}
return render(request,'login.html',error)

login.html

{% extends "base.html" %}


{% block body %}

    <div class="container">
      <div class="col-lg-3 col-lg-offset-4">
          <form class="form-signin" method="post"> {% csrf_token %}
                <h2 class="form-signin-heading">1024黃鱔社區</h2>
                <label for="inputEmail" class="sr-only">Username</label>
                <input type="text" 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>

                <span style="color: red">{{ error }}</span>
                <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>
          </form>

      </div>


    </div>


{% endblock %}

 

html

<ul class="nav navbar-nav navbar-right">
             <li class=""><a href="{% url 'new_article'  %}">發帖</a></li>#只有登陸了,才能發帖,views.py裏會驗證
             {% if request.user.is_authenticated %}
          #只有認證了,才顯示當前用戶
                 <li class="dropdown">
                  <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">{{ request.user }} <span class="caret"></span></a>
                  <ul class="dropdown-menu">
                    <li><a href="{% url 'logout' %}">Logout</a></li>
                  </ul>
                 </li>
             {% else %}
                <li class=""><a href="{% url 'login'  %}">登陸</a></li>#這裏默認會是accounts/login,須要在settings.py中修改,寫上LOGIN_URL ="/account/login/"
 {% endif %} </ul>

退出

def acc_logout(request):
    logout(request)
    return redirect('/login')

 

多級評論

#1.把數據庫裏全部的這篇文章的評論查出來,轉成字典

#2.遞歸循環字典,生成html

 

在文章html頁加

    <div style="border: 1px dashed red">
    {% load_comments article%}
    </div>

經過simple_tag業務邏輯全寫在bbs_tags.py中

from  django.template import Library
from django.utils.safestring import mark_safe

register = Library()

@register.simple_tag
def load_comments(article):
    comment_dic = {}#評論存在字典中
    comment_objs = article.comment_set.all().order_by('date')#經過文章反查comment
    for obj in comment_objs:
        if not obj.p_node:#就是頂級評論
            comment_dic[obj] = {}
        else:#不是頂級評論
            build_comment_tree(comment_dic,obj)
    comment_list = sorted(comment_dic.items(),key=lambda x:x[0].date)#按時間順序排列
    print(comment_dic)
    return(comment_dic)
def build_comment_tree(comment_dic,obj):
    for k,v in comment_dic.items():
        if obj.p_node == k:找到父級評論
            comment_dic[k][obj]={}
        else:#開始深度查找
            build_comment_tree(comment_dic[k],obj)

字典轉換成html格式

@register.simple_tag
def load_comments(article):
    comment_dic = {}
    comment_objs = article.comment_set.all().order_by('date')
    for obj in comment_objs:
        if not obj.p_node:
            comment_dic[obj] = {}
        else:
            build_comment_tree(comment_dic,obj)
    comment_list = sorted(comment_dic.items(),key=lambda x:x[0].date)
    print(comment_list)
    comment_html = """"""
    for comment_branch in comment_list:
        margin=0
        html_ele = """<div style="border:1px dashed red">{user}--{date}--{comment}</div>"""\
            .format(user=comment_branch[0].user,
                    date=comment_branch[0].date.strftime('%Y-%M-%D %H:%M:%S'),
                    comment = comment_branch[0].comment)
        comment_html += html_ele
        comment_html += build_comment_html(comment_branch[1],margin+20)

    return mark_safe(comment_html)

def build_comment_tree(comment_dic,obj):
    for k in comment_dic:
        if obj.p_node == k:
            comment_dic[k][obj]={}
        else:
            build_comment_tree(comment_dic[k],obj)
def build_comment_html(comment_branch,margin):
    comment_ele = """"""
    for k,v in comment_branch.items():
        comment_ele += """<div style="border:1px dashed red;margin-left:{margin}px">{user}--{date}--{comment}</div>""" \
            .format(margin=margin,
                    user=k.user,
                    date=k.date.strftime('%Y-%M-%D %H:%M:%S'),
                    comment=k.comment,
                    )
        if v:
            comment_ele += build_comment_html(comment_branch[k],margin+20)
    return comment_ele
相關文章
相關標籤/搜索