models.py 相关模型:
# 分类表 class Category(models.Model): name = models.CharField(max_length=40, null=False) # 分类名 def __str__(self): return self.name # 文章表 class Article(models.Model): title = models.CharField(max_length=100, null=False) # 标题 intro = models.CharField(max_length=1000) # 导语 abstract = models.TextField() # 摘要 category = models.ForeignKey(Category, related_name="cate") #连接分类表的外键,多对一关系 content = models.TextField(null=False) # 内容 publish_time = models.DateTimeField(null=False, default=now) # 发布时间 image = models.FileField(upload_to='article_image') # 文章配图 source_link = models.CharField(max_length=200) # 原文链接 author_name = models.CharField(max_length=100, null=False) # 作者名字 author_avatar = models.FileField(upload_to='author_avatar') # 作者头像 author_desc = models.CharField(max_length=100, null=False) # 作者签名 def __str__(self): return self.title #在后台中以文章标题显示 # 精选文章 class Best(models.Model): select_article = models.ForeignKey(Article, related_name='select_article') # 被精选的文章 SELECT_REASON = ( ('今日新闻', '今日新闻'), ('首页推荐', '首页推荐'), ('编辑推荐', '编辑推荐') ) select_reason = models.CharField(choices=SELECT_REASON, max_length=50, null=False) # 精选的理由 def __str__(self): return self.select_reason + '-' + self.select_article.title # 用户信息表 class UserProfile(models.Model): belong_to = models.OneToOneField(to=User, related_name="profile") # 所属用户 avatar = models.FileField(upload_to='avatar') # 用户头像 def __str__(self): return self.belong_to.username # 评论表 class Comment(models.Model): belong_article = models.ForeignKey(Article, related_name='article') # 评论所属的文章 belong_user = models.ForeignKey(User, related_name='user') # 评论者 words = models.CharField(max_length=200, null=False) # 评论内容 created = models.DateTimeField(null=False, default=now) # 评论时间 def __str__(self): return self.belong_user.username + ': ' + self.words
自定义评论表单 forms.py:
def words_validator(comment): if len(comment)<5: raise ValidationError("您输入的评论字数太短,请重新输入至少5个字符") class CommentForm(forms.Form): comment = forms.CharField(widget=forms.Textarea(),validators=[words_validator])
view.py:
def detail(request,article_id): cates = Category.objects.all().order_by("-id") #分类列表 editor_recommendtop3 = Best.objects.filter(select_reason="编辑推荐")[:3] editor_recommendtop3list = [i.select_article for i in editor_recommendtop3] #取出三篇编辑推荐作为大标题 editor_recommend = Best.objects.filter(select_reason="编辑推荐")[3:10] editor_recommendlist = [i.select_article for i in editor_recommend] #再取出七篇编辑推荐 article = Article.objects.get(id=article_id) comments = Comment.objects.filter(belong_article=article) form = CommentForm() if request.method == "POST": form = CommentForm(request.POST) if form.is_valid(): words = form.cleaned_data.get("comment") comment = Comment(belong_user=request.user,words=words,belong_article=Article.objects.get(id=article_id)) comment.save() form = CommentForm() context =[] context ={ "cates":cates, "editor_recommendtop3list":editor_recommendtop3list, "editor_recommendlist":editor_recommendlist, "article":article, "comments":comments, "form":form } return render(request,'detail.html',context=context)
模板css detail.css:
a{color:black;} .ui.red.basic.segment.topmenu{ height: 100px; padding-left:140px; padding-right: 140px; border-bottom: 1px solid rgb(189, 189, 189); } .ui.borderless.menu.container > .item > a{ color: black; font-weight: bold; } .ui.basic.segment.title{ background: rgba(110, 110, 110,0.7); position: absolute; width: 100%; height: 70px; left:0; bottom: 0; } .ui.horizontal.basic.segments.bodycontent{ padding-top: 20px; border-radius: 0; border: none; box-shadow: none; } .ui.segment.bodyleft{ width: 700px; } .ui.basic.segment.articleimg{ width: 700px; height: 384px; padding-top: 216px; padding-right: 29px; padding-left: 29px; } .ui.basic.segment.articleimg > hr{ border : 1px dashed white; } .image-text{ color: white; font-size: 40px; line-height: 1.3; } .ui.basic.segment.articleimg > span{ color: rgb(236, 236, 236); font-size: 20px; position: absolute; bottom: 17px; right: 29px; } .ui.center.aligned.basic.segment.abstract{ width: 200px; margin: 0 auto; color: #9b9b9b; font-size: 16px; font-weight: normal; line-height: 3; } .column > .ui.basic.segment{ height: 200px; } .ui.basic.segment.comment{ margin-top: 50px; border-top: 2px solid red; } .comment{ position: relative; margin-top: 60px; } .time{ color: #9b9b9b; position: relative; top:-15px; } .black-reply{ position: absolute; bottom:0; left: 52px; } .red-reply{ color: red; position: absolute; bottom: -35px; left:62px; } .ui.segment.bodyright{ width: 100px; } .ui.red.segment.best{ border-left:none; border-right:none; border-bottom:none; box-shadow:none; border-radius: 0; padding-left: 0; padding-right: 0; } .ui.segment.top3{ height: 120px; padding-top: 0; position: relative; border: none; box-shadow: none; } .sidebutton > p{ position: absolute; top:0; left:20px; color:white; } .ui.segment.bestlast{ border-radius: 0; height: 60px; padding-top: 0; border: none; box-shadow: none; } .ui.segment.bestlast > img{ position: absolute; top:4px; left:0; } .ui.segment.bestlast > p{ font-size: 12px; } .ui.segment.bestlast > span{ font-size: 12px; color: rgb(206, 208, 204); position: absolute; bottom: 0; } .ui.basic.segment.bottomblack{ height: 400px; background-color: rgb(50,50,50); padding-left: 250px; padding-top: 100px; margin-top: 100px; } .ui.circular.red.button.backtotop{ height: 60px; position: absolute; transform: translate(-50%,-50%); left: 50%; bottom:-15%; } .ui.basic.segment.wechat{ position: absolute; top:80px; right: 250px; margin-top: 0; } .ui.basic.segment.bottomwhite{ padding-left: 250px; border-bottom: 2px solid red; } .ui.basic.segment.bottomwhite > p{ font-size: 20px; }
模板html detail.html:
<!DOCTYPE html> {% load staticfiles %} <html> <head> <meta charset="utf-8"> <title>详情页</title> <link rel="stylesheet" href="{% static 'css/semantic.css' %}" media="screen" title="no title" charset="utf-8"> <link rel="stylesheet" href="{% static 'css/detail.css' %}" media="screen" title="no title" charset="utf-8"> </head> <body> <div class="ui red basic segment topmenu"> <div class="ui borderless menu container" style="border:0;box-shadow:none;"> <div class="header item" style="margin-right:10px;"> <div class="ui image"> <img src="{%static 'images/index/zhiribao.png' %}" alt="" /> </div> </div> <div class="item" style="margin-right:10px;"> <a href="{% url 'index' %}">首页</a> </div> {% for cate in cates %} <div class="item" style="margin-right:10px;"> <a href="/category/{{cate.id}}">{{cate.name}}</a> </div> {% endfor%} <div class="right menu login"> {% if request.user.is_authenticated %} <div class="item"> <a href="{% url 'profile' %}"><div class="ui image"> <img src="/upload/{{ request.user.profile.avatar }}" style="height:26px;24px;" alt="" /> </div> <p style="margin-right:10px;margin-top:6px;color:black;">{{ request.user.username }}</p> </a> </div> <div class="item"> <a href="{% url "logout" %}"> 退出 </a> </div> {% else %} <div class="item"> <a href="{% url 'login' %}"><div class="ui image"> <img src="{% static 'images/index/login.png' %}" alt="" /> </div> <p style="margin-right:10px;margin-top:6px;color:black;">登录</p> </a> </div> <div class="item"> <a href="{% url 'register' %}"> <div class="ui image"> <img src="{% static 'images/index/register.png' %}" alt="" /> </div> <p style="color:black;">注册</p> </a> </div> {% endif %} </div> </div> </div> <div class="ui basic segment container"> <div class="ui horizontal basic segments bodycontent"> <div class="ui segment bodyleft" style="border:none;box-shadow:none;"> <div class="ui basic segment articleimg" style="background:url('/upload/{{article.image}}');background-size: cover; background-repeat: no-repeat;"> <hr> <div class="image-text" > {{article.title}} </div> <span>图片:Zoommy</span> </div> <div class="ui center aligned basic segment abstract"> *** <br> {{article.abstract}} <br> *** </div> <div class="ui basic segment articledetail"> <h1>{{article.title}}</h1> <p> <div class="ui mini image" style="position:relative;top:-2px;left:5px;"> <img src="/upload/{{article.author_avatar}}" alt="" /> </div> <span style="font-size:16px;color: #000000;margin-left:10px;"> {{ article.author_name }}</span> <span style="color:grey;font-size:16px;">{{ article.author_desc }}</span> <p style="color:#000000;600px;font-size:16px;margin-top:20px;line-height:2;"> {{article.content}} </p> <a href="{{article.source_link}}"><span style="border-bottom:1px solid red;font-size:16px;margin-top:50px;margin-left:520px;">查看原文</span></a> </div> <div class="ui basic segment comment"> <p ><b>评论</b></p> {% for comment in comments %} <div class="comment" style="margin-top:22px;margin-bottom:20px;"> <div class="ui image" style="height:50px;50px;"> <img src="/upload/{{ comment.belong_user.profile.avatar }}" style="height:50px;50px;" alt="" /> </div> <span class="time"> <b style="color:black;">{{comment.belong_user.username}}</b> {{comment.created}}</span> <span class="black-reply"> {{comment.words}}</span> </div> {% endfor %} <form class="ui error form" method="post" > {% if form.errors %} <div class="ui error" > {{form.errors}} </div> {% endif %} {{form.comment}} {% if request.user.is_authenticated %} <button class="ui red button" style="144px;height:49px;position:relative;top:60px;" type="submit"> <span style="color: #ffffff;font-size: 20px;font-weight: bold;">写评论</span> </button> {% endif %} {% csrf_token %} </form> </div> </div> <div class="ui segment bodyright" style="border:none;box-shadow:none;"> <div class="ui red segment best"> <h4 class="ui center aligned header"><b>编辑推荐</b></h4> {% for editor_recommendtop3 in editor_recommendtop3list %} <div class="ui segment top3" style="background:url('/upload/{{editor_recommendtop3.image}}'); background-size:cover;background-repeat:no-repeat;border-radius:0;"> <div class="sidebutton"> <img src="{% static 'images/index/redtag.png' %}" alt="" /> <p>Top{{ forloop.counter }}</p> </div> <div class="ui basic segment title" style="height:40px;padding-top:2px;"> <p style="font-size:14px;margin-left:0px;"><a href="/detail/{{editor_recommendtop3.id}}" style="color:#fff;">{{editor_recommendtop3.title}}</a></p> </div> </div> {% endfor %} {% for editor_recommend in editor_recommendlist %} <div class="ui segment bestlast"> <img src="{% static 'images/index/Triangle.png' %}" alt="" /> <p> <a href="/detail/{{editor_recommend.id}}"> {{editor_recommend.title}} </a> </p> <span>{{editor_recommend.publish_time | date:"Y-m-d"}}</span> </div> {% endfor %} <div class="ui image"> <img src="{% static 'images/index/ad.png' %}" alt="" style="300px;"/> </div> </div> </div> </div> </div> <div class="ui basic segment bottomblack"> <div class="ui image"> <img src="{% static 'images/index/white_zhiribao.png' %}" alt="" /> </div> <p style="color:red;margin-top:50px;font-size:20px;"> 关于我们<span style="color:rgb(143, 143, 143)">|</span>加入我们<span style="color:rgb(143, 143, 143)">|</span>联系我们|寻求报道 </p> <p style="color:white;font-size:20px;"> 反馈建议:<span style="color:red;">124608760@qq.com</span> </p> <div class="ui basic segment wechat"> <img src="{% static 'images/index/qrcode.png' %}" style="margin-left:38px;"/> <h2 class="ui header" style="color:rgb(255, 255, 255);margin-left:20px;">扫码关注微信号</h2> </div> <button type="button" name="button" class="ui circular red button backtotop"> <img src="{% static 'images/index/upicon.png' %}" style="position:absolute;left:18%;top:10%;"> <img src="{% static 'images/index/TOP.png' %}" style="position:absolute;left:18%;bottom:28%;"> </button> </div> <div class="ui basic segment bottomwhite"> <p> Designed by Mugglecoding </p> <p> Developed by XYX </p> <p style="position:absolute;right:250px;top:40px;"> 京ICP备123878345号 </p> </div> </body> </html>
urls.py:
url(r'^detail/(?P<article_id>d+)/$', detail, name='detail')