从零开始搭建五脏俱全的django项目!day01

主路由模块添加功能

安装tinymce:



``'
sudo pip3 install django-tinymce==2.6.0

因为要使用到富文本编辑器所以在settings中注册应用’tinymce’,并且在settings中添加tinymce相关属性


这是富文本编辑器在settins.py中的应用

# 富文本编辑器配置

TINYMCE_DEFAULT_CONFIG = {

    'theme': 'advance',

    'width': 600,

    'height': 400,

}




还需要在主路由中添加一个新的请求地址:

url(r'^tinymce/', include('tinymce.urls')), # 富文本编辑器

USER APP

注意在使用模型类之前要注意,在项目配置包的init中

​ 如果没有pymysql可以使用


sudo pip3 install pymysql

​ 然后在init中


import pymysql

pymysql.install_as_MySQLdb()




首先在models模块中创建模型类:


from django.db import models

# 导入django自带的用户模型类

# 减少代码量

from django.contrib.auth.models import AbstractUser

from db.base_model import BaseModel

# Create your models here.







class User(AbstractUser, BaseModel):

    """

    用户模型类

    """




    class Meta:

        """

        元数据类

        :var:db_table:模型类在数据库中的表名

        :var:verbose_name:定义模型类在后端管理时显示的名字

        """

        db_table = 'df_user'

        verbose_name = '用户'

        verbose_name_plural = verbose_name

        

    class Address(BaseModel):

        """

        地址模型类

        """

        user = models.ForeignKey('User', verbose_name='所属账户')

        receiver = models.CharField(max_length=20, verbose_name='收件人')

        addr = models.CharField(max_length=256, verbose_name='收件地址')

        zip_code = models.CharField(max_length=6, null=True, verbose_name='邮政编码')

        phone = models.CharField(max_length=11, verbose_name='联系电话')

        is_default = models.BooleanField(default=False, verbose_name='是否默认')




        class Meta:

            db_table = 'df_address'

            verbose_name = '地址'

            verbose_name_plural = verbose_name




user.urls相关


from django.conf.urls import url

from user.views import RegisterView, ActiveView, LoginView

# 从views视图模块中导入请求处理类,要注意当你在定义请求处理类时,可以定义多种方法get, post




urlpatterns = [

    # url(r'^register$', views.register, name='register'), # 注册

    # url(r'^register_handle$', views.register_handle, name='register_handle'), # 注册处理




    url(r'^register$', RegisterView.as_view(), name='register'), # 注册

    url(r'^active/(?P.*)$', ActiveView.as_view(), name='active'), # 用户激活

    url(r'^login$', LoginView.as_view(), name='login'), # 登录

]

在user.views中创建处理RegisterView类来处理注册请求

要处理的请求:


url(r'^register$', RegisterView.as_view(), name='register'), # 注册

处理的代码:


from django.shortcuts import render,redirect

from django.core.urlresolvers import reverse

# 方向解析模块,reverse()函数传入'appname.urlname'进行反响解析

from django.core.mail import send_mail

# 发送email模块

from django.contrib.auth import authenticate, login

# 自动登录验证与保存登录信息模块

from django.views.generic import View

# 在定义视图类的时候需要集成View

from django.http import HttpResponse

from django.conf import settings

# 当你想使用settins中的一些属性时,你可以尝试这样导入settins

from user.models import User

# 导入models模块中的模型类

from celery_tasks.tasks import send_register_active_email

# 导入email发送处理模块

from itsdangerous import TimedJSONWebSignatureSerializer as Serializer

# 加密模块

from itsdangerous import SignatureExpired

# 加密模块的错误信息类当加密时间过期后在进行解密会报错

import re

import time




# /user/register

