博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python大神 - Django(基础知识)--构建项目的思路
阅读量:5154 次
发布时间:2019-06-13

本文共 23047 字,大约阅读时间需要 76 分钟。

一、Django的优势

Python的WEB框架有Django、Tornado、Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM、模型绑定、模板引擎、缓存、Session等诸多功能

二、DJango项目的创建

  1)命令行

django-admin startproject sitename  # 建项目  python manage.py runserver 0.0.0.0  # 启动服务  python manage.py startapp appname    # 创建app  python manage.py syncdb                # 建表是的编码是utf8(后面的版本取消)   python manage.py makemigrations        # 连接库  python manage.py migrate            # 建表  python manage.py createsuperuser    # 创建admin用户

  2)pycharm

三、Django的目录结构

1)同项目名称一样的目录,是做全局变量的:setting(配置文件,路径配置等),urls(路由系统),wsgi(socket)2)app文件:app,models,views,admin,tests3)templates(存放html文件)4)manage(进入Django命令行模式)以下是自定义:log(存放日志),media(存放视频,照片),static(存放js,css,静态图片..)

四、连接数据库

注:新建的数据库要指定utf8格式,否则在建表时(有中文输入)会出现乱码

步骤:setting配置数据库,连接数据库,建表

  1、setting配置DATABASES

DATABASES = {            'default': {            'ENGINE': 'django.db.backends.mysql',            'NAME':'dbname',            'USER': 'root',            'PASSWORD': 'xxx',            'HOST': '',            'PORT': '',            }        }
定义

  2、由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替

1         # 如下设置放置的与project同名的配置的 __init__.py文件中2             import pymysql3             pymysql.install_as_MySQLdb()

  3、在setting配置模版文件路径(把html存放在templates)--默认已配置好

TEMPLATE_DIRS = (

os.path.join(BASE_DIR,'templates'),
)

  4、在setting配置静态文件路径(把css,js存放在statics)

注:在生产环境下(DEBUG=False),该配置失效

STATICFILES_DIRS = (        os.path.join(BASE_DIR,'static'),        )        注:在html里应用静态文件,建议使用模板语言        1)在html开头添加        {
% load staticfiles %} 2)应用静态文件 {
% static 'css/reset.css' %}

  5、当涉及到文件上传时,在setting配置

 

注:涉及到文件上传的upload# 配置上传文件的路径=========================================MEDIA_URL = '/media/'MEDIA_ROOT = os.path.join(BASE_DIR,"media")=========================================

2)url配置

==================================================================
旧版本:
from django.views.static import serve # 前端显示出图片内容,旧版本
from TFF.settings import MEDIA_ROOT
# url(r'^madia/(?P<path>.*)$', serve,{"document_root":MEDIA_ROOT}), # 旧版本
==================================================================
# 新版本
from django.conf.urls.static import static
from TFF import settings
urlpatterns = [
]+static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT) # 在url配置的尾部加

 

=======================================以上是DJango项目的前期工作========================================================

 

一、数据库的设计(ORM):

思路:分层设计,如下例子

根据app设计(分层设计)    uers-用户管理    Course-课程管理    organization-机构和教师管理        以上的3个app在同一层           operation-用户操作管理 (最上层)

1)给每个app的model文件里,建表(关系对象映射):

  一般用户表,都需要继承Django原本的auth表

1)可以继承默认生成的user表            from django.contrib.auth.models import AbstractUser                        class Userprofile(AbstractUser):                nick_name = models.CharField(max_length=32,verbose_name=u"昵称",default=u"")                birthday = models.DataField(verbose_name=u"生日",null=True,blank=True)                gender = models.CharField(choices=(("male",u"男"),("female",u"女")),default=u"")                address = models.CharField(max_length=128,default=u"")                mobile = models.CharField(max_length=11,null=True,blank=True)                image = models.ImageField(upload_to="image/%Y/%m",default=u"image/default.png",max_length=128)                                class Meta:                    verbose_name = "用户信息"                    verbose_name_plural = verbose_name                                    def __unicode__(self):   # 定义返回utf8(中文)                     return self.username                                注:                 a)在setting中增加字段                 AUTH_USER_MODEL = "users.Userprofile"   # users为app的名,Userprofile为数据表的名                                b)下面为一些AbstractBaseUser的子类必须定义的关键的字段和方法: # 否则会报错:type object 'UserProfile' has no attribute 'USERNAME_FIELD'                USERNAME_FIELD                必须设置。 设置认证标识,设置成标识的字段 unique=True                class MyUser(AbstractBaseUser):                    identifier = models.CharField(max_length=40, unique=True)                    ...                    USERNAME_FIELD = 'identifier'                c)                用户重写: http://www.jianshu.com/p/b993f4feff83
User表

  又如给Course建表:

