django适当进阶篇

Django Form表单

django中的Form一般有两种功能:

  • 输入html

  • 验证用户输入

在项目中创建一个form文件


先写一个简单的forn:

1
2
3
4
5
6
7
from django import forms
from app01 import models
class BookForm(forms.Form):
    #数据库中要有对应的字段,如title
    title = forms.CharField(max_length=15)
 
    publication_date = forms.DateField()

再写一个对应的视图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def book_form(request):
    form = forms.BookForm()
    if request.method == 'POST':
        form = forms.BookForm(request.POST)
        if form.is_valid():
            form_data = form.cleaned_data #提取前端的数据
            form_data['publishers_id'] = request.POST.get('publisher_id')
            #保存数据
            book_obj = models.Book(**form_data)
            book_obj.save()
        else:
            #form的错误信息
            print(form.errors)
    publisher_list = models.Publisher.objects.all()
    return render(request,'book_form.html',{'book_form':form,
                                            'publishers':publisher_list})

最后写一个简单的模板:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="" method="post">{% csrf_token %}
    {{ book_form }}
    <select name="publisher_id">
        {% for publisher in publishers %}
            <option value="{{ publisher.id }}">{{ publisher.name }}</option>
        {% endfor %}
    </select>
    <input type="submit" value="创建图书">
</form>
 
</body>
</html>

  一个更复杂的实例:

form:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import re
from django import forms
from django.core.exceptions import ValidationError
 
 
def mobile_validate(value):
    mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
    if not mobile_re.match(value):
        raise ValidationError('手机号码格式错误')
 
 
class PublishForm(forms.Form):
 
    user_type_choice = (
        (0, u'普通用户'),
        (1, u'高级用户'),
    )
 
    user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,
                                                                  attrs={'class': "form-control"}))
 
    title = forms.CharField(max_length=20,
                            min_length=5,
                            error_messages={'required': u'标题不能为空',
                                            'min_length': u'标题最少为5个字符',
                                            'max_length': u'标题最多为20个字符'},
                            widget=forms.TextInput(attrs={'class': "form-control",
                                                          'placeholder': u'标题5-20个字符'}))
 
    memo = forms.CharField(required=False,
                           max_length=256,
                           widget=forms.widgets.Textarea(attrs={'class': "form-control no-radius", 'placeholder': u'详细描述', 'rows': 3}))
 
    phone = forms.CharField(validators=[mobile_validate, ],
                            error_messages={'required': u'手机不能为空'},
                            widget=forms.TextInput(attrs={'class': "form-control",
                                                          'placeholder': u'手机号码'}))
 
    email = forms.EmailField(required=False,
                            error_messages={'required': u'邮箱不能为空','invalid': u'邮箱格式错误'},
                            widget=forms.TextInput(attrs={'class': "form-control", 'placeholder': u'邮箱'}))
 
'''
def __init__(self, *args, **kwargs):
    super(SampleImportForm, self).__init__(*args, **kwargs)
 
    self.fields['idc'].widget.choices = models.IDC.objects.all().order_by('id').values_list('id','display')
    self.fields['business_unit'].widget.choices = models.BusinessUnit.objects.all().order_by('id').values_list('id','name')
 
Forms
'''

视图:

1
2
3
4
5
6
7
8
9
10
def test_form_view(request):
    if request.method == 'POST':
        request_form = PublishForm(request.POST)
        if request_form.is_valid():
            request_dict = request_form.clean()
            print(request_dict)
        return render(request,'test.html', {'pub_form':request_form})
    else:
        pub_form = PublishForm()
        return render(request,'test.html',{'pub_form':pub_form})

模板:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div>
    <form method="post" action="{% url 'test_form' %}">{% csrf_token %}
 
        <div>{{ pub_form.user_type }} {{ pub_form.errors.title }}</div>
        <div>{{ pub_form.title }}</div>
        <div>{{ pub_form.email }}</div>
        <div>{{ pub_form.phone }}</div>
        <div>{{ pub_form.memo }}</div>
 
 
        {% if pub_form.errors %}
            {{ pub_form.errors }}
        {% endif %}
        <input type="submit" value="提交">
    </form>
 
</div>

ModelForm

Form文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from django import forms
from app01 import models
class BookModelForm(forms.ModelForm):
 
    class Meta:   #写一个原类
 
        model = models.Book  #关联的表
 
        exclude = ()         #什么字段都显示
        #fields = ('titile')  #只显示title字段
        #添加样式
        widgets = {
            'title' : forms.TextInput(attrs={'class': 'form-control'}),
        }

对应的视图文件:

1
2
3
4
5
6
7
8
9
10
11
12
from django.shortcuts import render
from app01 import forms
from app01 import models
def book_modelform(request):
    form = forms.BookModelForm()
    if request.method == 'POST':
        form = forms.BookModelForm(request.POST)
        #表单验证
        if form.is_valid():
            #最牛逼的保存
            form.save()
    return render(request,'book_modelform.html',{'book_form':form,})

最后前端模板文件:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="/static/css/bootstrap.css" rel="stylesheet">
</head>
<body>
    <form action="" method="post" class="form-control"> {% csrf_token %}
{#        <div>#}  分开写
{#            {% for ele in book_form %}#}
{#                <div>{{ ele.name }}{{ ele }}{{ ele.errors }}</div>#}
{#            {% endfor %}#}
{#        </div>#}
        {{ book_form }} 
        <input type="submit" value="创建图书">
    </form>
    <script src="/static/js/jquery-2.2.3.js"></script>
</body>
</html>

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
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from django.contrib import admin
 
# Register your models here.
from app01 import models
def make_forbidden(modelAdmin,request,queryset):
    queryset.update(status='forbidden')
    make_forbidden.short_description = 'set to forbidden'
class BookAdmin(admin.ModelAdmin):
    #自定制admin
    list_display = ('id','title','publishers','publication_date','colored_status')
    #搜索
    search_fields = ('title','publishers__name') #publishers__name可以关联到另一个表
    #过滤
    list_filter = ('publishers','publication_date')
    #可编辑
    list_editable = ('title','publishers','publication_date')
    #分页
    list_per_page = 10
    filter_horizontal = ('authors',)
    raw_id_fields = ('publishers',)  
    #动作
    actions = [make_forbidden,]
admin.site.register(models.Author)
admin.site.register(models.Publisher)
admin.site.register(models.Book,BookAdmin)  #将上述类添加到这里

b、设置数据表名称

1
2
3
4
5
6
7
8
#models.py
class UserType(models.Model):
    name = models.CharField(max_length=50)
    
    class Meta:
        #修改前端显示名字
        verbose_name = '用户类型'
        verbose_name_plural = '用户类型'

Admin 定制Action:

1
2
3
4
5
6
7
from django.contrib import admin
 
# Register your models here.
from app01 import models
def make_forbidden(modelAdmin,request,queryset):
    queryset.update(status='forbidden')
    make_forbidden.short_description = 'set to forbidden'

其中queryset就是在前端选中的对象,在这个函数中可以对这个对象做操作。

1
2
3
class BookAdmin(admin.ModelAdmin):
   actions = [make_forbidden,]
admin.site.register(models.Book,BookAdmin)  #将上述类添加到这里

在类中添加action动作后就可以在前端找到set to forbidden动作,就可以将状态变成forbidden


将前端显示的状态加一个样式:

models中加入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from django.utils.html import format_html
class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    publishers = models.ForeignKey(Publisher)
    publication_date = models.DateField()
    status_choices = (('published',u'已出版'),
                      ('producing',u'待出版'),
                      ('forbidden',u'禁书'),
                      )
    status = models.CharField(choices=status_choices,max_length=32,default='producing')
    def __str__(self):
        return '<%s>' %(self.title)
    #给前端添加样式
    def colored_status(self):
        if self.status == "published":
            format_td =format_html('<span style="padding:2px;background-color:yellowgreen;color:white">已出版</span>')
        elif self.status == "producing":
            format_td =format_html('<span style="padding:2px;background-color:pink;color:white">待出版</span>')
        elif self.status == "forbidden":
            format_td =format_html('<span style="padding:2px;background-color:orange;color:white">禁书</span>')
 
        return  format_td
    #将前端显示的名字变成status
    colored_status.short_description = 'status'

在admin中添加一个status的字段:


前端显示效果如下:

常用ORM操作

一、一对多操作

models.py文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from django.db import models
 
# Create your models here.
 
class UserType(models.Model):
 
    caption = models.CharField(max_length=64)
 
    def __str__(self):
        return self.caption
class UserInfo(models.Model):
 
    user_type = models.ForeignKey(UserType)
    username = models.CharField(max_length=64)
    age = models.IntegerField()
 
    def __str__(self):
        return self.username

增加操作:

view中对user_type添加三条数据

1
2
3
4
5
6
7
8
9
10
11
12
from django.shortcuts import render,HttpResponse
from app01 import models
# Create your views here.
def user_type(request):
    dic = {'caption':'COO'}
    models.UserType.objects.create(**dic)
    return HttpResponse('ok')
 
def user_info(request):
 
 
    return HttpResponse('ok')


数据库中是外键的字段的字段名称是这样的:xxx_id


所以添加user_info的数据方式一如下:

1
2
3
4
def user_info(request):
    dic = {'username':'xx','age':'88','user_type_id':'1'}
    models.UserInfo.objects.create(**dic)
    return HttpResponse('ok')


方式二,通过对象添加:

1
2
3
4
5
dic = {'username':'hetan','age':'25','user_type':models.UserType.objects.get(id=1)}
    models.UserInfo.objects.create(**dic)
    result = models.UserInfo.objects.all()
    for item in result:
        print(item.username,item.age,item.user_type.caption)

其中item.user_type就代指了user_type表的对象,在通过.就可以调用caption属性了

其效果为



删除和修改同增加

查询操作:

正向查询:ForeignKey在哪个表中通过这个表查询两个表的关联数据就是正向查询

反向查询:和正向相反,通过没有ForeignKey那个表查询就是反向查询

实例1,需求:UserType为CEO的所有数据

通过UserInfo正向查询:

1
2
3
result = models.UserInfo.objects.filter(user_type__caption='CEO')
for item in result:
     print(item.username,item.age)


django的orm中的跨表查询要用到双下划线,例如上述代码中的user_type__caption,caption是另一张usertype表中的字段,从userinfo中


跨到usertype表中所以要写成user_type__caption。



通过UserType反向查询:

1
2
line = models.UserType.objects.get(id=1)
print(line.userinfo_set.all())


反向查询对象会有一个方法为另一张表名_set,这个方法就可以查询到另一张表的对象

还可以像这样:

1
2
line = models.UserType.objects.get(id=1)
    print(line.userinfo_set.filter(username='hetan'))



可以这样理解:

line.userinfo_set = model.UserInfo.objects.filter(user_type=line)

1
2
line = models.UserType.objects.get(userinfo__username='hetan')
print(line.userinfo_set.all().count())



二、多对多操作

表结构如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Host(models.Model):
 
 
    hostname= models.CharField(max_length=64)
    port = models.IntegerField()
    def __str__(self):
        return self.hostname
class HostAdmin(models.Model):
 
    username = models.CharField(max_length=32)
    email = models.CharField(max_length=32)
    host = models.ManyToManyField(Host)
    def __str__(self):
        return self.username

正向添加

1
2
3
4
5
6
7
8
models.Host.objects.create(hostname='c1',port=80)
    models.Host.objects.create(hostname='c2',port=80)
    models.Host.objects.create(hostname='c3',port=80)
     
    models.HostAdmin.objects.create(username='root',email='1@163.com')
    models.HostAdmin.objects.create(username='mysql',email='1@163.com')
    models.HostAdmin.objects.create(username='nginx',email='1@163.com')
    models.HostAdmin.objects.create(username='ssh',email='1@163.com')
1
2
3
admin_obj = models.HostAdmin.objects.get(username='root')
    host_list = models.Host.objects.filter(id__lt=3)
    admin_obj.host.add(*host_list)


反向添加

1
2
3
host_obj = models.Host.objects.get(id=3)
    admin_list = models.HostAdmin.objects.filter(id__gt=1)
    host_obj.hostadmin_set.add(*admin_list)


自定义第三张表

表结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Host1(models.Model):
 
 
    hostname= models.CharField(max_length=64)
    port = models.IntegerField()
    def __str__(self):
        return self.hostname
class HostAdmin1(models.Model):
 
    username = models.CharField(max_length=32)
    email = models.CharField(max_length=32)
    host = models.ManyToManyField(Host,through='HostRelation')
    def __str__(self):
        return self.username
class HostRelation(models.Model):
    c1 = models.ForeignKey(Host1)
    c2 = models.ForeignKey(HostAdmin1)

through='HostRelation'表示要自己定义第三张表,并且可以自定义添加字段

1
2
3
4
models.HostRelation.objects.create(
        c1_id=2,
        c2_id=1
    )

正向查询

1
2
admin_obj = models.HostAdmin.objects.get(id=1)
    print(admin_obj.host.all())

反向查询

1
2
host_obj = models.Host.objects.get(id=1)
    host_obj.hostadmin_set.all()

自定义方式查询

1
2
3
4
realtion_list = models.HostRelation.objects.all()
   for item in realtion_list:
       print(item.c1.hostname)
       print(item.c2.username)

三、select_related

用于优化查询,一次将Forigkey全部加载到内存

四、F

        需求:tb表中的age字段自加1

1
2
3
from django.db.models import F
models.tb.objects.all.update(age=F('age')+1)
sql语句 update tb set age=age+1;

五、Q

        作用:条件查询

        from django.db.models import Q

Q是可以嵌套的


其中hostname这个地方可以跨表操作或__gt/__contins等,和filter中的操作是一样的。

这里应该是con

1
models.Tb1.objects.filter(con)















来自为知笔记(Wiz)


posted on 2016-06-02 14:05  显卡  阅读(307)  评论(0编辑  收藏  举报

导航