前面我们先分析了一下,做这个项目需要的几张表,今天我们从配置文件开始一步一步去解释这么的原因

首先先来看setting.py文件:

"""Django settings for mybbs project.
Generated by 'django-admin startproject' using Django 1.11.11.
For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/"""
importos#Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))#Quick-start development settings - unsuitable for production#See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
#SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'b)f=d-08hdi_w_z1^=5e9oom9#+h1a*jk-y#u!-vt$rj%5y&aj'
#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','myapp.apps.MyappConfig','debug_toolbar'# 具体详情参考这里
]
MIDDLEWARE=['django.middleware.security.SecurityMiddleware','django.contrib.sessions.middleware.SessionMiddleware','debug_toolbar.middleware.DebugToolbarMiddleware','django.middleware.common.CommonMiddleware','django.middleware.csrf.CsrfViewMiddleware','django.contrib.auth.middleware.AuthenticationMiddleware','django.contrib.messages.middleware.MessageMiddleware','django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF= 'mybbs.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= 'mybbs.wsgi.application'
#Database#https://docs.djangoproject.com/en/1.11/ref/settings/#databases
#DATABASES = {#'default': {#'ENGINE': 'django.db.backends.sqlite3',#'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),#}#}
DATABASES={'default':{'ENGINE':'django.db.backends.mysql', #数据库的配置'NAME':'duoduo','USER':'root','PASSWORD':'123','HOST':'127.0.0.1','PORT':3306,
}
}#Password validation#https://docs.djangoproject.com/en/1.11/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',
},
]#Internationalization#https://docs.djangoproject.com/en/1.11/topics/i18n/
LANGUAGE_CODE= 'en-us'TIME_ZONE= 'UTC'USE_I18N=True
USE_L10N=True
USE_TZ= False #本机的时间,不用考虑时区的问题
#Static files (CSS, JavaScript, Images)#https://docs.djangoproject.com/en/1.11/howto/static-files/
STATIC_URL= '/static/'STATICFILES_DIRS=[
os.path.join(BASE_DIR,'static')
]#指定一下认证使用 自定义的UserInfo表
AUTH_USER_MODEL='myapp.UserInfo'
#用户上传的文件配置项
MEDIA_URL='/media/'MEDIA_ROOT=os.path.join(BASE_DIR,'media')#日志配置 Google浏览器jQuery 的URL在国内不支持
DEBUG_TOOLBAR_CONFIG ={'JQUERY_URL':'//cdn.bootcss.com/jquery/2.2.4/jquery.min.js',
}#设置为空,就用项目中的jQuery
BASE_LOG_DIR= os.path.join(BASE_DIR, "log")
LOGGING={'version': 1,#禁用已经存在的logger实例
'disable_existing_loggers': False,#定义日志 格式化的 工具
'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时才在屏幕打印日志
'class': 'logging.StreamHandler','formatter': 'simple'},'default': {'level': 'INFO','class': 'logging.handlers.RotatingFileHandler', #保存到文件,自动切
'filename': os.path.join(BASE_LOG_DIR, "info.log"), #日志文件
'maxBytes': 1024 * 1024 * 50, #日志大小 50M
'backupCount': 3,'formatter': 'standard','encoding': 'utf-8',
},'error': {'level': 'ERROR','class': 'logging.handlers.RotatingFileHandler', #保存到文件,自动切
'filename': os.path.join(BASE_LOG_DIR, "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, "xxx_collect.log"),'maxBytes': 1024 * 1024 * 50, #日志大小 50M
'backupCount': 5,'formatter': 'collect','encoding': "utf-8"}
},#logger实例
'loggers': {#默认的logger应用如下配置
'': {'handlers': ['default', 'console', 'error'], #上线之后可以把'console'移除
'level': 'DEBUG','propagate': True,
},#名为 'collect'的logger还单独处理
'collect': {'handlers': ['console', 'collect'],'level': 'INFO',
}
},
}
INTERNAL_IPS= ['127.0.0.1', ]
就是验证登陆和注册forms表单数据的合法性
from django importformsfrom django.core.exceptions importValidationErrorfrom django.core.validators importRegexValidatorfrom myapp importmodels#登陆的用户名
classLoginForm(forms.Form):
username=forms.CharField(
label='用户名',
min_length=3,
max_length=12,
error_messages={'required':'用户名不能为空','min_length':'用户名最短3位','max_length':'用户名最长12位',
},
widget=forms.widgets.TextInput(
attrs={'class':'form-control'}
)
)
password=forms.CharField(
label='密码',
min_length=4,
max_length=12,
error_messages={'required':'密码不能为空','min_length':'密码最短3位','max_length':'密码最长12位',
},
widget=forms.widgets.PasswordInput(
attrs={'class':'form-control'}
)
)#注册的form
classRegForm(forms.Form):
username=forms.CharField(
label='用户名',
min_length=3,
max_length=12,
error_messages={'required':'用户名不能为空!','min_length':'用户名最短3位','max_length':'用户名最长12位',
},
widget=forms.widgets.TextInput(
attrs={'class':'form-control'}
),
)
password=forms.CharField(
label='密码',
min_length=4,
max_length=12,
error_messages={'required':'密码不能为空!','min_length':'密码最短4位','max_length':'密码最长12位',
},
widget=forms.widgets.PasswordInput(
attrs={'class':'form-control'}
)
)
re_password=forms.CharField(
label="确认密码",
min_length=4,
max_length=12,
error_messages={"required": "确认密码不能为空!","min_length": "密码最短4位","max_length": "密码最长12位"},
widget=forms.widgets.PasswordInput(attrs={"class": "form-control"})
)
phone=forms.CharField(
label="手机",
min_length=11,
max_length=11,
validators=[
RegexValidator(r'^\d{11}$', "手机号必须是数字"),
RegexValidator(r'^1[356789][0-9]{9}$', "手机号码格式不正确")
],
error_messages={"required": "手机不能为空!","min_length": "手机号码11位","max_length": "手机号码11位"},
widget=forms.widgets.TextInput(attrs={"class": "form-control"})
)#局部钩子
defclean_username(self):
value= self.cleaned_data.get("username", "")if "xxx" invalue:raise ValidationError("不符合社会主义核心价值观!")elif models.UserInfo.objects.filter(username=value):raise ValidationError("用户名已存在!")else:returnvalue#全局钩子
defclean(self):
pwd= self.cleaned_data.get("password", "")
re_pwd= self.cleaned_data.get("re_password", "")if re_pwd and pwd ==re_pwd:returnself.cleaned_dataelse:
err_msg= "两次输入的密码不一致"self.add_error("re_password", err_msg)raise ValidationError(err_msg)
把表格注册到admin中
from django.contrib importadminfrom myapp importmodels#Register your models here.
admin.site.register(models.Article)
admin.site.register(models.UserInfo)
admin.site.register(models.ArticleDetail)
admin.site.register(models.Blog)
admin.site.register(models.Category)
admin.site.register(models.Tag)
admin.site.register(models.Comment)
admin.site.register(models.ArticleUpDown)
admin.site.register(models.Article2Tag)
文件的结构:

我们先从注册功能开始说起:
1.html
form_obj.字段    ------》生产html代码
2.views.py
form_obj=forms.RegForm(request.POST)
form_obj.is_valid() ------->返回布尔值
1.如果返回Trun,就能拿到校验后的数据
form_obj.cleaned_data

3.看源码分析得到钩子函数

1.局部钩子

def clean_字段名():

1.return value

2.raise ValidationError('错误信息')

2.全局钩子

def clean():

1.return self.cleaned_data

2.raise ValidationError('错误信息')

1、注册的form类

2、上传文件

1.表单上传

form标签两个属性
1.method='post'
2.enctype='multipart/form-data'
2.AJAX上传

1.创建一个FormData对象,使用对象的append()方法填充数据

2.AJAX需要设置两个参数
1.processData:false
2.contentTyoe:false
3.Django关于上传文件的几个配置
1.上传文件存在哪儿?
1.settings.py中 配置MEDIA_ROOT=os.path.join(BASE_DIR,'media')
2.我用户怎么访问我上传的文件
1.settings.py中配置 MEDIA_URL='/media/
2.在urls.py中 配置 media开头的访问请求交给谁来处理'
url(r'^media/(?P.*)$', serve, {"document_root": settings.MEDIA_ROOT})

4.浏览器图片预览

1.FileReader对象

from django.shortcuts importrender, HttpResponse, redirectfrom myapp importforms, modelsfrom django.contrib importauthfrom django.http importJsonResponseimportlogging#生成一个以当前文件名命名的logger实例
logger = logging.getLogger(__name__)#生成一个名为collect的logger实例
collect_logger = logging.getLogger("collect")defreg(request):
logger.info("又来了,小伙子!")
collect_logger.info("多多来洗脚!")if request.method == "POST":
ret= {"code": 0}
form_obj=forms.RegForm(request.POST)
logger.debug(request.FILES)ifform_obj.is_valid():#数据经过校验,没问题
logger.debug(form_obj.cleaned_data)
avatar_obj= request.FILES.get("avatar")#创建用户
form_obj.cleaned_data.pop("re_password", "")
models.UserInfo.objects.create_user(
avatar=avatar_obj,**form_obj.cleaned_data #这个骚操作大家还记得?
)
ret["data"] = "/login/"
else:#数据没有经过校验,有问题
ret["code"] = 1ret["data"] =form_obj.errorsreturnJsonResponse(ret)
form_obj=forms.RegForm()return render(request, "reg.html", {"form_obj": form_obj})
reg.html文件的代码
欢迎注册 
 
}#show-avatar{width:80px;height:80px;
}
{{ form_obj.username.label }}
{{ form_obj.username }}