项目源码下载: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,如下图,说明以上配置成功,后台管理界面可以添加一些分类等测试数据
五、创建序列化器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')