Python大神 - Django(基础知识)--构建项目的思路

python

一、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,tests

3)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 pymysql

3 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)

=================================================

另外一个后台管理构架--xadmin

1、安装

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<code_num>.*)/$',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(模板语言)

<div style="color: red;">{{ messgeinfo.error }}</div> # 字典获取元素的方法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<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配置的尾部加

3)html展示

{{ MEDIA_URL }}{{ obj.image }} # obj.image 为用户上传到数据库的字段

上传文件或图片的显示

以上是 Python大神 - Django(基础知识)--构建项目的思路 的全部内容, 来源链接: utcz.com/z/387779.html

回到顶部