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

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

一、Models数据结构
Django前后端分离开发-新闻管理系统(二)

二、创建模型 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后台管理系统登陆

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,如下图,说明以上配置成功,后台管理界面可以添加一些分类等测试数据
Django前后端分离开发-新闻管理系统(二)
Django前后端分离开发-新闻管理系统(二)

五、创建序列化器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: 976367613@qq.com
      @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 第一个应用 项目的数据库模型 (创建、激活模型)