Django前后端分离开发-新闻管理系统(二)

项目源码下载:https://github.com/Cherish-sun/NEWS/tree/master

一、Models数据结构

数据表结构

二、创建模型 models.py

# Create your models here.
from django.db import models
import datetime
from django.contrib.auth.models import User
from DjangoUeditor.models import UEditorField
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.authtoken.models import Token


class Category(models.Model):
    title = models.CharField(max_length=20, verbose_name='名称', help_text="大类")

    def __str__(self):
        return self.title

    class Meta:
        ordering = ['title']
        verbose_name = '新闻类别'
        verbose_name_plural = verbose_name


class Item(models.Model):
  title = models.CharField(max_length=20, verbose_name='名称', help_text="名称")
  created_date = models.DateTimeField(default=datetime.datetime.now, verbose_name='创建时间', help_text="创建时间")
  completed = models.BooleanField(default=False, verbose_name='是否完成', help_text="是否完成")
  categorys = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='items', help_text="大类")

  def __str__(self):
      return self.title

  class Meta:
      ordering = ['title']
      verbose_name = '新闻子栏目'
      verbose_name_plural = verbose_name


class Tag(models.Model):
    name = models.CharField(max_length=50, verbose_name=u'名称', help_text="名称")
    slug = models.SlugField(max_length=50, verbose_name=u'描述')

    def __str__(self):
        return self.name

    class Meta:
        ordering = ['id']
        verbose_name = '标签'
        verbose_name_plural = verbose_name


class Article(models.Model):
    title = models.CharField(max_length=100, verbose_name='标题', help_text="名称")
    slug = models.SlugField(unique_for_year='publish_date', verbose_name='描述')
    # author = models.CharField(max_length=100, verbose_name='作者', help_text="作者")
    author = models.ForeignKey(User, related_name='author', on_delete=models.CASCADE, verbose_name='作者', help_text="作者")
    # content = models.TextField(verbose_name='内容')
    content = UEditorField(u'内容', height=400, width=600, default='', imagePath="upload/",
                       toolbars='mini', filePath='upload/', blank=True)
    status = models.CharField(max_length=2, verbose_name='状态', help_text="状态")
    tags = models.ManyToManyField(Tag, related_name='tags', blank=True, help_text="标签")
    publish_date = models.DateTimeField(default=datetime.datetime.now(), verbose_name='发布日期', help_text="发布日期")
    expiration_date = models.DateTimeField(blank=True, null=True, verbose_name='有效日期', help_text="有效日期")
    is_active = models.BooleanField(default=True, blank=True, verbose_name='是否热门', help_text="是否热门")
    item = models.ForeignKey(Item, related_name='item', on_delete=models.CASCADE, verbose_name='类别名称', help_text="类别名称")
    pic = models.ImageField(upload_to='uploads', verbose_name='图片', help_text="图片")
    praise_num = models.IntegerField(default=0, verbose_name='点赞', help_text="点赞")
    read_num = models.IntegerField(default=0, verbose_name='浏览数', help_text="浏览数")
    fav_num = models.IntegerField(default=0, verbose_name='收藏数', help_text="收藏数")

    def __str__(self):
        return self.title

    class Meta:
        verbose_name = '新闻文章'
        verbose_name_plural = verbose_name


class Ad(models.Model):
    title = models.CharField(max_length=50, verbose_name='标题', help_text="标题")
    pic = models.ImageField(upload_to='uploads', verbose_name='广告图', help_text="广告图")
    adurl = models.URLField(verbose_name='地址', help_text="地址")
    adlocation = models.CharField(max_length=2, verbose_name='位置', help_text="位置")  # a1,a2,a3,b1,b2,b3....
    status = models.CharField(max_length=1, default=1, verbose_name='状态', help_text="状态")


class UserFav(models.Model):
    """
    用户收藏
    """
    user = models.ForeignKey(User, related_name='user', on_delete=models.CASCADE, verbose_name="用户")
    articles = models.ForeignKey(Article, related_name='articles', on_delete=models.CASCADE, verbose_name="文章",
                             help_text="文章id")
    add_time = models.DateTimeField(default=datetime.datetime.now, verbose_name=u"添加时间")

    class Meta:
        verbose_name = '用户收藏'
        verbose_name_plural = verbose_name
        unique_together = ("user", "articles")

    def __str__(self):
        return self.user.username

按住Ctrl+Alt+l 快捷键可以将代码格式化

二、安装DjangoUeditor,富文本编辑器

下载地址:https://github.com/wsf31325909/DjangoUeditor

解压后,把DjangoUeditor文件夹拷贝到项目目录下面

注意:直接pip install DjangoUeditor的方法会出问题

settings.py中添加app
INSTALLED_APPS = [
    'DjangoUeditor',
]

三、数据库迁移 , 打开pycharm底端Terminal依次输入以下迁移命令

