django: rest-framework序列化对象及关联对象(实现多级分类的序列化例子)

  1. 在项目中经常会遇到多级分类的状态, model中,常常用只用一个model类来表示多级分类, 那么使用restframework序列化的时候如何让类别的层级更有条理呢?
  • 1.在模块中是常规写法:

此处商品类别的分类级别是固定的, 不会无限级分类的的情况, 这样会简单的多。
models.py的常规写法:

class GoodsCategory(models.Model):
    """ 
    商品类别
    """
    CATEGORY_TYPE = ( 
        (1, "一级类目"),
        (2, "二级类目"),
        (3, "三级类目"),
    )   
    name = models.CharField(default="", max_length=30, verbose_name="类别名", help_text="类别名")
    category_type = models.IntegerField(choices=CATEGORY_TYPE, verbose_name="类目级别", help_text="类目级别")
    parent_category = models.ForeignKey("self", null=True, blank=True, verbose_name="父类目级别", help_text="父目录", related_name="sub_cat")

注意此处的related_name定义为sub_cat, 待会会用的到。

  • 2.在视图方法中同样使用的常规的写法:

在视图中指定一个需要序列化的查询集和一个序列化类:

class CategoryViewSet(mixins.ListModelMixin,  viewsets.GenericViewSet):
    queryset = GoodsCategory.objects.all()
    serializer_class = CategorySerializer
  • 3.关键之处在于序列化类的书写
class CategorySerializer(serializers.ModelSerializer):
    # sub_cat是model中已经指定的related_name, 需要保持一致
    # 以下sub_cat和parent_category均可以体现分类的层级关系, 
    # sub_cat表示子类, parent_category表示父类
    sub_cat = CategorySerializer2(many=True)
    # parent_category = CategorySerializer2()    
    class Meta:
        model = GoodsCategory
        fields = '__all__'

可以看出, 序列化类CategorySerializer中又对sub_cat字段作序列化。
当然还需要再写两个序列化类。

class CategorySerializer3(serializers.ModelSerializer):
    class Meta:
        model = GoodsCategory
        fields = '__all__'

class CategorySerializer2(serializers.ModelSerializer):
    sub_cat = CategorySerializer3(many=True)
    class Meta:
        model = GoodsCategory
        fields = '__all__'
  • 未完

线程池ThreadPoolExecutor

使用futures模块:

  • 线程池可以用来限制同时运行的最大线程数;
  • 在主进程中获取某一个线程或者某一个任务的状态或者返回值;
  • 当一个线程运行完成时主线程可以立即知道;
  • 让多线程和多进程的编码接口一致。

一. 函数体:

def get_html(sleep_time):
    time.sleep(sleep_time)
    # print('get_page success', sleep_time)
    return 'success,{}'.format(sleep_time)

二. 任务操作

submit提交

使用submit提交函数到线程池, 打开一个线程, submit是立即返回, 非阻塞方法

from concurrent.futures import ThreadPoolExecutor

if __name__ == '__main__':
    # 参数表示可以同时执行的嘴阀线程数量
    excu = ThreadPoolExecutor(3)
     # 使用submit提交函数到线程池, 打开一个线程, submit是立即返回, 非阻塞
    task1 = excu.submit(get_html, (5))
cancel取消

取消进程, 如果cancel失败会返回一个false, 如果任务处在执行中或者执行完成状态, 则会取消失败

    task2 = excu.submit(get_html, (5))
    print('查看取消', task2.cancel())   
done 判断完成.
 task1 = excu.submit(get_html, (5))
print('查看task1是否完成', task1.done())
result查看进程返回结果
 task2 = excu.submit(get_html, (5))
print('查看task2的运行返回结果', task2.result())
使用excutor.map
from concurrent.futures import ThreadPoolExecutor
if __name__ == '__main__':
    excu = ThreadPoolExecutor(3)
    urls = [2, 3, 4]
    # 通过excu.map()获取已经完成的task返回值
    for data in excu.map(get_html, urls):
         print('the result is ', data)
as_completed获取已经完成的task
from concurrent.futures import ThreadPoolExecutor, as_completed,
if __name__ == '__main__':
    excu = ThreadPoolExecutor(3)
    urls = [2, 3, 4]
     # 通过as_completed获取已经完成的task1
    all_task = [excu.submit(get_html, (url)) for url in urls]
    for future in as_completed(all_task):
        data = future.result()
        print(data)
wait阻塞以等待线程完成
from concurrent.futures import ThreadPoolExecutor, as_completed, wait
if __name__ == '__main__':
    excu = ThreadPoolExecutor(3)
    urls = [2, 3, 4]
     # 通过as_completed获取已经完成的task1
    all_task = [excu.submit(get_html, (url)) for url in urls]
    for future in as_completed(all_task):
        data = future.result()
        print(data)
    wait(all_task)
    print('end')

推荐: https://manjusaka.itscoder.com/2017/11/28/something-about-concurrent-future/

flask 多对多

在flask中实现字段间多对多关系, 需要手动创建中间的辅助表, 对于这个辅助表, 强烈建议不要使用模型,而是采用一个实际的表, 因为这个辅助表是永远不会被实例化使用的.


tags = db.Table('tags', db.Column('tag_id', db.Integer, db.ForeignKey('tag.id')), db.Column('page_id', db.Integer, db.ForeignKey('page.id')) ) class Page(db.Model): id = db.Column(db.Integer, primary_key=True) # secondary: 在多对多关系, 指定关联表的名称 tags = db.relationship('Tag', secondary=tags, backref=db.backref('pages', lazy='dynamic'), lazy='dynamic') class Tag(db.Model): id = db.Column(db.Integer, primary_key=True)
  • 例2

文章和收藏


# 创建一个收藏的中间表 collections = db.Table( 'collections', db.Column('user.id', db.Integer, db.ForeignKey('user.id')), db.Column('post_id', db.Integer, db.ForeignKey('posts.id')) ) class User(db.Model, UserMixin): __tablename__ = 'user' id = db.Column(db.Integer, primary_key=True) # secondary: 在多对多关系, 指定关联表的名称 favorite = db.relationship('Posts', secondary='collections', backref=db.backref('users'), lazy='dynamic') class Posts(db.Model): id = db.Column(db.Integer, primary_key=True)