1 class Course(models.Model): 2  3     name = models.CharField(max_length=64,verbose_name=u'课程名称') 4     org_name = models.ForeignKey(CourseOrg,verbose_name=u'所属机构',null=True,blank=True) 5     teacher = models.ForeignKey(Teacher,verbose_name=u'课程教师',null=True,blank=True) 6     desc = models.CharField(max_length=256,verbose_name=u'课程描述') 7     is_Adware = models.BooleanField(default=False,verbose_name=u'是否广告') 8     detail = models.TextField(verbose_name=u'课程详情') 9     course_type = models.CharField(verbose_name=u'课程类型',default='',max_length=50)10     degree = models.IntegerField(default=1,choices=((1,'初级'),(2,'中级'),(3,'高级')),verbose_name=u'课程级别')11     learn_times = models.IntegerField(default=0,verbose_name=u'学习时长')12     students = models.IntegerField(default=0,verbose_name=u'学习人数')13     fav_nums = models.IntegerField(default=0,verbose_name=u'收藏人数')14     image = models.ImageField(upload_to='course/%Y/%m',default='course/default.png',max_length=256,verbose_name=u'课程图片')15     click_num = models.IntegerField(default=0,verbose_name=u'点击人数')16     add_time = models.DateTimeField(default=datetime.now,verbose_name=u'添加时间')17     teacher_tellyour = models.CharField(default='',verbose_name=u'老师的讲话',max_length=300)18     work = models.CharField(default='',verbose_name=u'职业',max_length=64)
例子

2)在setting中增加字段 

  在INSTALLED_APPS列表里加载app

3)给app建好需求的表时:

运行命令:

python manage.py makemigrations        # 连接库 python manage.py migrate # 建表

附:(重点注意)

附:1、如果解决数据库输入中文乱码的问题        1)创建数据库时        create database test default charset=utf8;        2)在Django创建数据表示用:        python manager.py syncdb # 3.0版本后就没有了            2、每生成一个数据表        1)在app目录下的migrations目录会生成对应一个记录文件        2)在数据库中的auth_migration表里也会生成一条对应的数据记录            3、verbose_name 是后台管理显示的名字           4、def __unicode__(self):            return self.name 是后台管理显示创建每条数据的名称        注:上面是Python2.0的版本        3.0版本是        def __str__(self):            5、注:涉及到文件上传的upload        # 配置上传文件的路径        =========================================        MEDIA_URL = '/media/'        MEDIA_ROOT = os.path.join(BASE_DIR,"media")        =========================================

二、后台管理(Django admin和xadmin)---一般用xadmin,功能更强大,智能的管理系统

特点:    权限管理    少前端样式    快速开发    1、设置网站为中文显示(zh-hans,Asia/Shanghai,USE_TZ=False) # USE_TZ管理写入数据库的时区时间2、管理user用户表    1)设置app的admin.py    =================================================    from .models import UserProfile    class UserProfileAdmin(admin.ModelAdmin):        pass    admin.site.register(UserProfile,UserProfileAdmin)    =================================================另外一个后台管理构架--xadmin1、安装     1)pip install xadmin    2)源码安装(推荐使用),用GitHub        依赖包:pip3 install future;pip3 install django-crispy_forms;            3)在setting中的applist加上         'xadmin',         'crispy_forms',             4) 修改url,把admin ==> xadmin    5) 生成xadmin数据表    2、xadmin用法--app的model注册    1)在每个app文件夹里新建py文件:adminx.py    2)        import xadmin        from .models import UserProfile,EmailVerifyRecord,Banner        class EmailVerifyRecordAdmin(object):            list_display = ['email','code','send_type','send_time']  # 展示出来的列            search_fields = ['email','code','send_type']             # 搜索栏            list_filter = ['email','code','send_type','send_time']   # 过滤器            ordering = ['-click_nums']                                 # 排序            readonly_fields = ['fav_nums']                              # 设置只读            exclude = ['click_nums']                                 # 不可见,与readonly_fields有冲突,同一列数据不可同时存在这两个字段里                                    xadmin.site.register(EmailVerifyRecord,EmailVerifyRecordAdmin) # 与admin关联            3)注:        当有外键时:            list_filter = ['user__username','fav_id','fav_type','add_time'] # 过滤器有所变量,用双下划线            3、xadmin后台管理页面设置(在user的app设置)    1)主题设置        ==============================================        from xadmin import views                class BaseSetting(object):            enable_themes = True    # 显示主题            use_bootswatch = True   # 能使用那些主题                    xadmin.site.register(views.BaseAdminView,BaseSetting)        ==============================================                2)网站标题和页尾标题、model显示样式        ==============================================        from xadmin import views                class GlobalSetting(object):            site_title = "腾飞后台管理系统"            site_footer = "腾飞学习网"            menu_style = "accordion"                    xadmin.site.register(views.CommAdminView,GlobalSetting)        ==============================================            3)model显示的app名,如何改为中文名        a. 在apps.py修改            在类中增加 verbose_name = u"用户操作"        b. 在__init__.py 文件增加            default_app_config = "users.apps.Usersconfig"  # Usersconfig :类名 + config
管理系统相关的配置