python manage.py makemigrations  # 迁移到我们数据库
python manage.py migrate # 同步到数据库
python manage.py createsuperuser # 创建超级用户, 根据提示输入用户名、邮箱、密码,用于django后台管理系统登陆
迁移成功

四、后台管理系统admin.py配置

from django.contrib import admin
from .models import *


# Register your models here.
class ArticleAdmin(admin.ModelAdmin):
    # 列表显示字段
    list_display = ('title', 'item', 'status', 'author', 'publish_date',
                'expiration_date', 'is_active')

    list_filter = ('author', 'status', 'is_active', 'publish_date',
               'expiration_date')
    # 每页记录数
    list_per_page = 25
    # 查询字段
    search_fields = ('title', 'tags', 'slug', 'content')

    class Media:
        js = ('/static/ueditor/ueditor.config.js', '/static/ueditor/ueditor.all.min.js',)


class TagAdmin(admin.ModelAdmin):
    list_display = ('name', 'article_count')

    def article_count(self, obj):
        return Article.objects.filter(tag=obj).count()


class CategoryAdmin(admin.ModelAdmin):
    list_display = ('id', 'title', 'item_count')

    def item_count(self, obj):
        # return obj.item_set.count()
        return Item.objects.filter(categorys=obj).count()


class ItemAdmin(admin.ModelAdmin):
    list_display = ('title', 'created_date', 'categorys', 'completed')


class AdAdmin(admin.ModelAdmin):
    list_display = ('title', 'pic', 'adurl', 'adlocation', 'status')


admin.site.register(Category, CategoryAdmin)
admin.site.register(Item, ItemAdmin)
admin.site.register(Tag, TagAdmin)
admin.site.register(Article, ArticleAdmin)
admin.site.register(Ad, AdAdmin)

这时运行程序,浏览器依次打开 http://127.0.0.1:8000/和http://127.0.0.1:8000/admin,如下图,说明以上配置成功,后台管理界面可以添加一些分类等测试数据

运行结果

admin

五、创建序列化器serializers

serializers是一个数据转换器,序列化主要是处理输入数据和输出数据(序列化输出、反序列化输入)

将复杂的数据结构与json或者xml这个格式互相转换
实例对象 <=> 原生数据类型 <=> JSON(XML)
User <=> b'{"name": 1}' <=> {"name": 1}

• serializers有以下几个作用:

1、将queryset与model实例等进行序列化,转化成json格式,返回给用户(api接口)。
2、将post与patch/put的上来的数据进行验证。
3、对post与patch/put数据进行处理。
* 推荐用ModelSerializer继承了Serializer的相关功能,是对model实现序列化的封装(代码少)

序列化详细介绍:http://www.careeru.cn/blog/article/?id=85
进入article目录下创建serilaizes.py文件

# -*- coding: utf-8 -*-
"""
@version: v1.0
@author: wyq
@license: Apache Licence
@contact: [email protected]
@site:
@software: PyCharm
@file: serilaizes.py
@time: 2019/3/1 16:48
"""
from rest_framework import serializers
from django.contrib.auth.models import User, Group
from .models import Category, Item, Tag, Article, Ad, UserFav
from rest_framework.validators import UniqueValidator, UniqueTogetherValidator  # 序列化验证
from rest_framework.compat import authenticate  # 权限验证


# user序列化类 继承ModelSerializer
class UserSerializer(serializers.ModelSerializer):
    class Meta:
        # 指定模型名称
        model = User
        # 指定需要字段,全部用"__all__"
        fields = "__all__"
    # fields = ('url', 'username', 'email', 'groups')


class GroupSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Group
        fields = ('url', 'name')


# 分类
class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = "__all__"


# 实现新闻类别增加类别下面的栏目数据,采用自定义字段方法实现
class CategoryitemsSerializer(serializers.ModelSerializer):
    # 通过SerializerMethodField增加新字段值
    items = serializers.SerializerMethodField()

    class Meta:
        model = Category
        fields = "__all__"

    # 在序列化对象里添加自定义内容 函数名为:# 方法写法:get_ + 字段
    def get_items(self, obj):
        items = Item.objects.filter(categorys=obj.id)
        if items:
            items_serializer = ItemnocateSerializer(items, many=True, context={'request': self.context['request']})
            return items_serializer.data


class CategoryStringSerializer(serializers.ModelSerializer):
    # 用__str__方法表示只读关系 items 为外键关系中的related_name
    items = serializers.StringRelatedField(many=True)

    class Meta:
        model = Category
        # fields = ('id', 'title','items')
        fields = "__all__"


class CategoryPrimaryKeySerializer(serializers.ModelSerializer):
    # 用主键表示关系
    items = serializers.PrimaryKeyRelatedField(many=True, read_only=True)

    class Meta:
        model = Category
        fields = "__all__"


