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 importnow # 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模型(下)