三、每个html页面与一个view的类一一对应

注:

要用“return HttpResponseRedirect(reverse("index"))”而不用“return render(request,"index.html",{})”    原因是:第一种:除了跳转到页面,还会执行“页面对应view方法”,而render不会执行view方法

如:登录与注册的页面设置

一、登录    1、网站主页        1)把index.html 放入templates里        2)新建静态文件/static,把css、images、img、js、media放入其内        3)设置setting中的静态文件路径        4)编写url            ==================================================            from django.views.generic import TemplateView            url(r'^$',TemplateView.as_view(template_name="index.html"),name="index"),            ==================================================                2、登录页面        1)把login.html 放入templates里        2)编写user的app中的views文件(写函数)-- 一般是以类的方式写            ==================================================            类:            from django.contrib.auth import authenticate,login # 用户验证函数            from django.views.generic.base import View         # 编写类时,一定要继承该类            class UserLogin(View):                def get(self,request):                    return render(request, "login.html", {})                def post(self,request):                    user_name = request.POST.get("username",None)                    user_pwd = request.POST.get("password",None)                    result = authenticate(username=user_name,password=user_pwd) # 使字段request.user.is_authenticated变成True                    if result:                        login(request,result)  # 把result写入request                        return render(request,"index.html",{
"username":result.username}) # result为user该条数据 else: return render(request,"login.html",{
"meg":"用户名或密码错误"}) ============================================================ 函数: from django.contrib.auth import authenticate,login # 用户验证函数;login是生成session def UserLogin(request): if request.method == "POST": user_name = request.POST.get("username",None) user_pwd = request.POST.get("password",None) result = authenticate(username=user_name,password=user_pwd) # 使字段request.user.is_authenticated变成True if result: login(request,result) # 把result写入request return render(request,"index.html",{
"username":result.username}) else: return render(request,"login.html",{}) elif request.method == "GET": return render(request, "login.html", {}) ============================================================ 注:POST要大写;两个内置用户验证函数authenticate,login 3)编写验证成功后跳转页面的设置(数据交互) {
% if request.user.is_authenticated %} # 验证成功后,request.user.is_authenticated为True 4)url url(r'^login/',user_views.UserLogin.as_view(),name="userlogin") # 类的写法,多了as_view() url(r'^login/',user_views.UserLogin,name="userlogin") # 函数的写法 3、自定义authenticate类,用户验证(原来只支持用户名登录,不支持邮箱登录) 1)在app中views文件里重写authenticate ============================================================ from django.contrib.auth.backends import ModelBackend # 重写时一定要继承这个类 from django.db.models import Q # 逻辑and,or class UserBackend(ModelBackend): def authenticate(self, request, username=None, password=None, **kwargs): try: user = UserProfile.objects.get(Q(username=username)|Q(email=username)) # 或的写法,and的写用逗号隔开 if user.check_password(password): # 检查密码是否正确 return user except Exception as e: return None ============================================================ 2)在setting中加入 AUTHENTICATION_BACKENDS = ( "user.views.UserBackend", ) 4、后台的Form验证(有两种方法) 1)在app下新建form.py,内容如下 ========================================================= 方法一:自定义 from django import forms class LoginForm(forms.Form): username = forms.CharField(required=True) # username必须与form表单里定义的name一致 password = forms.CharField(required=True,min_length=8) # password必须与form表单里定义的name一致 注:重新定义错误信息: error_messages={
'required':u"密码不能为空",'invalid':u"密码最少8位数"} 方法二:引用自带的(推荐使用,与model结合) class UserAskForm(forms.ModelForm): class Meta: model = UserAsk fields = ['name','mobile','course_name'] def clean_mobile(self): mobile = self.cleaned_data['mobile'] mobile_model = "^1[358]\d{9}$|^147\d{8}$|^176/d{8}$" p = re.compile(mobile_model) if p.match(mobile): return mobile else: raise forms.ValidationError(u'手机号码错误',code="mobile_invalid") ========================================================= 2)在view里调用 方法一对应的调用: login_form = LoginForm(request.POST) # 获取一个验证的大字典,错误信息放在errors的健值里 if login_form.is_valid(): # 判断是否验证成功 方法二对应的调用: userask_form = UserAskForm(request.POST) if userask_form.is_valid(): # 把提交数据保存在数据表里,不用在从form表单里提出每个数据,在进行保存(优点) userask_obj = userask_form.save(commit=True) 3)在html调用login_form {
% if form_error.errors.password %}errorput{% endif %} {
% for key,value in form_error.errors.items %} # 字典循环(items) 二、注册 1、注册页面 其他的设置类似于登录页面。 注意: 1)、验证码(相关操作地址http://django-simple-captcha.readthedocs.io/en/latest/usage.html) 2)、验证码在view引用时,get方法时:register_form = RegisterForm() # 不需要传变量 def get(self,request): register_form = RegisterForm() return render(request,'register.html',{
"register_form":register_form}) 3)、验证码在html引用是:{
{ register_form.captcha }} 2、后台逻辑操作 =============================================== class UserRegister(View): def get(self,request): register_form = RegisterForm() return render(request,'register.html',{
"register_form":register_form}) def post(self,request): register_form = RegisterForm(request.POST) if register_form.is_valid(): user_name = request.POST.get("email",None) user_pwd = request.POST.get("password",None) user_object = UserProfile() user_object.username = user_name user_object.email = user_name user_object.password = make_password(user_pwd) user_object.save() return render(request,'index.html',{
"username":user_name}) else: return render(request,'register.html',{
"register_form":register_form}) =============================================== 3、实现发送邮箱 1)配置setting =========================================== EMAIL_HOST = "smtp.126.com" EMAIL_PORT = 25 EMAIL_HOST_USER = "huang7299@126.com" EMAIL_HOST_PASSWORD = "huang5607299" # 授权密码 EMAIL_USE_TLS = False EMAIL_FROM = "huang7299@126.com" =========================================== 2)在apps下进行目录util,在目录下新建文件sendmail.py ============================================================ import random from user.models import EmailVerifyRecord from django.core.mail import send_mail # django内置发邮件 from TFF.settings import EMAIL_FROM # 加载setting变量 def randow_str(num=6): code = '' for i in range(num): r = random.randrange(0,4) if r == 0 or r == 2: m = random.randint(0,9) code += str(m) else : temp = chr(random.randint(65,90)) code += str(temp) return code def Sendmail(email,send_type=2,code_num=10): email_object = EmailVerifyRecord() code = randow_str(num=code_num) email_object.code = code email_object.email = email email_object.send_type = send_type email_object.save() email_title='' email_boby='' if send_type == 2 : email_title='腾飞学习网注册激活链接' email_boby='请点击下面的链接激活你的账号:http://127.0.0.1:8000/active/{0}'.format(code) email_result = send_mail(email_title,email_boby,EMAIL_FROM,[email]) if email_result: return True else: return False elif send_type == 1 : email_title='腾飞学习网重置密码链接' email_boby='请点击下面的链接重置你的密码:http://127.0.0.1:8000/reset/{0}'.format(code) email_result = send_mail(email_title,email_boby,EMAIL_FROM,[email]) if email_result: return True else: return False ============================================================ 三、忘记密码=========================================================================class UserReset(View): def get(self,request,code_num): email_obj = EmailVerifyRecord.objects.filter(code=code_num) for i_email in email_obj: email = i_email.email send_time = i_email.send_time now_time = datetime.datetime.now() days = (now_time - send_time).days seconds = (now_time - send_time).seconds if days == 0 and seconds < 600: user_obj = UserProfile.objects.get(email=email) return render(request,"password_reset.html",{
"email_value":user_obj.email}) else: continue return render(request,"sendmail_outtime.html") ==========================================================================class UserPwdReset(View): # def get(self,request): # return render(request,'password_reset.html') def post(self,request): pwdreset_form = PwdResetForm(request.POST) email = request.POST.get('email',None) if pwdreset_form.is_valid(): password1 = request.POST.get('password1',None) password2 = request.POST.get('password2',None) if password1 == password2: user_obj = UserProfile.objects.get(email=email) user_obj.password = make_password(password1) user_obj.save() return render(request,'login.html',{}) else: return render(request,'password_reset.html',{
"email_value":email,"mesg":u"密码不一致"}) else: return render(request,'password_reset.html',{
"pwdreset_form":pwdreset_form,"email_value":email})注:重置密码页面不用写get,避免直接访问========================================================================== url(r'^forgetpwd/',user_views.UserForgetPWD.as_view(),name="userforgetpwd"), url(r'^reset/(?P
.*)/$',user_views.UserReset.as_view(),name="userreset"), url(r'^password_reset/',user_views.UserPwdReset.as_view(),name="pwdreset"), 注:第三条url的目的 # 为了在html上form提交上使用action="{% url 'pwdreset' %}"==========================================================================四、退出登录==========================================================================class UserLogout(IsLoginRequired,View): def get(self,request): logout(request) from django.core.urlresolvers import reverse return HttpResponseRedirect(reverse("index")) 注:要用“return HttpResponseRedirect(reverse("index"))”而不用“return render(request,"index.html",{})” 原因是:第一种:除了跳转到页面,还会执行“页面对应view方法”,而render不会执行view方法============================================================================
登录与注册

