Models模型(下)

Posted bijian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Models模型(下)相关的知识,希望对你有一定的参考价值。

一、最基本的django模型

1、先看下一个新闻博客的Article模型。这个模型是最基本的django模型,里面包括了各个字段(fields),重写了显示文章对象名字的__str__方法(python内置的),并在Meta选项里给模型命名(verbose name)。建议每个django模型至少包括字段,重写的__str__方法和Meta选项。

from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
from django.utils.timezone import now

# Create your models here.

class Article(models.Model):

    STATUS_CHOICES = (
        (d, 草稿),
        (p, 发表),
    )

    title = models.CharField(标题, max_length=200, unique=True)
    slug = models.SlugField(slug, max_length=60)
    body = models.TextField(正文)
    pub_date = models.DateTimeField(发布时间, default=now, null=True)
    create_date = models.DateTimeField(创建时间, auto_now_add=True)
    mod_date = models.DateTimeField(修改时间, auto_now=True)
    status = models.CharField(文章状态, max_length=1, choices=STATUS_CHOICES, default=p)
    views = models.PositiveIntegerField(浏览量, default=0)
    author = models.ForeignKey(User, verbose_name=作者, on_delete=models.CASCADE)

    tags = models.ManyToManyField(Tag, verbose_name=标签集合, blank=True)

    def __str__(self):
        return self.title

    class Meta:
        verbose_name = "article"

2、基础模型很多时候并不能满足需求。试想打算使用django自带的通用视图创建文章,由于通用视图在完成对象创建后需要跳转到文章的absolute_url, 这时需要在模型里加入自定义的get_absolute_url方法。由于希望统计每篇文章浏览次数,还需自定义一个使浏览量自增1的viewed方法,并更新数据表。

def get_absolute_url(self):
    return reverse(blog:article_detail, args=[str(self.id)])

def viewed(self):
    self.views += 1
    self.save(update_fields=[views])

如果希望调用Article.objects.all()按时pub_date降序排列查询结果,可以在Meta里加入ordering选项即可。

class Meta:
    ordering = [-pub_date]
    verbose_name = "article"

二、模型中自定义图片和文件上传路径

  Django模型中的ImageField和FileField的upload_to选项是必填项,其存储路径是相对于MEIDA_ROOT而来的。然而可能希望动态定义上传路径,比如把文件上传到每个用户名下的文件夹里,并对上传文件重命名,这时可以定义一个user_directory_path方法。

from django.db import models
from django.contrib.auth.models import User
import uuid
import os

# Create your models here.


def user_directory_path(instance, filename):
    ext = filename.split(.)[-1]
    filename = {}.{}.format(uuid.uuid4().hex[:10], ext)
    # return the whole path to the file
    return os.path.join(instance.user.id, "avatar", filename)


class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name=profile)
    avatar = models.ImageField(upload_to=user_directory_path, verbose_name="头像")

三、Django模型的Manager方法

  Django模型自带models.Manager方法,可以简化代码。如下面案例中,可以使用Person.objects.all()查询到所有人,而Person.authors.all和Person.editors.all()只返回所authors和editors。

from django.db import models

# Create your models here.


class AuthorManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(role=A)

class EditorManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(role=E)

class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    role = models.CharField(max_length=1, choices=((A, _(Author)), (E, _(Editor))))
    objects = models.Manager()
    authors = AuthorManager()
    editors = EditorManager()

四、Django模型的save方法重写

在很多应用场景中需要重写django模型的save方法。

from django.db import models
import hashlib


class UserInfo(models.Model):
    username = models.CharField("用户名", max_length=64, unique=True)
    password = models.CharField("密码", max_length=64)
    uid = models.CharField(verbose_name=个人唯一ID, max_length=64, unique=True)

    wx_id = models.CharField(verbose_name="微信ID", max_length=128, blank=True, null=True, db_index=True)

    def save(self, *args, **kwargs):
        # 创建用户时,为用户自动生成个人唯一ID
        if not self.pk:
        # 存在就更新,不存在就创建
            m = hashlib.md5()
            m.update(self.username.encode(encoding="utf-8"))
            self.uid = m.hexdigest()
        super(UserInfo, self).save(*args, **kwargs)

五、完美的Django高级模型结构

from django.db import models
from django.urls import reverse

# Create your models here.

# 自定义Manager方法
class HighRatingManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(rating=1)


class Product(models.Model):
    # CHOICES选项
    RATING_CHOICES = (
        ("1", Very good),
        ("2", Good),
        ("3", Bad),
    )

    # 数据表字段
    name = models.CharField(name, max_length=30)
    rating = models.CharField(max_length=1, choices=RATING_CHOICES)


# MANAGERS方法
objects = models.Manager()
high_rating_products = HighRatingManager()


# META类选项
class Meta:
    verbose_name = product
    verbose_name_plural = products


# __str__方法
def __str__(self):
    return self.name


# 重写save方法
def save(self, *args, **kwargs):
    pass

# 定义绝对路径
def get_absolute_url(self):
    return reverse(product_details, kwargs={pk: self.id})


# 定义其它方法
def do_something(self):
    pass

 

以上是关于Models模型(下)的主要内容,如果未能解决你的问题,请参考以下文章

3相关数据模型(models)的创建

如何从django中具有@property装饰器的模型类序列化函数

片段的视图模型

Django-1.11中文文档-模型Models

机器学习算法之——隐马尔可夫模型(Hidden Markov Models,HMM) 代码实现

视图中的两个模型(使用 foreach)