项目
1. 路由分配
1.1 知识点
- 为区分主页index中不同的标签请求,使用正则路由匹配
- 路由匹配为空时,从上向下匹配时,若上面没有匹配到,则会执行空对应的路由函数
1.2 示例代码
- urls.py
-
- from django.contrib import admin
- from django.urls import path
- from django.conf.urls import url
- from app01 import views
-
- urlpatterns = [
- path('admin/', admin.site.urls),
-
- url(r'^all/(?P<type_id>\d+)', views.index),
- url(r'^login/', views.login),
- url(r'^register/', views.register),
- url(r'^check_code/', views.check_code),
- url(r'^upload_avatar/', views.upload_avatar),
- url(r'^', views.index),
- ]
2. 数据库
2.1 知识点
- auto_now_add 与 auto_now的区别
- ManyToMany 正反向操作
- 联合唯一索引与ManyToMany混合使用
- OneToOneField的正反向操作
- 枚举的使用
2.2 示例代码
- models.py
-
- from django.db import models
-
-
- class UserInfo(models.Model):
- '''
- 用户信息表
- '''
- nid = models.BigAutoField(primary_key=True)
- username = models.CharField(verbose_name='用户名', max_length=32, unique=True)
- password = models.CharField(verbose_name='密码', max_length=64)
- nickname = models.CharField(verbose_name='昵称', max_length=32)
- email = models.EmailField(verbose_name='邮箱', unique=True)
- avatar = models.ImageField(verbose_name='头像')
-
- create_time = models.DateField(verbose_name='创建时间', auto_now_add=True)
-
- U2U = models.ManyToManyField(verbose_name='粉丝们',
- to='UserInfo',
- through='UserFans',
- through_fields=('user', 'follwers'),
- related_name='fans',
- )
-
-
- class UserFans(models.Model):
- '''
- 互粉关系表
- '''
- nid = models.BigAutoField(primary_key=True)
- user = models.ForeignKey(verbose_name='博主', to='UserInfo', to_field='nid', related_name='user', on_delete=models.CASCADE)
- follwers = models.ForeignKey(verbose_name='粉丝', to='UserInfo', to_field='nid', related_name='follwers', on_delete=models.CASCADE)
-
-
- class Meta:
- unique_together = [
- ('user', 'follwers'),
- ]
-
-
- class Blog(models.Model):
- '''
- 博客信息表
- '''
- nid = models.BigAutoField(primary_key=True)
- title = models.CharField(verbose_name='个人博客标题', max_length=64)
- theme = models.CharField(verbose_name='个人博客主题', max_length=32)
- site = models.CharField(verbose_name='个人博客域名', max_length=32, unique=True)
- user = models.OneToOneField(verbose_name='博客用户', to='UserInfo', to_field='nid', on_delete=models.CASCADE)
-
-
- class Article(models.Model):
- '''
- 文章信息表
- '''
- nid = models.BigAutoField(primary_key=True)
- title = models.CharField(verbose_name='文章标题', max_length=128)
- summary = models.CharField(verbose_name='文章简介', max_length=255)
- create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
- blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE)
- category = models.ForeignKey(verbose_name='文章类型', to='Category', to_field='nid', null=True, on_delete=models.CASCADE)
-
-
-
- read_count = models.IntegerField(default=0)
- comment_count = models.IntegerField(default=0)
- up_count = models.IntegerField(default=0)
- down_count = models.IntegerField(default=0)
-
- type_choice = [
- (1, 'Python'),
- (2, 'Linux'),
- (3, '人工智能'),
- (4, '区块链'),
- (5, 'Golang'),
- ]
-
-
- article_type_id = models.IntegerField(choices=type_choice, default=None)
-
-
- tags = models.ManyToManyField(verbose_name='标签类型',
- to='Tag',
- through='Article2Tag',
- through_fields=('article', 'tag'))
-
-
- class Category(models.Model):
- '''
- 个人用户文章分类
- '''
- nid = models.AutoField(primary_key=True)
- title = models.CharField(verbose_name='分类标题', max_length=32)
- blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE)
-
-
- class Tag(models.Model):
- '''
- 标签表
- '''
- nid = models.AutoField(primary_key=True)
- title = models.CharField(verbose_name='标签名称', max_length=32 )
- blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete=models.CASCADE)
-
-
- class Article2Tag(models.Model):
- '''
- 文章to标签 多对多 关系表
- '''
- nid = models.BigAutoField(primary_key=True)
- article = models.ForeignKey(verbose_name='文章', to='Article', to_field='nid', on_delete=models.CASCADE)
- tag = models.ForeignKey(verbose_name='标签', to='Tag', to_field='nid', on_delete=models.CASCADE)
-
- class Meta:
- unique_together = [
- ('article', 'tag'),
- ]
-
-
- class ArticleDetail(models.Model):
- '''
- 文章详细表
- '''
- content = models.TextField(verbose_name='文章内容')
- article = models.OneToOneField(verbose_name='所属文章', to='Article', to_field='nid', on_delete=models.CASCADE)
-
-
- class UpDown(models.Model):
- '''
- 文章 顶/踩
- '''
- article = models.ForeignKey(verbose_name='所属文章', to='Article', to_field='nid', on_delete=models.CASCADE)
- user = models.ForeignKey(verbose_name='顶或踩的用户', to='UserInfo', to_field='nid', on_delete=models.CASCADE)
- up = models.BooleanField(verbose_name='是否赞')
-
- class Meta:
- unique_together = [
- ('article', 'user'),
- ]
-
-
- class Comment(models.Model):
- '''
- 文章评论表
- '''
- nid = models.BigAutoField(primary_key=True)
- content = models.CharField(verbose_name='评论内容', max_length=255)
- create_time = models.DateTimeField(verbose_name='评论时间', auto_now_add=True)
- article = models.ForeignKey(verbose_name='被评论文章', to='Article', to_field='nid', on_delete=models.CASCADE)
- user = models.ForeignKey(verbose_name='评论者', to='UserInfo', to_field='nid', on_delete=models.CASCADE)
- reply = models.ForeignKey(verbose_name='被回复评论', to='self', to_field='nid', null=True, on_delete=models.CASCADE)
3. 主页
3.1 知识点
- 获取当前请求request的URL
- 数据库操作models.filter(**kwargs)为空字典时,将会获取全部数据
- 通过数据库中的枚举,实现显示主页的标签
- BootStrap中 class 默认navbar是圆角的 如果不想要 则需自己定制 类 no-radius
- container-fluid 表示100%平铺 如果改成container 就可以设置宽度 并且container中包括响应式
- 前端可直接调用request
- 前端中文字与图片的排版
- BootStrap中 class = ‘clearfix’ 相当于在类所在标签的最后增加一个空标签 clear:both 用于清除浮动
3.2 示例代码
- Views.py
-
- def index(request, *args, **kwargs):
- '''
- 主页
- :param request:
- :param args:
- :param kwargs:
- :return:
- '''
- result = request.session.get('username')
- if result:
-
-
-
- current_page = request.GET.get('page')
- base_url = request.path_info
-
-
-
-
-
-
-
-
-
-
- content = {}
- type_id = int(kwargs.get('type_id')) if kwargs.get('type_id') else None
- if type_id:
- content['article_type_id'] = type_id
-
-
- all_count = models.Article.objects.filter(**content).count()
- page_info = PageInfo(current_page, all_count, 10, base_url, 11)
-
- article_list = models.Article.objects.filter(**content)[page_info.start():page_info.end()]
-
- type_choice = models.Article.type_choice
- login_flag = True
- return render(request, 'index.html', {
- 'type_choice': type_choice,
- 'article_list': article_list,
- 'type_id': type_id,
- 'page_info': page_info,
- 'login_flag': login_flag
- })
- else:
- return redirect('/login/')
- index.html
4. 注册
4.1 知识点
4.2 示例代码
- forms.py
- register.html
- Views.py
5. 登陆
5.1 知识点
5.2 示例代码
- login.html
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <meta http-equiv="x-ua-compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1">
- <title>Title</title>
- <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css">
-
- <style>
- .login {
- margin: 0 auto;
- width: 600px;
- padding: 20px;
- margin-top: 80px;
- }
-
- .head {
- text-align: center;
- padding: 10px;
- margin-bottom: 20px;
- margin-left: 90px;
- margin-top: -60px;
- }
-
- .logined, .register {
- width: 460px;
- }
- </style>
- </head>
-
- <body>
- <div class="login">
- <div class="head">
- <h2><a href="/login/">用户登陆</a></h2>
- </div>
-
- <div>
- <form class="form-horizontal" novalidate method="post" action="/login/">
- {% csrf_token %}
- {% for row in range %}
- <div class="form-group">
- <label class="col-sm-2 control-label">用户名</label>
- <div class="col-sm-10">
-
- {{ my_login_form.username }}{{ my_login_form.errors.username.0 }}{{ user_error }}
- </div>
- </div>
- <div class="form-group">
- <label class="col-sm-2 control-label">密码</label>
- <div class="col-sm-10">
-
- {{ my_login_form.password }}{{ my_login_form.errors.password.0 }}
- </div>
- </div>
- <div class="form-group">
- <label class="col-sm-2 control-label">验证码</label>
- <div class="col-sm-3">
-
- {{ my_login_form.code }}{{ my_login_form.errors.code.0 }}{{ code_error }}
- </div>
- <div class="col-sm-5">
-
-
-
- <img id="check_code" style="width: 120px;height: 30px" src="/check_code/">
-
- </div>
- </div>
- <div class="form-group">
- <div class="col-sm-offset-2 col-sm-10">
- <button type="submit" class="btn btn-default logined">登陆</button>
- </div>
- </div>
- <div class="form-group">
- <div class="col-sm-offset-2 col-sm-10">
- <a href="/register/">
- <button type="button" class="btn btn-default register">注册</button>
- </a>x
- </div>
- </div>
- </form>
- </div>
- </div>
- <script src="/static/jquery-3.3.1.js"></script>
- <script>
-
- $('#check_code').click(function () {
- $('#check_code')[0].src = $('#check_code')[0].src + '?'
- })
-
- </script>
-
- </body>
- </html>
- form.py
-
- class MyLoginForm(Form):
- '''
- 用户登陆Form
- '''
- username = fields.CharField(max_length=32,
- error_messages={
- 'required': '用户名不能为空',
- 'max_length': '用户名最多为32个字符',
- },
- widget=widgets.TextInput(
- attrs={
- 'class': "form-control",
- 'placeholder': "用户名",
- }
- ))
- password = fields.CharField(
- max_length=32,
- min_length=6,
- error_messages={
- 'required': '密码不能为空',
- 'max_length': '密码最多为32个字符',
- 'min_length': '密码最多为6个字符',
- },
- widget=widgets.PasswordInput(
- attrs={
- 'name': 'password',
- 'class': "form-control",
- 'placeholder': "密码",
- }))
- code = fields.CharField(max_length=5, min_length=5,
- error_messages={
- 'required': '验证码不能为空',
- 'max_length': '验证码只能为5个字符',
- 'min_length': '验证码只能为5个字符',
- },
- widget=widgets.TextInput(
- attrs={
-
- 'class': "form-control",
- 'placeholder': "验证码",
- }
- ))
- Views.py
posted @
2018-07-09 18:23
LexSama
阅读(
225)
评论()
编辑
收藏
举报