settings页面设置mysql
import os BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) SECRET_KEY = '%^klc2c5$z033pu(pbydgk$+=58w7j2$!1@5ff(z(y2jg^s+9a' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01.apps.App01Config', # 你的项目应用位置位置,版本问题有的没加你直接加上你的应用名称便可 ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', # 安全组件 你在后面的提交中必须使用csrf_token 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', # 这里存放你本身的中间件 ] ROOT_URLCONF = 'BBS.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], # 版本问题有可能须要手动配置 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 'BBS.wsgi.application' # Database # https://docs.djangoproject.com/en/2.0/ref/settings/#databases # 使用mysql的配置 不改默认的直接使用sqlite DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'blog_ebola', # 数据库名称 'USER': 'ebola', # 用户名 'PASSWORD': '2017@ebolaer', # 密码 'POST': 3306, # 端口 'HOST': '140.143.228.216' } } # Password validation # https://docs.djangoproject.com/en/2.0/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True # 在博客园的按时间分类中没法解决把他改成false就能够 # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/2.0/howto/static-files/ STATIC_URL = '/static/' #不配置static路径了由于static文件夹放在了app中不须要配置 AUTH_USER_MODEL = "app01.UserInfo" # 主要是配合模块不使用本身建立的user数据表 # logging模块 BASE_LOG_DIR = os.path.join(BASE_DIR, 'log') # 建立一个log文件夹,配置路径 LOGGING = { 'version': 1, # 系统与预留字 'disable_existing_loggers': False, # 禁用django模块中已经存在的log实例 # 格式化输出 'formatters': { 'standard': { 'format': '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' '[%(levelname)s][%(message)s]' }, 'simple': { 'format': '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s' }, 'collect': { 'format': '%(message)s' } }, # 过滤器 'filters': { 'require_debug_true': { '()': 'django.utils.log.RequireDebugTrue', }, }, # 处理器 'handlers': { 'console': { 'level': 'DEBUG', 'filters': ['require_debug_true'], # 只有在Django debug为True时才在屏幕打印日志 ,通常上线会把级别调高或者改成flase 这样就很好地避免了一行行删代码 'class': 'logging.StreamHandler', # 这个是在屏幕显示 'formatter': 'simple' # 按照上面配置的simple方法进行输出 }, 'default': { 'level': 'INFO', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切 'filename': os.path.join(BASE_LOG_DIR, "bbs_info.log"), # 日志文件 'maxBytes': 1024 * 1024 * 50, # 日志大小 50M 'backupCount': 3, # 最大备份数量 'formatter': 'standard', # 格式化输出,按照standard方式(在上面配置的格式)输出 'encoding': 'utf-8', # 编码方式若是不指定就是系统环境编码 千万注意你永远不知道那帮运维会搞出什么编码方式!!!! }, 'error': { 'level': 'ERROR', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切 'filename': os.path.join(BASE_LOG_DIR, "bbs_err.log"), # 日志文件 'maxBytes': 1024 * 1024 * 50, # 日志大小 50M 'backupCount': 5, 'formatter': 'standard', 'encoding': 'utf-8', }, 'collect': { 'level': 'INFO', 'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切 'filename': os.path.join(BASE_LOG_DIR, "bbs_collect.log"), 'maxBytes': 1024 * 1024 * 50, # 日志大小 50M 'backupCount': 5, 'formatter': 'collect', 'encoding': "utf-8" } }, 'loggers': { # 默认的logger应用以下配置 '': { 'handlers': ['default', 'console', 'error'], # 上线以后能够把'console'移除,若是一处列表中的console那么就不会显示 只显示列表中有的级别 'level': 'DEBUG', 'propagate': True, }, # 名为 'collect'的logger还单独处理,这个的存在主要做用于用户我的数据、浏览器习惯等收集 'collect': { 'handlers': ['console', 'collect'], 'level': 'INFO', }, # 查看sql中的执行语句 'django.db.backends': { 'handlers': ['console'], 'level': 'INFO', }, }, } # MEDIA配置 对外开放接口 MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'app01', 'media')
①开放图片访问的借口media url中配置sql
②不使用auth中默认的user表而是用本身userinfo表 数据库
urls中配置的图片开放接口以及分级路由django
from django.contrib import admin from django.conf.urls import url,include from app01.views import * # 如下为开放头像借口 from django.views.static import serve from BBS import settings from app01.urls import * urlpatterns = [ url('admin/', admin.site.urls), # 注销\登陆\修改密码\注册 url(r'^login/', Login.as_view(), name='login'), url(r'^loginout/', LoginOut.as_view(), name='loginout'), url(r'^reg/', Reg.as_view(), name='reg'), # 主页 url(r'^index/', Index.as_view(), name='index'), # 我的站点 url(r'blog/', include("app01.urls")), # 头像接口、验证码图片 url(r'^media/(?P<path>.*)$',serve,{'document_root':settings.MEDIA_ROOT}), url(r'^get_valid_img/', GetValidImg.as_view(), name='get_valid_img'), # url(r'background/(?P<username>\w+)/(?P<cate>\w+)', BackGround.as_view()), url(r'background/article/(?P<func>\w+)/(?P<article_id>\d*)',BackGround.as_view()), ]
models模块表关系浏览器
from django.contrib.auth.models import AbstractUser from django.db import models class UserInfo(AbstractUser): """ 用户信息 """ nid = models.AutoField(primary_key=True) telephone = models.CharField(max_length=11, null=True, unique=True) avatar = models.FileField(upload_to='avatars/', default="/avatars/default.png") create_time = models.DateTimeField(verbose_name='建立时间', auto_now_add=True) blog = models.OneToOneField(to='Blog', to_field='nid', null=True) def __str__(self): return self.username class Blog(models.Model): """ 博客信息 """ nid = models.AutoField(primary_key=True) title = models.CharField(verbose_name='我的博客标题', max_length=64) site = models.CharField(verbose_name='我的博客后缀', max_length=32, unique=True) theme = models.CharField(verbose_name='博客主题', max_length=32) def __str__(self): return self.title 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') def __str__(self): return self.title 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') def __str__(self): return self.title class Article(models.Model): nid = models.AutoField(primary_key=True) title = models.CharField(max_length=50, verbose_name='文章标题') desc = models.CharField(max_length=255, verbose_name='文章描述') create_time = models.DateTimeField(verbose_name='建立时间', auto_now_add=True) category = models.ForeignKey(to='Category', to_field='nid', null=True) user = models.ForeignKey(verbose_name='做者', to='UserInfo', to_field='nid') comment_count = models.IntegerField(default=0) up_count = models.IntegerField(default=0) down_count = models.IntegerField(default=0) tags = models.ManyToManyField( to="Tag", through='Article2Tag', through_fields=('article', 'tag'), ) def __str__(self): return self.title class ArticleDetail(models.Model): """ 文章详细表 """ nid = models.AutoField(primary_key=True) content = models.TextField() article = models.OneToOneField(to='Article', to_field='nid') class Article2Tag(models.Model): nid = models.AutoField(primary_key=True) article = models.ForeignKey(verbose_name='文章', to="Article", to_field='nid') tag = models.ForeignKey(verbose_name='标签', to="Tag", to_field='nid') class Meta: unique_together = [ ('article', 'tag'), ] def __str__(self): v = self.article.title + "--" + self.tag.title return v class ArticleUpDown(models.Model): """ 点赞表 """ nid = models.AutoField(primary_key=True) user = models.ForeignKey('UserInfo', null=True) article = models.ForeignKey("Article", null=True) is_up = models.BooleanField(default=True) class Meta: unique_together = [ ('article', 'user'), ] class Comment(models.Model): """ 评论表 """ nid = models.AutoField(primary_key=True) article = models.ForeignKey(verbose_name='评论文章', to='Article', to_field='nid') user = models.ForeignKey(verbose_name='评论者', to='UserInfo', to_field='nid') content = models.CharField(verbose_name='评论内容', max_length=255) create_time = models.DateTimeField(verbose_name='建立时间', auto_now_add=True) parent_comment = models.ForeignKey('self', null=True) def __str__(self): return self.content
①中间的models.FileField字段,里面存放图片avatar = models.FileField(upload_to='avatars/', default="/avatars/default.png") 安全
一、登陆页面网络
全屏背景设置样式session
body { background-image: url(http://imgcdn.ph.126.net/UQhSl0NAkp9wsn0keF-rLA==/3084402794814350820.jpg); #这里能够放网络地址也能够放本地图片 直接存放本地路径也能够不加冒号 background-position: center; background-repeat: no-repeat; background-attachment: fixed; }
auth验证app
验证码生成及验证运维
二、注册页面
滑动模块应用
三、登陆装饰器
next跳转问题
装饰器函数问题