四、前端和后台逻辑实现数据交互

一、前端通过http方式提交数据到后台(get,post)    1、html        子form表单下面要加上以下的模板语言,才能把数据提交到后台        {
% csrf_token %} 2、view 后台获取数据(注:POST是大写) if request.method == 'POST': # request包含了请求所发给后端的所有信息(请求头,请求方式,数据。。) u_user = request.POST.get('name',None) u_email = request.POST.get('email',None) u_adress = request.POST.get('address',None) u_textinfo = request.POST.get('message',None) models.Userinfo2.objects.create( user=u_user,email=u_email,adress=u_adress,textinfo=u_textinfo )二、后台传递数据到前端 1、views 格式: return render(request,html,{}) 例子: return render(request,"upbook.html",{ "messgeinfo":session # session可以是字典形式 }) 2、html(模板语言)
{
{ messgeinfo.error }}
# 字典获取元素的方法messgeinfo.error
1、将上传的图片或者文件,展示到前端        1)配置settings            # 上传文件的路径            MEDIA_URL = '/media/'            MEDIA_ROOT = os.path.join(BASE_DIR,"media")                    2)url配置        ==================================================================        旧版本:        from django.views.static import serve  # 前端显示出图片内容,旧版本        from TFF.settings import MEDIA_ROOT                # url(r'^madia/(?P
.*)$', serve,{"document_root":MEDIA_ROOT}), # 旧版本 ================================================================== # 新版本 from django.conf.urls.static import static from TFF import settings urlpatterns = [ ]+static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT) # 在url配置的尾部加 3)html展示 {
{ MEDIA_URL }}{
{ obj.image }} # obj.image 为用户上传到数据库的字段
上传文件或图片的显示

 

转载于:https://www.cnblogs.com/langzibin/p/7693457.html

你可能感兴趣的文章
注意java的对象引用
查看>>
C++ 面向对象 类成员函数this指针
查看>>
NSPredicate的使用,超级强大
查看>>
自动分割mp3等音频视频文件的脚本
查看>>
判断字符串是否为空的注意事项
查看>>
布兰诗歌
查看>>
js编码
查看>>
Pycharm Error loading package list:Status: 403错误解决方法
查看>>
steps/train_sat.sh
查看>>
转:Linux设备树(Device Tree)机制
查看>>
iOS 组件化
查看>>
(转)Tomcat 8 安装和配置、优化
查看>>
(转)Linxu磁盘体系知识介绍及磁盘介绍
查看>>
tkinter布局
查看>>
命令ord
查看>>
Sharepoint 2013搜索服务配置总结(实战)
查看>>
博客盈利请先考虑这七点
查看>>
使用 XMLBeans 进行编程
查看>>
写接口请求类型为get或post的时,参数定义的几种方式,如何用注解(原创)--雷锋...
查看>>
【OpenJ_Bailian - 2287】Tian Ji -- The Horse Racing (贪心)
查看>>