class RegisterView(View):

    """

    注册

    用处理类来处理请求,需要集成自View,在其中可以定义实力方法get,post等需要注意方法名必须为小写

    """




    def get(self, request):

        """

        显示注册页面

        :param request:

        :return:

        """

        return render(request, 'register.html')




    def post(self, request):

        """

        进行注册处理

        :param request:

        :return:

        """

        # 接收数据

        username = request.POST.get('user_name')

        password = request.POST.get('pwd')

        email = request.POST.get('email')

        allow = request.POST.get('allow')




        # 进行数据校验

        if not all([username, password, email]):

            # 数据不完整

            return render(request, 'register.html', {'errmsg': '数据不完整'})




        # 校验邮箱

        if not re.match(r'^[a-z0-9][\w.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):

            return render(request, 'register.html', {'errmsg': '邮箱格式不正确'})




        if allow != 'on':

            return render(request, 'register.html', {'errmsg': '请同意协议'})




        # 校验用户名是否重复

        try:

            user = User.objects.get(username=username)

        except User.DoesNotExist:

            # 用户名不存在

            user = None




        if user:

            # 用户名已存在

            return render(request, 'register.html', {'errmsg': '用户名已存在'})




        # 进行业务处理: 进行用户注册

        user = User.objects.create_user(username, email, password)

        user.is_active = 0

        user.save()




        # 发送激活邮件,包含激活链接: http://127.0.0.1:8000/user/active/3

        # 激活链接中需要包含用户的身份信息, 并且要把身份信息进行加密




        # 加密用户的身份信息,生成激活token

        serializer = Serializer(settings.SECRET_KEY, 3600)

        info = {'confirm':user.id}

        token = serializer.dumps(info) # bytes

        token = token.decode()




        # 发邮件

        send_register_active_email.delay(email, username, token)




        # 返回应答, 跳转到首页

        return redirect(reverse('goods:index'))

因为发送email为了提高性能所以使用celery分布式处理任务

需要在本地安装celery


sudo pip3 install celery==3.1.25

sudo pip3 install django-celery==3.1.17

  1. 首先在项目主目录下创建celery_tasks python package

  2. 在celery_tasks包下创建tasks.py

  3. 在tasks中创建函数send_register_active_email()用来进行email的发送

    1. 
      在settins.py中添加如下配置
      
      
      
      
      # 发送邮件配置
      
      EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
      
      # smpt服务地址
      
      EMAIL_HOST = 'smtp.163.com'
      
      EMAIL_PORT = 25
      
      # 发送邮件的邮箱
      
      EMAIL_HOST_USER = '[email protected]'
      
      # 在邮箱中设置的客户端授权密码
      
      EMAIL_HOST_PASSWORD = 'hxx258456'
      
      # 收件人看到的发件人
      
      EMAIL_FROM = '天天生鲜<[email protected]>'
      
      
      
      
      
    2. 
      在tasks.py中添加如下代码
      # 使用celery
      from django.core.mail import send_mail
      from django.conf import settings
      from celery import Celery
      import time
      
      # 在任务处理者一端加这几句
      # import os
      # import django
      # os.environ.setdefault("DJANGO_SETTINGS_MODULE", "dailyfresh.settings")
      # django.setup()
      # 创建一个Celery类的实例对象
      # 使用redis处理任务队列
      app = Celery('celery_tasks.tasks', broker='redis://172.16.179.130:6379/8')
      
      
      # 定义任务函数
      @app.task
      def send_register_active_email(to_email, username, token):
      
          '''发送激活邮件'''
      
          # 组织邮件信息
      
          subject = '天天生鲜欢迎信息'
      
          message = ''
      
          sender = settings.EMAIL_FROM
      
          receiver = [to_email]
      
          html_message = '

      %s, 欢迎您成为天天生鲜注册会员

      请点击下面链接激活您的账户
      http://192.168.0.129:8000/user/active/%s' % (username, token, token) # html_message中的host:port要改为你项目启动时监听的地址和端口 send_mail(subject, message, sender, receiver, html_message=html_message) time.sleep(5)

  4. 在user.views中创建处理 ActiveView类来处理注册请求

要处理的请求:


url(r'^active/(?P.*)$', ActiveView.as_view(), name='active'), # 用户激活

处理的代码:


from django.shortcuts import render,redirect

from django.core.urlresolvers import reverse

# 方向解析模块,reverse()函数传入'appname.urlname'进行反响解析

from django.core.mail import send_mail

# 发送email模块

from django.contrib.auth import authenticate, login

# 自动登录验证与保存登录信息模块

from django.views.generic import View

# 在定义视图类的时候需要集成View

from django.http import HttpResponse

from django.conf import settings

# 当你想使用settins中的一些属性时,你可以尝试这样导入settins

from user.models import User

# 导入models模块中的模型类

from celery_tasks.tasks import send_register_active_email

# 导入email发送处理模块

from itsdangerous import TimedJSONWebSignatureSerializer as Serializer

# 加密模块

from itsdangerous import SignatureExpired

# 加密模块的错误信息类当加密时间过期后在进行解密会报错

import re

import time




class ActiveView(View):

    """用户激活"""

    def get(self, request, token):

        """进行用户激活"""

        # 进行解密,获取要激活的用户信息

        serializer = Serializer(settings.SECRET_KEY, 3600)

        try:

            info = serializer.loads(token)

            # 获取待激活用户的id

            user_id = info['confirm']




            # 根据id获取用户信息

            user = User.objects.get(id=user_id)

            user.is_active = 1

            user.save()




            # 跳转到登录页面

            return redirect(reverse('user:login'))

        except SignatureExpired as e:

            # 激活链接已过期

            return HttpResponse('激活链接已过期')

启动celery异步式任务处理
拷贝一份项目代码,在tasks.py中对项目django项目进行初始化初始化代码如下

# 在任务处理者一端加这几句
import os
import django
# 进行项目初始化
# worker在接收到处理任务时,需要对django项目环境变量进行初始化,启动项目
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mydailyfresh.settings")
django.setup()

注意处理者一定要连接网络不然没有办法使用smtp发送邮件
进入到拷贝好的项目主目录下

celery -A celery_tasks.tasks worker -l info
启动celery  -A 后添加你的任务处理转发者所在的目录

因为在register处理类的post方法中最后重定向到了goods.index视图所以需要对goodsapp进行配置

  1. 在goods下的models中配置相关模型类,来连接数据库

    
    from django.db import models
    
    from db.base_model import BaseModel
    
    from tinymce.models import HTMLField
    
    # Create your models here.
    
    
    class GoodsType(BaseModel):
    
        '''商品类型模型类'''
    
        name = models.CharField(max_length=20, verbose_name='种类名称')
    
        logo = models.CharField(max_length=20, verbose_name='标识')
    
        image = models.ImageField(upload_to='type', verbose_name='商品类型图片')
    
    
    
    
        class Meta:
    
            db_table = 'df_goods_type'
    
            verbose_name = '商品种类'
    
            verbose_name_plural = verbose_name
    
    
    
    
        def __str__(self):
    
            return self.name
    
    
    
    
    
    
    
    class GoodsSKU(BaseModel):
    
        '''商品SKU模型类'''
    
        status_choices = (
    
            (0, '下线'),
    
            (1, '上线'),
    
        )
    
        type = models.ForeignKey('GoodsType', verbose_name='商品种类')
    
        goods = models.ForeignKey('Goods', verbose_name='商品SPU')
    
        name = models.CharField(max_length=20, verbose_name='商品名称')
    
        desc = models.CharField(max_length=256, verbose_name='商品简介')
    
        price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='商品价格')
    
        unite = models.CharField(max_length=20, verbose_name='商品单位')
    
        image = models.ImageField(upload_to='goods', verbose_name='商品图片')
    
        stock = models.IntegerField(default=1, verbose_name='商品库存')
    
        sales = models.IntegerField(default=0, verbose_name='商品销量')
    
        status = models.SmallIntegerField(default=1, choices=status_choices, verbose_name='商品状态')
    
    
    
    
        class Meta:
    
            db_table = 'df_goods_sku'
    
            verbose_name = '商品'
    
            verbose_name_plural = verbose_name
    
    
    
    
    
    
    
    class Goods(BaseModel):
    
        '''商品SPU模型类'''
    
        name = models.CharField(max_length=20, verbose_name='商品SPU名称')
    
        # 富文本类型:带有格式的文本
    
        detail = HTMLField(blank=True, verbose_name='商品详情')
    
    
    
    
        class Meta:
    
            db_table = 'df_goods'
    
            verbose_name = '商品SPU'
    
            verbose_name_plural = verbose_name
    
    
    
    
    
    
    
    class GoodsImage(BaseModel):
    
        '''商品图片模型类'''
    
        sku = models.ForeignKey('GoodsSKU', verbose_name='商品')
    
        image = models.ImageField(upload_to='goods', verbose_name='图片路径')
    
    
    
    
        class Meta:
    
            db_table = 'df_goods_image'
    
            verbose_name = '商品图片'
    
            verbose_name_plural = verbose_name
    
    
    
    
    
    
    
    class IndexGoodsBanner(BaseModel):
    
        '''首页轮播商品展示模型类'''
    
        sku = models.ForeignKey('GoodsSKU', verbose_name='商品')
    
        image = models.ImageField(upload_to='banner', verbose_name='图片')
    
        index = models.SmallIntegerField(default=0, verbose_name='展示顺序')
    
    
    
    
        class Meta:
    
            db_table = 'df_index_banner'
    
            verbose_name = '首页轮播商品'
    
            verbose_name_plural = verbose_name
    
    
    
    
    
    
    
    class IndexTypeGoodsBanner(BaseModel):
    
        '''首页分类商品展示模型类'''
    
        DISPLAY_TYPE_CHOICES = (
    
            (0, "标题"),
    
            (1, "图片")
    
        )
    
    
    
    
        type = models.ForeignKey('GoodsType', verbose_name='商品类型')
    
        sku = models.ForeignKey('GoodsSKU', verbose_name='商品SKU')
    
        display_type = models.SmallIntegerField(default=1, choices=DISPLAY_TYPE_CHOICES, verbose_name='展示类型')
    
        index = models.SmallIntegerField(default=0, verbose_name='展示顺序')
    
    
    
    
        class Meta:
    
            db_table = 'df_index_type_goods'
    
            verbose_name = "主页分类展示商品"
    
            verbose_name_plural = verbose_name
    
    
    
    
    
    
    
    class IndexPromotionBanner(BaseModel):
    
        '''首页促销活动模型类'''
    
        name = models.CharField(max_length=20, verbose_name='活动名称')
    
        url = models.URLField(verbose_name='活动链接')
    
        image = models.ImageField(upload_to='banner', verbose_name='活动图片')
    
        index = models.SmallIntegerField(default=0, verbose_name='展示顺序')
    
    
    
    
        class Meta:
    
            db_table = 'df_index_promotion'
    
            verbose_name = "主页促销活动"
    
            verbose_name_plural = verbose_name
    
    
  2. 在goods下的urls.py中

    
    from django.conf.urls import url
    
    from goods import views
    
    
    
    
    urlpatterns = [
    
        url(r'^$', views.index, name='index'), # 首页
    
    ]
    
    
  3. 在goods下的views.py中

    
    from django.shortcuts import render
    
    
    
    
    # Create your views here.
    
    
    
    
    # http://127.0.0.1:8000
    
    def index(request):
    
        '''首页'''
    
        return render(request, 'index.html')
    
    

