django之admin&model
admin.py文件
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.contrib import admin
from . import models
# Register your models here.
class UserInfoAdmin(admin.ModelAdmin):
list_display = ('nid','username','password','nickname','email','avatar','create_time')
search_fields = ('username','nickname','email')
list_filter = ('create_time',)
# date_hierarchy = 'create_time'
# 添加负号表示降序 这里的优先级高于model里的Meta 这个ordering选项基本像模块中class Meta的ordering那样工作,除了它只用列表中的第一个字段名。
ordering = ('-nid',)
class UserFansAdmin(admin.ModelAdmin):
list_display = ('user','follow')
# 外键不显示为下拉框而显示为搜索框
raw_id_fields = ('user','follow')
class ArticleAdmin(admin.ModelAdmin):
# 多对多关系的tag不能再admin中显示
list_display = ('tittle', 'summary','read_count','comment_count','up_count','down_count','create_time','blog','category')
# 改变外键或一对一的添加方式
raw_id_fields = ('blog','category')
# 改变多对多的添加方式
filter_horizontal = ('tags',)
# 手动创建第三张表可以在这里注册然后在admin里看到第三张表,但是自动创建的第三张表,这里没法注册导致admin里看不到
admin.site.register(models.UserInfo, UserInfoAdmin)
admin.site.register(models.UserFans, UserFansAdmin)
admin.site.register(models.Blog, BlogAdmin)
admin.site.register(models.Article, ArticleAdmin)
admin.site.register(models.ArticleDetail,ArticleDetailAdmin)
admin.site.register(models.UpDown,UpDownAdmin)
admin.site.register(models.Comment,CommentAdmin)
admin.site.register(models.Tag, TagAdmin)
admin.site.register(models.Category, CategoryAdmin)
admin.site.register(models.Tpl,TplAdmin)
admin.site.register(models.Trouble,TroubleAdmin)
# admin.site.register(models.Article2Tag)
model文件
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models
# Create your models here.
class UserInfo(models.Model):
"""
用户表
"""
nid = models.BigAutoField(primary_key=True)
# verbose_name表示在admin中列表里显示的列名
username = models.CharField(verbose_name='用户名', max_length=32, unique=True)
password = models.CharField(verbose_name='密码', max_length=64)
nickname = models.CharField(verbose_name='昵称', max_length=32)
email = models.EmailField(verbose_name='邮箱', unique=True)
avatar = models.ImageField(verbose_name='头像', upload_to='static/imgs/avatar', null=True, blank=True)
create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
# 用户和用户之间是多对多的互粉关系
fans = models.ManyToManyField(
verbose_name='粉丝们',
to='UserInfo',#外键关联的是哪张表
through='UserFans',#自定义第三张表的表名
related_name='f',#反向查询时用的名称 默认_set
through_fields=('user', 'follow')#自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表
)
def __str__(self):
return self.username
class Meta:
#根据nid降序 nid相同再根据username升序
ordering = ['nid', 'username']
verbose_name = "用户表"
class UserFans(models.Model):
"""
手动创建的第三张关系表
互粉关系表,手动创建的第三张关系表 ,自己和自己关联
"""
user = models.ForeignKey(verbose_name='博主', to='UserInfo', to_field='nid', related_name='users', on_delete= models.CASCADE)
follow = models.ForeignKey(verbose_name='粉丝', to='UserInfo', to_field='nid',related_name='followers', on_delete= models.CASCADE)
class Meta:
# 联合唯一索引
unique_together = [
('user','follow')
]
verbose_name = "粉丝表"
class Blog(models.Model):
"""
博客信息
"""
nid = models.BigAutoField(primary_key=True)
tittle = models.CharField(verbose_name='博客标题', max_length=64)
site = models.CharField(verbose_name='博客地址前缀', max_length=32, unique=True)
theme = models.CharField(verbose_name='博客主题', max_length=32)
# 一个博客属于一个人
user = models.OneToOneField(verbose_name='所属人',to='UserInfo', to_field='nid', on_delete= models.CASCADE)
def __str__(self):
return self.tittle
class Meta:
verbose_name = "博客表"
class Category(models.Model):
"""
个人文章分类
"""
nid = models.AutoField(primary_key=True)
tittle = models.CharField(verbose_name='分类标题', max_length=32)
# 每个人的博客有多个不同类型的文章
blog = models.ForeignKey(verbose_name="所属博客", to='Blog', to_field='nid', on_delete= models.CASCADE)
def __str__(self):
return self.tittle
class Meta:
verbose_name = "个人文章分类表"
class Article(models.Model):
"""
文章表
"""
nid = models.BigAutoField(primary_key=True)
tittle = models.CharField(verbose_name='文章标题', max_length=128)
summary = models.CharField(verbose_name='文章简介', max_length=255)
read_count = models.IntegerField(verbose_name='阅读数', default=0)
comment_count = models.IntegerField(verbose_name='评论数', default=0)
up_count = models.IntegerField(verbose_name='点赞数', default=0)
down_count = models.IntegerField(verbose_name='踩数', default=0)
create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
# 一篇文章属于一个博客
blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid', on_delete= models.CASCADE)
# 一篇文章只属于一个类别
# null如果为True , Django在数据库中会将空值(empty)存储为NULL 。默认为False
# blank设置字段是否可以为空,默认为False(不允许为空)。
# null是数据库的范围,而blank是用于验证。如果一个字段的blank = True ,Django在进行表单数据验证时,会允许该字段是空值。如果字段的
# blank = False ,该字段就是必填的。
category = models.ForeignKey(verbose_name='文章类型', to='Category', to_field='nid', null=True, blank=True, on_delete= models.CASCADE)
type_choices = [
(1,'python'),
(2,'linux'),
(3,'java'),
(4,'php')
]
# 如果设置了choices, Django会显示选择框,而不是标准的文本框,而且这个选择框的选项就是choices中的元组。
# 每个元组中的第一个元素,是存储在数据库中的值;第二个元素是在管理界面或ModelChoiceField中用作显示的内容。在一个给定的
# model类的实例中,想得到某个choices字段的显示值,就调用a.get_type_choices_display(); a是文章对象
article_type_id = models.IntegerField(choices=type_choices, default=None,null=True,blank=True)
# 这里使用自动创建第三张表
tags = models.ManyToManyField(
to='Tag',
# through='Article22Tag',
# through_fields=('article','tag'),
)
def __str__(self):
return self.tittle
class Meta:
verbose_name = "文章表"
class ArticleDetail(models.Model):
"""
文章详情
"""
content = models.TextField(verbose_name='文章内容')
# 一篇文章详情属于一篇文章
# 手动创建第三张表可以在这里注册然后在admin里看到第三张表,但是自动创建的第三张表,admin里没法注册导致admin里看不到
article = models.OneToOneField(verbose_name='所属文章', to='Article', to_field='nid', on_delete= models.CASCADE)
def __str__(self):
return self.content
class Meta:
verbose_name = "文章详情表"
class UpDown(models.Model):
"""
文章踩或顶
"""
article = models.ForeignKey(verbose_name='文章', to='Article', to_field='nid', on_delete= models.CASCADE)
user = models.ForeignKey(verbose_name='踩或顶的用户', to='UserInfo', to_field='nid', on_delete= models.CASCADE)
up = models.BooleanField(verbose_name='是否赞')
def __str__(self):
return self.article
class Meta:
# 联合唯一索引
unique_together=[
('article','user'),
]
verbose_name = "文章顶踩表"
class Comment(models.Model):
"""
评论表
"""
nid = models.BigAutoField(primary_key=True)
content = models.CharField(verbose_name='评论内容', max_length=255)
create_time = models.DateTimeField(verbose_name='评论时间', auto_now_add=True)
# 一个评论对应一篇文章,一篇文章有多个评论
article = models.ForeignKey(verbose_name="评论文章", to='Article', to_field='nid', on_delete= models.CASCADE)
# 一个评论属于一个人,一个人可以给出多个评论
user = models.ForeignKey(verbose_name='评论者', to='UserInfo', to_field='nid', on_delete= models.CASCADE)
reply = models.ForeignKey(verbose_name='回复评论', to='Comment', related_name='back', null=True, blank=True, on_delete= models.CASCADE)
class Meta:
verbose_name = "评论表"
def __str__(self):
return self.content
class Tag(models.Model):
nid = models.AutoField(primary_key=True)
tittle = models.CharField(verbose_name='标签名称', max_length=32)
# 每个人的标签是独立的 一个人有多个标签
blog = models.ForeignKey(verbose_name='所属博客', to='Blog', to_field='nid',on_delete= models.CASCADE)
def __str__(self):
return self.tittle
class Meta:
verbose_name = "标签表"
# class Article2Tag(models.Model):
# article = models.ForeignKey(verbose_name='文章', to='Article', to_field='nid', on_delete= models.CASCADE)
# tag = models.ForeignKey(verbose_name='标题', to='Tag', to_field='nid', on_delete= models.CASCADE)
#
# class Meta:
# # 联合唯一索引
# unique_together=[
# ('article', 'tag')
# ]
# class Article22Tag(models.Model):
# article = models.ForeignKey(verbose_name='文章', to='Article', to_field='nid', on_delete= models.CASCADE)
# tag = models.ForeignKey(verbose_name='标题', to='Tag', to_field='nid', on_delete= models.CASCADE)
#
# class Meta:
# # 联合唯一索引
# unique_together=[
# ('article', 'tag')
# ]
class Tpl(models.Model):
tittle = models.CharField(max_length=32,verbose_name='标题')
content = models.TextField(verbose_name='内容')
def __str__(self):
return self.tittle
class Meta:
verbose_name = "问题表"
class Trouble(models.Model):
tittle = models.CharField(max_length=32,verbose_name='标题')
detail = models.TextField(verbose_name='详细情况')
user = models.ForeignKey(UserInfo,related_name='u', on_delete=models.CASCADE,verbose_name='来自用户')
ctime = models.DateTimeField(verbose_name='创建时间')
status_choices = (
(1,'未处理'),
(2,'处理中'),
(3,'已处理')
)
status = models.IntegerField(choices=status_choices,default=1,verbose_name='处理状态')
processer = models.ForeignKey(UserInfo,related_name='p',null=True,blank=True,on_delete=models.CASCADE,verbose_name='处理人')
solution = models.TextField(null=True,verbose_name='解决情况')
ptime = models.DateTimeField(null=True,verbose_name='解决时间')
pj_choice = (
(1,'不满意'),
(2,'一般'),
(3,'很好'),
)
pj = models.IntegerField(choices=pj_choice, null=True, default=2,verbose_name='评价')
def __str__(self):
return self.tittle
class Meta:
verbose_name = "问题详情表"
用safe过滤器为单独的变量关闭自动转意:
This will be escaped: {{ data }}
This will not be escaped: {{ data|safe }}
#结果
This will be escaped: <b>
This will not be escaped: <b>
为了控制模板的自动转意,用标签autoescape来包装整个模板(或者模板中常用的部分)
{% autoescape off %}
This will not be auto-escaped: {{ data }}.
Nor this: {{ other_data }}
{% autoescape on %}
Auto-escaping applies again: {{ name }}
{% endautoescape %}
{% endautoescape %}
auto-escaping 标签的作用域不仅可以影响到当前模板还可以通过include标签作用到其他标签,就像block标签一样。
# base.html
{% autoescape off %}
<h1>{% block title %}{% endblock %}</h1>
{% block content %}
{% endblock %}
{% endautoescape %}
# child.html
{% extends "base.html" %}
{% block title %}This & that{% endblock %}
{% block content %}{{ greeting }}{% endblock %}
Managers(针对整个表的方法,选出来的是某些满足条件的对象)
为Book模型定义了一个title_count()方法,它需要一个关键字,返回包含这个关键字的书的数量。
我们把BookManager()赋值给模型的objects属性。 它将取代模型的默认manager(objects)如果我们没有特别定义,它将会被自动创建。 我们把它命名为objects,这是为了与自动创建的manager保持一致。
# models.py
from django.db import models
# ... Author and Publisher models here ...
**class BookManager(models.Manager):**
**def title_count(self, keyword):**
**return self.filter(title__icontains=keyword).count()**
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()
num_pages = models.IntegerField(blank=True, null=True)
**objects = BookManager()**
def __unicode__(self):
return self.title
重写父类的方法(找某个作者的所有书)
注意我们明确地将objects设置成manager的实例,因为如果我们不这么做,那么唯一可用的manager就将是dah1_objects。
from django.db import models
**# First, define the Manager subclass.**
**class DahlBookManager(models.Manager):**
**def get_query_set(self):**
**return super(DahlBookManager, self).get_query_set().filter(author='Roald Dahl')**
**# Then hook it into the Book model explicitly.**
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=50)
# ...
**objects = models.Manager() # The default manager.**
**dahl_objects = DahlBookManager() # The Dahl-specific manager.**
同一模型中使用多个Manager
这个例子允许你执行Person.men.all() ,Person.women.all() ,Person.people.all() 查询,生成你想要的结果。
class MaleManager(models.Manager):
def get_query_set(self):
return super(MaleManager, self).get_query_set().filter(sex='M')
class FemaleManager(models.Manager):
def get_query_set(self):
return super(FemaleManager, self).get_query_set().filter(sex='F')
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
sex = models.CharField(max_length=1, choices=(('M', 'Male'), ('F', 'Female')))
people = models.Manager()
men = MaleManager()
women = FemaleManager()
模型方法(针对的是某个对象,查询的是对象的信息)
from django.contrib.localflavor.us.models import USStateField
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
birth_date = models.DateField()
address = models.CharField(max_length=100)
city = models.CharField(max_length=50)
state = USStateField() # Yes, this is U.S.-centric...
def baby_boomer_status(self):
"Returns the person's baby-boomer status."
import datetime
if datetime.date(1945, 8, 1) <= self.birth_date <= datetime.date(1964, 12, 31):
return "Baby boomer"
if self.birth_date < datetime.date(1945, 8, 1):
return "Pre-boomer"
return "Post-boomer"
def is_midwestern(self):
"Returns True if this person is from the Midwest."
return self.state in ('IL', 'WI', 'MI', 'IN', 'OH', 'IA', 'MO')
def _get_full_name(self):
"Returns the person's full name."
return u'%s %s' % (self.first_name, self.last_name)
#将方法赋给他的一个属性,调用时直接p.full_name而不是p.full_name()
full_name = property(_get_full_name)
使用方式
>>> p = Person.objects.get(first_name='Barack', last_name='Obama')
>>> p.birth_date
datetime.date(1961, 8, 4)
>>> p.baby_boomer_status()
'Baby boomer'
>>> p.is_midwestern()
True
>>> p.full_name # Note this isn't a method -- it's treated as an attribute
u'Barack Obama'
执行原生SQL
不要把你的视图代码和django.db.connection语句混杂在一起,把它们放在自定义模型或者自定义manager方法中是个不错的主意。
cursor.fetchone():将只取最上面的第一条结果,返回单个元组如(‘id‘,‘title‘),然后多次使用cursor.fetchone(),依次取得下一条结果,直到为空。
cursor.fetchall() :将返回所有结果,返回二维元组,如((‘id‘,‘title‘),(‘id‘,‘title‘)),
如果select本身取的时候只有一条数据时:
cursor.fetchone():将只返回一条结果,返回单个元组如(‘id‘,‘title‘)。
cursor.fetchall() :也将返回所有结果,返回二维元组,如((‘id‘,‘title‘),),
from django.db import connection, models
class PersonManager(models.Manager):
def first_names(self, last_name):
cursor = connection.cursor()
cursor.execute("""
SELECT DISTINCT first_name
FROM people_person
WHERE last_name = %s""", [last_name])
return [row[0] for row in cursor.fetchone()]
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
objects = PersonManager()

浙公网安备 33010602011771号