This commit is contained in:
commit
5fec1d1fc5
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="django" name="Django">
|
||||
<configuration>
|
||||
<option name="rootFolder" value="$MODULE_DIR$" />
|
||||
<option name="settingsModule" value="settings.py" />
|
||||
<option name="manageScript" value="manage.py" />
|
||||
<option name="environment" value="<map/>" />
|
||||
<option name="doNotUseTestRunner" value="false" />
|
||||
<option name="trackFilePattern" value="migrations" />
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
<component name="TemplatesService">
|
||||
<option name="TEMPLATE_CONFIGURATION" value="Django" />
|
||||
</component>
|
||||
</module>
|
|
@ -0,0 +1,6 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.7" project-jdk-type="Python SDK" />
|
||||
</project>
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/blog.iml" filepath="$PROJECT_DIR$/.idea/blog.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/../.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
|
@ -0,0 +1,71 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="c4898c06-8fd7-45b7-8b1e-9ba196f6aa51" name="Default Changelist" comment="">
|
||||
<change beforePath="$PROJECT_DIR$/../logs/blog.log" beforeDir="false" afterPath="$PROJECT_DIR$/../logs/blog.log" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../static/js/index.js" beforeDir="false" afterPath="$PROJECT_DIR$/../static/js/index.js" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../templates/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/../templates/index.html" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../users/urls.py" beforeDir="false" afterPath="$PROJECT_DIR$/../users/urls.py" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/../users/views.py" beforeDir="false" afterPath="$PROJECT_DIR$/../users/views.py" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$/../.." />
|
||||
</component>
|
||||
<component name="ProjectId" id="230BVlZklfykHjZmhGjoxvPoTVn" />
|
||||
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
|
||||
<component name="ProjectViewState">
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent">
|
||||
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
|
||||
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
|
||||
<property name="WebServerToolWindowFactoryState" value="false" />
|
||||
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="RunManager">
|
||||
<configuration name="blog" type="Python.DjangoServer" factoryName="Django server">
|
||||
<module name="blog" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="PARENT_ENVS" value="true" />
|
||||
<envs>
|
||||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="" />
|
||||
<option name="IS_MODULE_SDK" value="false" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||
<option name="launchJavascriptDebuger" value="false" />
|
||||
<option name="port" value="8000" />
|
||||
<option name="host" value="" />
|
||||
<option name="additionalOptions" value="" />
|
||||
<option name="browserUrl" value="" />
|
||||
<option name="runTestServer" value="false" />
|
||||
<option name="runNoReload" value="false" />
|
||||
<option name="useCustomRunCommand" value="false" />
|
||||
<option name="customRunCommand" value="" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task">
|
||||
<changelist id="c4898c06-8fd7-45b7-8b1e-9ba196f6aa51" name="Default Changelist" comment="" />
|
||||
<created>1640861149677</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1640861149677</updated>
|
||||
<workItem from="1640861150893" duration="8000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="3" />
|
||||
</component>
|
||||
</project>
|
Binary file not shown.
|
@ -42,6 +42,7 @@ INSTALLED_APPS = [
|
|||
'django.contrib.staticfiles',
|
||||
#子应用的注册
|
||||
'users.apps.UsersConfig',
|
||||
'home.apps.HomeConfig'
|
||||
]
|
||||
|
||||
MIDDLEWARE = [
|
||||
|
@ -52,6 +53,7 @@ MIDDLEWARE = [
|
|||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||
'django.contrib.messages.middleware.MessageMiddleware',
|
||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||
|
||||
]
|
||||
|
||||
ROOT_URLCONF = 'blog.urls'
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,3 +1,5 @@
|
|||
from django.contrib import admin
|
||||
|
||||
from home.models import ArticleCategory
|
||||
# Register your models here.
|
||||
from home.models import ArticleCategory
|
||||
admin.site.register(ArticleCategory)
|
|
@ -0,0 +1,28 @@
|
|||
# Generated by Django 2.1.1 on 2021-12-30 12:33
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ArticleCategory',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('title', models.CharField(blank=True, max_length=100)),
|
||||
('created', models.DateTimeField(default=django.utils.timezone.now)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': '类别管理',
|
||||
'verbose_name_plural': '类别管理',
|
||||
'db_table': 'tb_category',
|
||||
},
|
||||
),
|
||||
]
|
|
@ -0,0 +1,40 @@
|
|||
# Generated by Django 2.1.1 on 2021-12-31 10:14
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import django.utils.timezone
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('home', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Article',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('avatar', models.ImageField(blank=True, upload_to='article/%Y%m%d/')),
|
||||
('tags', models.CharField(blank=True, max_length=20)),
|
||||
('title', models.CharField(max_length=100)),
|
||||
('sumary', models.CharField(max_length=200)),
|
||||
('content', models.TextField()),
|
||||
('total_views', models.PositiveIntegerField(default=0)),
|
||||
('comments_count', models.PositiveIntegerField(default=0)),
|
||||
('created', models.DateTimeField(default=django.utils.timezone.now)),
|
||||
('updated', models.DateTimeField(auto_now=True)),
|
||||
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
('category', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='article', to='home.ArticleCategory')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': '文章管理',
|
||||
'verbose_name_plural': '文章管理',
|
||||
'db_table': 'tb_article',
|
||||
'ordering': ('-created',),
|
||||
},
|
||||
),
|
||||
]
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,3 +1,87 @@
|
|||
from django.db import models
|
||||
from django.utils import timezone
|
||||
from users.models import User
|
||||
class ArticleCategory(models.Model):
|
||||
"""
|
||||
文章分类
|
||||
"""
|
||||
# 栏目标题
|
||||
title = models.CharField(max_length=100, blank=True)
|
||||
# 创建时间
|
||||
created = models.DateTimeField(default=timezone.now)
|
||||
|
||||
# Create your models here.
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
class Meta:
|
||||
db_table='tb_category'
|
||||
verbose_name = '类别管理'
|
||||
verbose_name_plural = verbose_name
|
||||
|
||||
from django.utils import timezone
|
||||
|
||||
class ArticleCategory(models.Model):
|
||||
"""
|
||||
文章分类
|
||||
"""
|
||||
# 栏目标题
|
||||
title = models.CharField(max_length=100, blank=True)
|
||||
# 创建时间
|
||||
created = models.DateTimeField(default=timezone.now)
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
class Meta:
|
||||
db_table='tb_category'
|
||||
verbose_name = '类别管理'
|
||||
verbose_name_plural = verbose_name
|
||||
class Article(models.Model):
|
||||
"""
|
||||
文章
|
||||
"""
|
||||
# 定义文章作者。 author 通过 models.ForeignKey 外键与内建的 User 模型关联在一起
|
||||
# 参数 on_delete 用于指定数据删除的方式,避免两个关联表的数据不一致。
|
||||
author = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
# 文章标题图
|
||||
avatar = models.ImageField(upload_to='article/%Y%m%d/', blank=True)
|
||||
# 文章栏目的 “一对多” 外键
|
||||
category = models.ForeignKey(
|
||||
ArticleCategory,
|
||||
null=True,
|
||||
blank=True,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='article'
|
||||
)
|
||||
# 文章标签
|
||||
tags = models.CharField(max_length=20,blank=True)
|
||||
# 文章标题。
|
||||
title = models.CharField(max_length=100,null=False,blank=False)
|
||||
# 概要
|
||||
sumary = models.CharField(max_length=200,null=False,blank=False)
|
||||
# 文章正文。
|
||||
content = models.TextField()
|
||||
# 浏览量
|
||||
total_views = models.PositiveIntegerField(default=0)
|
||||
# 文章评论数
|
||||
comments_count = models.PositiveIntegerField(default=0)
|
||||
# 文章创建时间。
|
||||
# 参数 default=timezone.now 指定其在创建数据时将默认写入当前的时间
|
||||
created = models.DateTimeField(default=timezone.now)
|
||||
# 文章更新时间。
|
||||
# 参数 auto_now=True 指定每次数据更新时自动写入当前时间
|
||||
updated = models.DateTimeField(auto_now=True)
|
||||
|
||||
# 内部类 class Meta 用于给 model 定义元数据
|
||||
class Meta:
|
||||
# ordering 指定模型返回的数据的排列顺序
|
||||
# '-created' 表明数据应该以倒序排列
|
||||
ordering = ('-created',)
|
||||
db_table='tb_article'
|
||||
verbose_name='文章管理'
|
||||
verbose_name_plural=verbose_name
|
||||
# 函数 __str__ 定义当调用对象的 str() 方法时的返回值内容
|
||||
# 它最常见的就是在Django管理后台中做为对象的显示值。因此应该总是为 __str__ 返回一个友好易读的字符串
|
||||
def __str__(self):
|
||||
# 将文章标题返回
|
||||
return self.title
|
3544
blog/logs/blog.log
3544
blog/logs/blog.log
File diff suppressed because it is too large
Load Diff
Binary file not shown.
After Width: | Height: | Size: 1.6 MiB |
|
@ -32,7 +32,7 @@
|
|||
<li class="nav-item dropdown" v-if="is_login">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" @click="show_menu_click">admin</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown" style="display: block" v-show="show_menu">
|
||||
<a class="dropdown-item" href="write_blog.html">写文章</a>
|
||||
<a class="dropdown-item" href="../templates/write_blog.html">写文章</a>
|
||||
<a class="dropdown-item" href='./center.html'>个人信息</a>
|
||||
<a class="dropdown-item" href='#'>退出登录</a>
|
||||
</div>
|
||||
|
|
|
@ -72,3 +72,26 @@
|
|||
list-style-type: none;
|
||||
font-family: 'Microsoft Yahei', '宋体', arial, 'Hiragino Sans GB', Helvetica;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.main2 {
|
||||
|
||||
position: absolute;
|
||||
left:42.4%;
|
||||
top:25.5%;
|
||||
box-shadow: 0 0 10px pink;
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
color: #fff;
|
||||
/* 圆角形成圆形 */
|
||||
border-radius: 50%;
|
||||
/* 实现顶部圆弧 */
|
||||
|
||||
border-bottom: 5px solid pink;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
/* 增加动画 */
|
||||
|
||||
}
|
|
@ -58,7 +58,7 @@
|
|||
<li class="nav-item dropdown" v-if="is_login">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" @click="show_menu_click">admin</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown" style="display: block" v-show="show_menu">
|
||||
<a class="dropdown-item" href="write_blog.html">写文章</a>
|
||||
<a class="dropdown-item" href="../templates/write_blog.html">写文章</a>
|
||||
<a class="dropdown-item" href='./center.html'>个人信息</a>
|
||||
<a class="dropdown-item" href='#'>退出登录</a>
|
||||
</div>
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 520 KiB |
|
@ -5,13 +5,14 @@ var vm = new Vue({
|
|||
data: {
|
||||
host,
|
||||
show_menu:false,
|
||||
is_login:true,
|
||||
username:''
|
||||
username:'',
|
||||
is_login:'true'
|
||||
},
|
||||
mounted(){
|
||||
this.username=getCookie('username');
|
||||
// this.is_login=getCookie('is_login');
|
||||
this.is_login=getCookie('is_login');
|
||||
this.is_login=true
|
||||
|
||||
},
|
||||
methods: {
|
||||
//显示下拉菜单
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
<li class="nav-item dropdown" v-if="is_login">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" @click="show_menu_click">admin</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown" style="display: block" v-show="show_menu">
|
||||
<a class="dropdown-item" href="write_blog.html">写文章</a>
|
||||
<a class="dropdown-item" href="../templates/write_blog.html">写文章</a>
|
||||
<a class="dropdown-item" href='./center.html'>个人信息</a>
|
||||
<a class="dropdown-item" href='#'>退出登录</a>
|
||||
</div>
|
||||
|
|
|
@ -6,15 +6,16 @@
|
|||
<meta charset="utf-8">
|
||||
<!-- 网站标题 -->
|
||||
<title>首页</title>
|
||||
|
||||
<!-- 引入bootstrap的css文件 -->
|
||||
<link rel="stylesheet" href="../static/bootstrap/css/bootstrap.min.css">
|
||||
<!-- 引入monikai.css -->
|
||||
<link rel="stylesheet" href="../static/md_css/monokai.css">
|
||||
{# <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous">#}
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous">
|
||||
<!--导入css-->
|
||||
<link rel="stylesheet" href="../static/common/common.css">
|
||||
<link rel="stylesheet" href="../static/common/zhan.css">
|
||||
{# <link rel="stylesheet" href="../static/common/jquery.pagination.css">#}
|
||||
<link rel="stylesheet" href="../static/common/jquery.pagination.css">
|
||||
<!-- 引入vuejs -->
|
||||
<script type="text/javascript" src="../static/js/vue-2.5.16.js"></script>
|
||||
<script type="text/javascript" src="../static/js/axios-0.18.0.min.js"></script>
|
||||
|
@ -26,6 +27,7 @@
|
|||
background-size: 1920px,1001.19px;
|
||||
|
||||
}
|
||||
|
||||
.loader {
|
||||
animation-name:animate;
|
||||
position: absolute;
|
||||
|
@ -75,6 +77,7 @@
|
|||
opacity: 0;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
<body>
|
||||
|
||||
|
@ -114,16 +117,17 @@
|
|||
<ul class="nav navbar-nav">
|
||||
<!-- 如果用户已经登录,则显示用户名下拉框 -->
|
||||
<li class="nav-item dropdown" v-if="is_login">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" @click="show_menu_click">admin</a>
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" @click="show_menu_click">[[username]]</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown" style="display: block" v-show="show_menu">
|
||||
<a class="dropdown-item" href="../static/write_blog.html">写文章</a>
|
||||
<a class="dropdown-item" href='../static/center.html'>个人信息</a>
|
||||
<a class="dropdown-item" href='#'>退出登录</a>
|
||||
<a class="dropdown-item" href='login/'>登录</a>
|
||||
<a class="dropdown-item" href="writeblog">写文章</a>
|
||||
|
||||
<a class="dropdown-item" href='{% url 'users:logout' %}'>退出登录</a>
|
||||
</div>
|
||||
</li>
|
||||
<!-- 如果用户未登录,则显示登录按钮 -->
|
||||
<li class="nav-item" v-else>
|
||||
<a class="nav-link" href="login.html">登录</a>
|
||||
<a class="nav-link1" href="login.html">登录</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -131,10 +135,12 @@
|
|||
|
||||
<!-- content -->
|
||||
<div class="loader">
|
||||
|
||||
</div>
|
||||
|
||||
<div class="main"
|
||||
></div>
|
||||
<div class="main2"
|
||||
></div>
|
||||
<div class="tupain"
|
||||
></div>
|
||||
|
||||
|
|
|
@ -16,11 +16,42 @@
|
|||
</head>
|
||||
<style>
|
||||
body{
|
||||
background-image:url("../static/img/bizhi.jpg") ;
|
||||
background-image:url("../static/img/33.jpg") ;
|
||||
background-size:1920px,900px;
|
||||
|
||||
}
|
||||
.login{
|
||||
|
||||
|
||||
|
||||
}
|
||||
.containe{
|
||||
position: absolute;
|
||||
left: 40%;
|
||||
top: 20%;
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
|
||||
opacity: 0.5;
|
||||
border-top: 4px solid ;
|
||||
border-bottom: 4px solid ;
|
||||
}
|
||||
.form-group{
|
||||
width: 300px;
|
||||
|
||||
font-weight: bold;
|
||||
font-size: larger;
|
||||
}
|
||||
.primaryAction btn btn-primary{
|
||||
position: absolute;
|
||||
top:40%;
|
||||
left:50%;
|
||||
|
||||
}
|
||||
.custom-control-label{
|
||||
|
||||
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div id="app">
|
||||
|
@ -37,11 +68,10 @@
|
|||
</div>
|
||||
</nav>
|
||||
<!--content-->
|
||||
<div class="container" style="height: 600px;margin-top: 20px">
|
||||
<div class="containe" >
|
||||
|
||||
|
||||
<div class="col-6">
|
||||
<form class="login" id="login_form" method="POST" style="padding-right: 200px;margin-left: -100px">
|
||||
<form class="login" id="login_form" method="POST" >
|
||||
{% csrf_token %}
|
||||
|
||||
<div class="form-group">
|
||||
|
@ -63,7 +93,7 @@
|
|||
</form>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
<!DOCTYPE html>
|
||||
<!-- 网站主语言 -->
|
||||
<html lang="zh-cn">
|
||||
|
||||
<head>
|
||||
<!-- 网站采用的字符编码 -->
|
||||
<meta charset="utf-8">
|
||||
<!-- 网站标题 -->
|
||||
<title> 写文章 </title>
|
||||
{% load staticfiles %}
|
||||
<!-- 引入bootstrap的css文件 -->
|
||||
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
|
||||
<!-- 引入monikai.css -->
|
||||
<link rel="stylesheet" href="{% static 'md_css/monokai.css' %}">
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" integrity="sha384-50oBUHEmvpQ+1lW4y57PTFmhCaXp0ML5d60M1M7uH2+nqUivzIebhndOJK28anvf" crossorigin="anonymous">
|
||||
<!-- 引入vuejs -->
|
||||
<script type="text/javascript" src="{% static 'js/vue-2.5.16.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'js/axios-0.18.0.min.js' %}"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app">
|
||||
<!-- 定义导航栏 -->
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
<div class="container">
|
||||
<!-- 导航栏商标 -->
|
||||
<div>
|
||||
<a class="navbar-brand" href="{% url 'home:index' %}">个人博客</a>
|
||||
</div>
|
||||
</div>
|
||||
<!--登录/个人中心-->
|
||||
<div class="navbar-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<!-- 如果用户已经登录,则显示用户名下拉框 -->
|
||||
<li class="nav-item dropdown" v-if="is_login">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" @click="show_menu_click">[[username]]</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown" style="display: block" v-show="show_menu">
|
||||
<a class="dropdown-item" href="{% url 'users:writeblog' %}">写文章</a>
|
||||
<a class="dropdown-item" href='{% url 'users:login' %}'>退出登录</a>
|
||||
</div>
|
||||
</li>
|
||||
<!-- 如果用户未登录,则显示登录按钮 -->
|
||||
<li class="nav-item" v-else>
|
||||
<a class="nav-link" href="{% url 'users:login' %}">登录</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- 写文章表单 -->
|
||||
<div class="container" style="margin-bottom: 20px">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<br>
|
||||
<!-- 提交文章的表单 -->
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<!-- 文章标题图 -->
|
||||
<div class="form-group">
|
||||
<label for="avatar">标题图</label>
|
||||
<input type="file" class="form-control-file" name="avatar" id="avatar" >
|
||||
</div>
|
||||
|
||||
<!-- 文章标题 -->
|
||||
<div class="form-group">
|
||||
<!-- 标签 -->
|
||||
<label for="title">文章标题</label>
|
||||
<!-- 文本框 -->
|
||||
<input type="text" class="form-control" id="title" name="title">
|
||||
</div>
|
||||
|
||||
<!-- 文章栏目 -->
|
||||
<div class="form-group">
|
||||
<label for="category">栏目</label>
|
||||
<select class="form-control col-3" id="category" name="category">
|
||||
{% for category in categories %}
|
||||
<option value="{{ category.id }}">{{ category.title }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- 文章标签 -->
|
||||
<div class="form-group">
|
||||
<!-- 标签 -->
|
||||
<label for="tags">标签</label>
|
||||
<!-- 文本框 -->
|
||||
<input type="text" class="form-control col-3" id="tags" name="tags" >
|
||||
</div>
|
||||
<!-- 文章摘要 -->
|
||||
<div class="form-group">
|
||||
<!-- 标签 -->
|
||||
<label for="sumary">文章摘要</label>
|
||||
<!-- 文本框 -->
|
||||
<input type="text" class="form-control" id="sumary" name="sumary">
|
||||
</div>
|
||||
<!-- 文章正文 -->
|
||||
<div class="form-group">
|
||||
<label for="body">文章正文</label>
|
||||
<!-- 文本区域 -->
|
||||
<!--<textarea type="text" class="form-control" id="body" name="body" rows="12"></textarea>-->
|
||||
<textarea cols="40" id="id_body" name="content" rows="10" required data-processed="0" :data-config="data_config" data-external-plugin-resources="[]" data-id="id_body" data-type="ckeditortype">
|
||||
</textarea>
|
||||
</div>
|
||||
<!-- 提交按钮 -->
|
||||
<button type="submit" class="btn btn-primary">完成</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="py-3 bg-dark" id="footer">
|
||||
<div class="container">
|
||||
<h5 class="m-0 text-center text-white">Copyright @ qiruihua</h5>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
<!--ckeditor-->
|
||||
<script type="text/javascript" src="{% static 'ckeditor/ckeditor-init.js' %}" data-ckeditor-basepath="{% static 'ckeditor/ckeditor/' %}" id="ckeditor-init-script"></script>
|
||||
<script type="text/javascript" src="{% static 'ckeditor/ckeditor/ckeditor.js' %}"></script>
|
||||
<!-- 引入js -->
|
||||
<script type="text/javascript" src="{% static 'js/host.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'js/common.js' %}"></script>
|
||||
<script type="text/javascript" src="{% static 'js/write_blog.js' %}"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -2,6 +2,8 @@
|
|||
from django.urls import path
|
||||
from users.views import RegisterView
|
||||
from users.views import LoginView
|
||||
from users.views import LogoutView
|
||||
from users.views import WriteBlogView
|
||||
|
||||
urlpatterns = [
|
||||
# 参数1:路由
|
||||
|
@ -9,5 +11,7 @@ urlpatterns = [
|
|||
# 参数3:路由名,方便通过reverse来获取路由
|
||||
path('register/',RegisterView.as_view(),name='register'),
|
||||
path('login/',LoginView.as_view(),name='login'),
|
||||
path('logout/',LogoutView.as_view(),name='logout'),
|
||||
path('writeblog/', WriteBlogView.as_view(), name='writeblog'),
|
||||
|
||||
]
|
|
@ -1,3 +1,4 @@
|
|||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.http import HttpResponseBadRequest, HttpResponse,HttpResponseRedirect
|
||||
from django.shortcuts import render, redirect
|
||||
from django.contrib.auth import login
|
||||
|
@ -69,26 +70,13 @@ class LoginView(View):
|
|||
|
||||
# 认证登录用户
|
||||
# 认证字段已经在User模型中的USERNAME_FIELD = 'mobile'修改
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#
|
||||
user = authenticate(mobile=mobile, password=password)
|
||||
|
||||
# 返回响应
|
||||
|
||||
if user is None:
|
||||
return HttpResponseBadRequest('用户名或密码错误')
|
||||
|
||||
response = redirect(reverse('home:index'))
|
||||
|
||||
|
||||
# 实现状态保持
|
||||
|
||||
# 响应登录结果
|
||||
|
||||
# 设置状态保持的周期
|
||||
if remember != 'on':
|
||||
# 没有记住用户:浏览器会话结束就过期
|
||||
|
@ -107,11 +95,79 @@ class LoginView(View):
|
|||
|
||||
|
||||
|
||||
# 设置状态保持的周期
|
||||
|
||||
# 记住用户:None表示两周后过期
|
||||
|
||||
return HttpResponseRedirect('/')
|
||||
|
||||
|
||||
|
||||
|
||||
from django.contrib.auth import logout
|
||||
class LogoutView(View):
|
||||
|
||||
def get(self,request):
|
||||
# 清理session
|
||||
logout(request)
|
||||
# 退出登录,重定向到登录页
|
||||
response = redirect(reverse('home:index'))
|
||||
# 退出登录时清除cookie中的登录状态
|
||||
response.delete_cookie('is_login')
|
||||
response.delete_cookie('username')
|
||||
|
||||
return response
|
||||
|
||||
class WriteBlogView(View):
|
||||
|
||||
def get(self,request):
|
||||
|
||||
return render(request,'write_blog.html')
|
||||
from home.models import ArticleCategory,Article
|
||||
import logging
|
||||
#创建获取日志器
|
||||
logger=logging.getLogger('django')
|
||||
class WriteBlogView(LoginRequiredMixin,View):
|
||||
|
||||
def get(self,request):
|
||||
# 获取博客分类信息
|
||||
categories = ArticleCategory.objects.all()
|
||||
|
||||
context = {
|
||||
'categories': categories
|
||||
}
|
||||
return render(request,'write_blog.html',context=context)
|
||||
|
||||
def post(self, request):
|
||||
# 接收数据
|
||||
avatar = request.FILES.get('avatar')
|
||||
title = request.POST.get('title')
|
||||
category_id = request.POST.get('category')
|
||||
tags = request.POST.get('tags')
|
||||
sumary = request.POST.get('sumary')
|
||||
content = request.POST.get('content')
|
||||
user = request.user
|
||||
|
||||
# 验证数据是否齐全
|
||||
if not all([avatar, title, category_id, sumary, content]):
|
||||
return HttpResponseBadRequest('参数不全')
|
||||
|
||||
# 判断文章分类id数据是否正确
|
||||
try:
|
||||
article_category = ArticleCategory.objects.get(id=category_id)
|
||||
except ArticleCategory.DoesNotExist:
|
||||
return HttpResponseBadRequest('没有此分类信息')
|
||||
|
||||
# 保存到数据库
|
||||
try:
|
||||
article = Article.objects.create(
|
||||
author=user,
|
||||
avatar=avatar,
|
||||
category=article_category,
|
||||
tags=tags,
|
||||
title=title,
|
||||
sumary=sumary,
|
||||
content=content
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
return HttpResponseBadRequest('发布失败,请稍后再试')
|
||||
|
||||
# 返回响应,跳转到文章详情页面
|
||||
# 暂时先跳转到首页
|
||||
return redirect(reverse('home:index'))
|
Loading…
Reference in New Issue