因为在用户激活后会重定向到user.login视图中所以要在user.views中创建LoginView处理类

# /user/login
class LoginView(View):
    '''登录'''
    def get(self, request):
        '''显示登录页面'''
        # 判断是否记住了用户名
        if 'username' in request.COOKIES:
            username = request.COOKIES.get('username')
            checked = 'checked'
        else:
            username = ''
            checked = ''

    # 使用模板
    return render(request, 'login.html', {'username':username, 'checked':checked})

def post(self, request):
    '''登录校验'''
    # 接收数据
    username = request.POST.get('username')
    password = request.POST.get('pwd')

    # 校验数据
    if not all([username, password]):
        return render(request, 'login.html', {'errmsg':'数据不完整'})

    # 业务处理:登录校验
    user = authenticate(username=username, password=password)
    # 使用django官方登录函数认证传入用户名和密码如果认证成会返回一个user对象,否则返回一个None
    if user is not None:
        # 用户名密码正确
        if user.is_active:
            # 用户已激活
            # 记录用户的登录状态
            login(request, user)

            # 跳转到首页
            response = redirect(reverse('goods:index')) # HttpResponseRedirect

            # 判断是否需要记住用户名
            remember = request.POST.get('remember')

            if remember == 'on':
                # 记住用户名
                response.set_cookie('username', username, max_age=7*24*3600)
            else:
                response.delete_cookie('username')

            # 返回response
            return response
        else:
            # 用户未激活
            return render(request, 'login.html', {'errmsg':'账户未激活'})
    else:
        # 用户名或密码错误
        return render(request, 'login.html', {'errmsg':'用户名或密码错误'})

使用redis保存django项目的缓存与session
首先要安装django-redis-sessions==0.5.6

pip3 install django-redis

安装完成后需要在settings中配置如下

# Django的缓存配置
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/2",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}

# 配置session存储
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "default"

你可能感兴趣的:(小经验)