class CategorySlugSerializer(serializers.ModelSerializer):
    # 选取关系对象中任意一个字段(唯一标识)表示关系
    items = serializers.SlugRelatedField(
        many=True,
        read_only=True,
        slug_field='title'
    )

    class Meta:
        model = Category
        fields = "__all__"


# 子栏目
class ItemSerializer(serializers.ModelSerializer):
    # 正向嵌套
    categorys = CategorySerializer()

    class Meta:
        model = Item
        fields = "__all__"


class ItemnocateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Item
        fields = "__all__"


# 按serializers来序列化
class TagSerializer(serializers.ModelSerializer):
    # id = serializers.Field()
    name = serializers.CharField(required=True, max_length=100)
    slug = serializers.CharField(required=True, max_length=100)

    class Meta:
        model = Tag
        fields = ('id', 'name', 'slug')


class AdSerializer(serializers.ModelSerializer):
    class Meta:
        model = Ad
        fields = "__all__"


class ArticleSerializer(serializers.ModelSerializer):
    # 外键相关对象
    item = ItemSerializer()
    author = UserSerializer()
    tags = TagSerializer(many=True)

    class Meta:
        model = Article
        fields = "__all__"


class Hot_articleSerializer(serializers.ModelSerializer):
    item = ItemSerializer()
    author = UserSerializer()
    tags = TagSerializer(many=True)

    class Meta:
        model = Article
        fields = "__all__"


class ArticlemodelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Article
        fields = "__all__"


class UserDetailSerializer(serializers.ModelSerializer):
    """
    用户详情序列化类
    """
    token = serializers.CharField(required=False, max_length=1024)

    class Meta:
        model = User
        fields = "__all__"


class UserRegSerializer(serializers.ModelSerializer):
    username = serializers.CharField(label="用户名", help_text="用户名", required=True, allow_blank=False,
                                 validators=[UniqueValidator(queryset=User.objects.all(), message="用户已经存在")])

    password = serializers.CharField(
    style={'input_type': 'password'}, help_text="密码", label="密码", write_only=True,
)
    token = serializers.CharField(required=False, max_length=1024)

    class Meta:
        model = User
        fields = ('username', 'password', 'token')


class UserLoginSerializer(serializers.ModelSerializer):
    """
    用户登录序列化类
    """
    username = serializers.CharField(required=True, max_length=100)
    password = serializers.CharField(required=True, max_length=100)
    token = serializers.CharField(required=False, max_length=1024)

    # attrs 为封装后的request
    def validate(self, attrs):
        username = attrs.get('username')
        password = attrs.get('password')

        if username and password:
            # 用户名称、密码登录验证
            user = authenticate(request=self.context.get('request'),
                            username=username, password=password)
            # The authenticate call simply returns None for is_active=False
            # users. (Assuming the default ModelBackend authentication
        # backend.)

            if not user:
                msg = '不能登录'
                raise serializers.ValidationError(msg, code='authorization')
        else:
            msg = '必须输入同时输入名称和密码'
            raise serializers.ValidationError(msg, code='authorization')

        attrs['user'] = user
        return attrs

    class Meta:
        model = User
        fields = ('id', 'username', 'password', 'token')


class UserSetPasswordSerializer(serializers.ModelSerializer):
    username = serializers.CharField(label="用户名", help_text="用户名", required=True, allow_blank=False)

    password = serializers.CharField(
    style={'input_type': 'password'}, help_text="密码", label="密码", write_only=True,
)
    newpassword = serializers.CharField(
    style={'input_type': 'password'}, help_text="新密码", label="新密码", write_only=True,
)

    # 验证用户名、密码是否正确
    def validate(self, attrs):
        username = attrs.get('username')
        password = attrs.get('password')

        if username and password:
            # 用户名称、密码登录验证
            user = authenticate(request=self.context.get('request'),
                            username=username, password=password)
            # The authenticate call simply returns None for is_active=False
            # users. (Assuming the default ModelBackend authentication
            # backend.)

            if not user:
                msg = '不能修改'
                raise serializers.ValidationError(msg, code='authorization')
        else:
            msg = '必须输入同时输入名称和密码'
            raise serializers.ValidationError(msg, code='authorization')

        attrs['user'] = user
        return attrs

    class Meta:
        model = User
        fields = ('username', 'password', 'newpassword')


class UserFavDetailSerializer(serializers.ModelSerializer):
    articles = ArticleSerializer()

    class Meta:
        model = UserFav
        fields = ('articles', 'id')


class UserFavSerializer(serializers.ModelSerializer):
    # 隐藏字段
    user = serializers.HiddenField(
    default=serializers.CurrentUserDefault()
)

    class Meta:
        model = UserFav
        validators = [
            UniqueTogetherValidator(
            queryset=UserFav.objects.all(),
            fields=('articles', 'user'),
            message="已经收藏"
        )
    ]

        fields = ('user', 'articles', 'id')

你可能感兴趣的:(Django前后端分离开发-新闻管理系统(二))