python 自动化之路 day 20 Django进阶/BBS项目【一】
一、django进阶
1、django orm 增删改查
1.1、创建表:
1
2
3
|
>>> from blog.models import Blog >>> b = Blog(name = 'Beatles Blog' , tagline = 'All the latest Beatles news.' ) >>> b.save() |
This performs an INSERT
SQL statement behind the scenes. Django doesn’t hit the database until you explicitly call save()
.
The save()
method has no return value.
处理带外键关联或多对多关联的对象
ForeignKey的关联
1
2
3
4
5
|
>>> from blog.models import Entry >>> entry = Entry.objects.get(pk = 1 ) >>> cheese_blog = Blog.objects.get(name = "Cheddar Talk" ) >>> entry.blog = cheese_blog >>> entry.save() |
ManyToManyField关联
1
2
3
|
>>> from blog.models import Author >>> joe = Author.objects.create(name = "Joe" ) >>> entry.authors.add(joe) |
添加多个ManyToMany对象
1
2
3
4
5
|
>>> john = Author.objects.create(name = "John" ) >>> paul = Author.objects.create(name = "Paul" ) >>> george = Author.objects.create(name = "George" ) >>> ringo = Author.objects.create(name = "Ringo" ) >>> entry.authors.add(john, paul, george, ringo) |
1.2、查询
单表查询:
1 all_entries = Entry.objects.all() #查询所有 2 Entry.objects.filter(pub_date__year=2006) #查询所有pub_date为2006年的纪录 3 Entry.objects.all().filter(pub_date__year=2006) #与上面那句一样 4 >>> Entry.objects.filter( #链式查询 5 ... headline__startswith='What' 6 ... ).exclude( 7 ... pub_date__gte=datetime.date.today() 8 ... ).filter( 9 ... pub_date__gte=datetime(2005, 1, 30) 10 ... ) 11 12 one_entry = Entry.objects.get(pk=1) #单条查询 13 14 Entry.objects.all()[:5] #查询前5条 15 Entry.objects.all()[5:10] #你猜 16 17 Entry.objects.order_by('headline')[0] #按headline排序取第一条 18 19 Entry.objects.filter(pub_date__lte='2006-01-01') #相当于sql语句SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01'; 20 21 Entry.objects.get(headline__exact="Cat bites dog") #相当于SELECT ... WHERE headline = 'Cat bites dog'; 22 Blog.objects.get(name__iexact="beatles blog") #与上面相同,只是大小写不敏感 23 24 Entry.objects.get(headline__contains='Lennon') #相当 于SELECT ... WHERE headline LIKE '%Lennon%';
关联查询:
#This example retrieves all Entry objects with a Blog whose name is 'Beatles Blog': Entry.objects.filter(blog__name='Beatles Blog') Blog.objects.filter(entry__headline__contains='Lennon')
对同一表内不同的字段进行对比查询,In the examples given so far, we have constructed filters that compare the value of a model field with a constant. But what if you want to compare the value of a model field with another field on the same model?
Django provides F expressions
to allow such comparisons. Instances of F()
act as a reference to a model field within a query. These references can then be used in query filters to compare the values of two different fields on the same model instance.
For example, to find a list of all blog entries that have had more comments than pingbacks, we construct an F()
object to reference the pingback count, and use that F()
object in the query:
1
2
|
>>> from django.db.models import F >>> Entry.objects. filter (n_comments__gt = F( 'n_pingbacks' )) |
Django supports the use of addition, subtraction, multiplication, division, modulo, and power arithmetic with F()
objects, both with constants and with other F()
objects. To find all the blog entries with more than twice as many comments as pingbacks, we modify the query:
1
|
>>> Entry.objects. filter (n_comments__gt = F( 'n_pingbacks' ) * 2 ) |
To find all the entries where the rating of the entry is less than the sum of the pingback count and comment count, we would issue the query:
1
|
>>> Entry.objects. filter (rating__lt = F( 'n_comments' ) + F( 'n_pingbacks' )) |
For date and date/time fields, you can add or subtract a timedelta
object. The following would return all entries that were modified more than 3 days after they were published:
1
2
|
>>> from datetime import timedelta >>> Entry.objects. filter (mod_date__gt = F( 'pub_date' ) + timedelta(days = 3 )) |
更多复杂装逼的查询可以查看django文档。
1.3、更新
Updating multiple objects at once
1
2
|
# Update all the headlines with pub_date in 2007. Entry.objects. filter (pub_date__year = 2007 ).update(headline = 'Everything is the same' ) |
在原有数据的基础上批量自增
Calls to update can also use F expressions
to update one field based on the value of another field in the model. This is especially useful for incrementing counters based upon their current value. For example, to increment the pingback count for every entry in the blog:
1
|
>>> Entry.objects. all ().update(n_pingbacks = F( 'n_pingbacks' ) + 1 ) |
However, unlike F()
objects in filter and exclude clauses, you can’t introduce joins when you use F()
objects in an update – you can only reference fields local to the model being updated. If you attempt to introduce a join with an F()
object, a FieldError
will be raised:
1
2
|
# THIS WILL RAISE A FieldError >>> Entry.objects.update(headline = F( 'blog__name' )) |
1.4、聚合
https://docs.djangoproject.com/en/1.9/topics/db/aggregation/
2、django form
django中的Form一般有两种功能:
- 输入html
- 验证用户输入
表单验证
1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import re 4 from django import forms 5 from django.core.exceptions import ValidationError 6 7 8 def mobile_validate(value): 9 mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$') 10 if not mobile_re.match(value): 11 raise ValidationError('手机号码格式错误') 12 13 14 class PublishForm(forms.Form): 15 16 user_type_choice = ( 17 (0, u'普通用户'), 18 (1, u'高级用户'), 19 ) 20 21 user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice, 22 attrs={'class': "form-control"})) 23 24 title = forms.CharField(max_length=20, 25 min_length=5, 26 error_messages={'required': u'标题不能为空', 27 'min_length': u'标题最少为5个字符', 28 'max_length': u'标题最多为20个字符'}, 29 widget=forms.TextInput(attrs={'class': "form-control", 30 'placeholder': u'标题5-20个字符'})) 31 32 memo = forms.CharField(required=False, 33 max_length=256, 34 widget=forms.widgets.Textarea(attrs={'class': "form-control no-radius", 'placeholder': u'详细描述', 'rows': 3})) 35 36 phone = forms.CharField(validators=[mobile_validate, ], 37 error_messages={'required': u'手机不能为空'}, 38 widget=forms.TextInput(attrs={'class': "form-control", 39 'placeholder': u'手机号码'})) 40 41 email = forms.EmailField(required=False, 42 error_messages={'required': u'邮箱不能为空','invalid': u'邮箱格式错误'}, 43 widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'邮箱'}))
1 def publish(request): 2 ret = {'status': False, 'data': '', 'error': '', 'summary': ''} 3 if request.method == 'POST': 4 request_form = PublishForm(request.POST) 5 if request_form.is_valid(): 6 request_dict = request_form.clean() 7 print request_dict 8 ret['status'] = True 9 else: 10 error_msg = request_form.errors.as_json() 11 ret['error'] = json.loads(error_msg) 12 return HttpResponse(json.dumps(ret))
modelform验证
在使用Model和Form时,都需要对字段进行定义并指定类型,通过ModelForm则可以省去From中字段的定义
1 class AdminModelForm(forms.ModelForm): 2 3 class Meta: 4 model = models.Admin 5 #fields = '__all__' 6 fields = ('username', 'email') 7 8 widgets = { 9 'email' : forms.PasswordInput(attrs={'class':"alex"}), 10 }
3、django类视图
4、django admin配置
django amdin是django提供的一个后台管理页面,改管理页面提供完善的html和css,使得你在通过Model创建完数据库表之后,就可以对数据进行增删改查,而使用django admin 则需要以下步骤:
- 创建后台管理员
- 配置url
- 注册和配置django admin后台管理页面
1、创建后台管理员
1
|
python manage.py createsuperuser |
2、配置后台管理url
1
|
url(r '^admin/' , include(admin.site.urls)) |
3、注册和配置django admin 后台管理页面
a、在admin中执行如下配置
1
2
3
4
5
6
7
8
|
from django.contrib import admin from app01 import models admin.site.register(models.UserType) admin.site.register(models.UserInfo) admin.site.register(models.UserGroup) admin.site.register(models.Asset) |
b、设置数据表名称
1
2
3
4
5
6
|
class UserType(models.Model): name = models.CharField(max_length = 50 ) class Meta: verbose_name = '用户类型' verbose_name_plural = '用户类型' |
c、打开表之后,设定默认显示,需要在model中作如下配置
1
2
3
4
5
|
class UserType(models.Model): name = models.CharField(max_length = 50 ) def __unicode__( self ): return self .name |
1
2
3
4
5
6
7
8
9
10
11
12
|
from django.contrib import admin from app01 import models class UserInfoAdmin(admin.ModelAdmin): list_display = ( 'username' , 'password' , 'email' ) admin.site.register(models.UserType) admin.site.register(models.UserInfo,UserInfoAdmin) admin.site.register(models.UserGroup) admin.site.register(models.Asset) |
d、为数据表添加搜索功能
1
2
3
4
5
6
7
8
9
10
11
12
|
from django.contrib import admin from app01 import models class UserInfoAdmin(admin.ModelAdmin): list_display = ( 'username' , 'password' , 'email' ) search_fields = ( 'username' , 'email' ) admin.site.register(models.UserType) admin.site.register(models.UserInfo,UserInfoAdmin) admin.site.register(models.UserGroup) admin.site.register(models.Asset) |
e、添加快速过滤
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
from django.contrib import admin from app01 import models class UserInfoAdmin(admin.ModelAdmin): list_display = ( 'username' , 'password' , 'email' ) search_fields = ( 'username' , 'email' ) list_filter = ( 'username' , 'email' ) admin.site.register(models.UserType) admin.site.register(models.UserInfo,UserInfoAdmin) admin.site.register(models.UserGroup) admin.site.register(models.Asset) |
二、BBS项目
1、需求分析
- 整体参考“抽屉新热榜” + “虎嗅网”
- 实现不同论坛版块
- 帖子列表展示
- 帖子评论数、点赞数展示
- 允许登录用户发贴、评论、点赞
- 允许上传文件
- 帖子可被置顶
- 可进行多级评论
知识点:
- Django
- HTML\CSS\JS
- BootStrap
- Jquery
2、用户场景分析
游客(非登陆状态):可浏览所有文章
登陆状态:可浏览、可评论、可点赞
3、表结构设计
1 from django.db import models 2 from django.contrib.auth.models import User 3 4 # Create your models here. 5 6 7 8 class UserProifle(models.Model): 9 user = models.OneToOneField(User,null=True,default=None) 10 name = models.CharField(max_length=32) 11 12 def __str__(self): 13 return self.name 14 15 class Article(models.Model): 16 """文章表""" 17 title = models.CharField(max_length=128,unique=True) 18 author = models.ForeignKey("UserProifle") 19 category = models.ForeignKey("Category") 20 pub_date = models.DateTimeField(auto_now_add=True,auto_created=True) 21 tags = models.ManyToManyField("Tag", null=True) 22 body = models.TextField(max_length=100000) 23 head_img = models.ImageField(upload_to="uploads") 24 status_choices = ((0,'草稿'),(1,'发布'),(2,'隐藏')) 25 priority = models.SmallIntegerField(default=1000,verbose_name="优先级") 26 27 def __str__(self): 28 return self.title 29 30 class Category(models.Model): 31 """板块""" 32 name = models.CharField(max_length=64,unique=True) 33 set_as_top_menu = models.BooleanField(default=True) 34 35 def __str__(self): 36 return self.name 37 38 39 class Tag(models.Model): 40 """标签表""" 41 name = models.CharField(max_length=64, unique=True) 42 def __str__(self): 43 return self.name 44 45 class Comment(models.Model): 46 """评论""" 47 article = models.ForeignKey("Article") 48 p_node = models.ForeignKey("Comment",null=True,blank=True,related_name="my_child_comments") 49 50 user = models.ForeignKey("UserProifle") 51 date = models.DateTimeField(auto_now_add=True) 52 comment = models.TextField(max_length=1024) 53 54 55 def __str__(self): 56 return self.comment 57 58 class Like(models.Model): 59 """点赞""" 60 article = models.ForeignKey("Article") 61 user = models.ForeignKey("UserProifle") 62 date = models.DateTimeField(auto_now_add=True) 63 64 65 class PrivateMail(models.Model): 66 """私信""" 67 pass