Django补充及初识Ajax

Django创建一对多表结构

首先现在models.py中写如下代码:

from django.db import models

# Create your models here.

class Business(models.Model):
    caption = models.CharField(max_length=32)



class Host(models.Model):
    nid = models.AutoField(primary_key=True)
    hostname = models.CharField(max_length=32,db_index=True)
    ip = models.GenericIPAddressField(db_index=True)
    port = models.IntegerField()
    b = models.ForeignKey(to="Business",to_field="id")

这里有几个知识点:

1、b = models.ForeignKey(to="Business",to_field="id")

这里的to参数是表示和那个表创建外键关系

to_field参数表示和表中那个字段创建外键关系,如果不指定to_filed,默认则是与主键建立外键关系

2、同时关于ip地址格式在新版本中是:GenericIPAddressField

3、db_index=True设置索引

然后执行python manage.py makemigrations以及python manage.py migrate就可以在数据库中创建出表结构

这里有个问题需要注意:

如果在创建表结构后,你在Business表中添加了数据,并且这个时候你需要在Business中添加一列新的字段的时候,如将创建Business表结构的类改成如下:

class Business(models.Model):
    caption = models.CharField(max_length=32)
    code = models.CharField(max_length=32)

这样就比之前增加了一列字段code

如果不做其他设置,执行python manage.py makemigrations,这个时候会提示如下:

D:\python培训\Django_zi_host>python manage.py makemigrations                                                                                                                                               
You are trying to add a non-nullable field 'code' to business without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
 2) Quit, and let me add a default in models.py
Select an option: 1
Please enter the default value now, as valid Python
The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now
Type 'exit' to exit this prompt
>>> "sa"
Migrations for 'app01':
  app01\migrations\0002_business_code.py:
    - Add field code to business

D:\python培训\Django_zi_host>python manage.py migrate   

因为你的表中在添加code字段之前已经有了数据,所以当添加新的字段的时候你需要对之前已经有数据的数据行进行设置,这里选择1表示给之前已经有数据的行设置一个默认值,这里我全部设置为sa

另外可以通过将类中code字段的代码进行修改如下:

code =models.CharField(max_length=32,null=True,default="SA")

这样设置就表示code字段可以为空,并且给这个字段设置了一个默认值为SA

获取数据库数据的三种方式

三种方式为:

models.Business.objects.all()

models.Business.objects.all().values("id","caption")

models.Business.objects.all().values_list("id","caption")

在views.py中写如下代码:

from django.shortcuts import render
from app01 import models
# Create your views here.

def business(request):
    v1 = models.Business.objects.all()

    v2 = models.Business.objects.all().values("id","caption")

    v3 = models.Business.objects.all().values_list("id","caption")
    return render(request,"business.html",{"v1":v1,"v2":v2,"v3":v3})

在urls.py中写如下代码:

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^business$', views.business),
]

url(r'^business$', views.business),通过$,可以防止如果还有:

url(r'^business_add/', views.business),匹配不到,这通过$符号,解决此类问题,如果没有$符号,就只会匹配上面的business,而不会匹配下面的bussiness_add

在business.html中写如下代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>业务线列表(对象)</h1>
    {{ v1 }}
    <ul>
        {% for row in v1 %}
            <li>{{ row.id }}-{{ row.caption }}-{{ row.code }}</li>

        {% endfor %}
    </ul>

    <h1>业务线列表(字典)</h1>
    {{ v2 }}
    <ul>
        {% for row in v2 %}
            <li>{{ row.id }}-{{ row.caption }}</li>

        {% endfor %}
    </ul>

    <h1>业务线列表(元组)</h1>
    {{ v3 }}
    <ul>
        {% for row in v3 %}
            <li>{{ row.0}}-{{ row.1 }}</li>

        {% endfor %}
    </ul>
</body>
</html>

查看运行结果如下:

可以看出v1和v2以及v3其实都是QuerySet类型

区别在于:

v1中是QuerySet中存着每行数据的对象

v2中是QuerySet中存着数据对应的字典

v3中是QuerySet中存着数据对应的元组

这也是objects.all()、objects.all().values()、objects.all().values_list()的区别

一对多的跨表操作的三种方式

其实我们在建立ForeignKey的时候代码中:

class Host(models.Model):
    nid = models.AutoField(primary_key=True)
    hostname = models.CharField(max_length=32,db_index=True)
    ip = models.GenericIPAddressField(db_index=True)
    port = models.IntegerField()
    b = models.ForeignKey(to="Business",to_field="id")

其实这个b就是另外一张表的Business表的对象,当我们在views.py中写host函数的时候,v1 = models.Host.objects.filter(nid__gt=0),这个时候我们可以知道v1是一个QuerySet,并且存着所有行数据的对象。

如果这个时候我们需要注意:如果我们通过for循环可以v1可以获得每行数据任意列的数据,但是这里host表中最后一列有点特殊

如果我们用如下代码:

 for row in v1:
         print(row.nid,row.hostname,row.port,row.ip,row.b_id,sep="\t")

我们知道数据库中host表的最后一别是b_id,所以我们可以通过row.b_id获得最后一列的值,我们也可以获取row.b,这样获取的就是一个对象,而这个对象就是Business表中一行数据的对象,同样的我们可以通过row.b.id、row.b.caption以及row.b.code,这就是跨表操作。

我们在views.py中添加如下代码:

def host(request):
    v1 = models.Host.objects.filter(nid__gt=0)
    return render(request,"host.html",{"v1":v1})

host.html代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>业务线列表</h1>
    <table border="1">
        <thead>
        <tr>
            <th>主机名</th>
            <th>IP</th>
            <th>端口</th>
            <th>业务线id</th>
        </tr>
        </thead>
        <tbody>
            {% for row in v1 %}
            <tr hid="{{ row.nid }}" bid="{{ row.b_id }}">
                <td>{{ row.hostname }}</td>
                <td>{{ row.ip }}</td>
                <td>{{ row.port }}</td>
                <td>{{ row.b.caption }}</td>
            </tr>
            {% endfor %}

        </tbody>
    </table>
</body>
</html>

这里有个小知识需要注意:对于用户id以及Bussines表的id、code我们并不需要在页面上显示,但是用户id以及Bussines表的id是唯一的,后面可能需要获取,所以将这两个值作为了tr标签的属性,而code则不是必须的。最终页面的效果如下:

同时这里有一种跨表操作的方式:

当我们在host函数中:

v2 = models.Host.objects.filter(nid__gt=0).values("nid","hostname","b_id","b__caption")

这里我们注意到跨表操作的时候用了b__caption,这里其实无法用b.caption来跨表获取数据,所以这是也是双下划线的一种用法

最终代码如下:

host函数的代码:

def host(request):
    v1 = models.Host.objects.filter(nid__gt=0)

    v2 = models.Host.objects.filter(nid__gt=0).values("nid","hostname","b_id","b__caption")

    v3 = models.Host.objects.filter(nid__gt=0).values_list("nid","hostname","b_id","b__caption")
    return render(request,"host.html",{"v1":v1,"v2":v2,"v3":v3})
host.html代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>主机列表(对象)</h1>
    {{ v1 }}
    <table border="1">
        <thead>
        <tr>
            <th>主机名</th>
            <th>IP</th>
            <th>端口</th>
            <th>业务线id</th>
        </tr>
        </thead>
        <tbody>
            {% for row in v1 %}
            <tr hid="{{ row.nid }}" bid="{{ row.b_id }}">
                <td>{{ row.hostname }}</td>
                <td>{{ row.ip }}</td>
                <td>{{ row.port }}</td>
                <td>{{ row.b.caption }}</td>
            </tr>
            {% endfor %}

        </tbody>
    </table>


    <h1>主机列表(字典)</h1>
     {{ v2 }}
    <table border="1">
        <thead>
        <tr>
            <th>主机名</th>
            <th>业务线id</th>
        </tr>
        </thead>
        <tbody>
            {% for row in v2 %}
            <tr hid="{{ row.nid }}" bid="{{ row.b_id }}">
                <td>{{ row.hostname }}</td>
                <td>{{ row.b__caption }}</td>
            </tr>
            {% endfor %}

        </tbody>
    </table>


    <h1>主机列表(元组)</h1>
     {{ v3 }}
       <table border="1">
           <thead>
           <tr>
               <th>主机名</th>
               <th>业务线id</th>
           </tr>
           </thead>
           <tbody>
               {% for row in v3 %}
               <tr hid="{{ row.0 }}" bid="{{ row.2 }}">
                   <td>{{ row.1 }}</td>
                   <td>{{ row.3 }}</td>
               </tr>
               {% endfor %}

           </tbody>
       </table>
</body>
</html>

效果如下:

这里有个小知识点:

如果想要在表单的最左侧有个序号列,方法如下:

在模板语言中只有有for循环,里面就会有一个forloop

如果想要有一个需要直接添加forloop.counter,就可以了

这里有几个参数:

forloop.counter :表示从1开始计数

forloop.counter0:表示从0开始计数

forloop.first:如果是第一个则会会True,否则为False

forloop.last:如果是最后一个则会为True,否则为False

forloop.revcounter:将序号从大到小,最小为1

forloop.revcounter0:将序号从大到小,最小为0

forloop.parentloop:记录外层循环的层数

初识Ajax

通过jQuery可以调用Ajax,方式如下:

$("#ajax_submit").click(function () {
                $.ajax({
                    url:"/test_ajax",
                    type:"POST",
                    data:{"hostname":$("#hostname").val(),"ip":$("#ip").val(),"port":$("#port").val(),"b_id":$("#sel").val()},
                    success: function(data) {
                        var obj = JSON.parse(data)
                    }
                })
            })

关于ajax参数的解释:

url:表示要传递数据的地址

type:表示传递的方式

data:表示要传递的数据

success:function{data}表示如果成功就会执行这个函数,这里的data是服务器返回的数据或者结果

这里JSON.parse将字典进行反序列化

一般情况,建议让服务器返回一个字典:

return HttpResponse(json.dumps(字典))

这里有个知识点需要注意:

$.ajax({
         data:$("#edit_form").serialize()
        })

data:$("#edit_form").serialize()这种方式就可以将form表单中的数据提交,而不用一个一个写了

Django创建多对多

这里有两种方式:

自定义关系表

代码例子如下:

class Business(models.Model):
    caption = models.CharField(max_length=32)
    code = models.CharField(max_length=32,null=True,default="SA")



class Host(models.Model):
    nid = models.AutoField(primary_key=True)
    hostname = models.CharField(max_length=32,db_index=True)
    ip = models.GenericIPAddressField(db_index=True)
    port = models.IntegerField()
    b = models.ForeignKey(to="Business",to_field="id")

class Application(models.Model):
    name = models.CharField(max_length=32)
class HostToApp(models.Model):
    hobj = models.ForeignKey(to="Host",to_field="nid")
    aobj = models.ForeignKey(to="Application",to_field="id")

自动创建关系表

代码例子如下:

class Host(models.Model):
    nid = models.AutoField(primary_key=True)
    hostname = models.CharField(max_length=32,db_index=True)
    ip = models.GenericIPAddressField(db_index=True)
    port = models.IntegerField()
    b = models.ForeignKey(to="Business",to_field="id")

class Application(models.Model):
    name = models.CharField(max_length=32)
    r = models.ManyToManyField("Host")

如果是通过自动创建的则无法直接对第三张表进行操作,可以间接操作

例子如下:

obj = Application.objects.get(id=1)

obj.r.add(1) :表示创建Application表的id=1和host表中的id=1创建一个对应关系

obj.r.add(2) :表示创建Application表的id=1和host表中的id=1创建一个对应关系

obj.r.add(1,2,3,4):表示增加多个对应关系

obj.r.add(*[1,2,3,4]):表示增加多个对应关系

obj.r.remove(*[1,2,3,4]):表示删除多个对应关系

obj.r.clear():这样会删除Application中id=1的对应关系都会给清空

obj.r.set([3,5,7]):这样表示重置,将原有的关系删除,然后只有和3,5,7的对应关系

obj.r.all():这里获得是所有相关的主机对象的“列表”即QuerySet

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏后端之路

生产环境频繁被自动退出

最近发现一个奇怪的现象,用户登录的时候总是提示 ? 本以为只是正常偶发,突然最近日志 check了一下登录请求发现如下 192.168.1.170 - - [...

22510
来自专栏Java帮帮-微信公众号-技术文章全总结

第三十天-加强2-多表查询&JDBC&连接池&DBUtils&综合案例【悟空教程】

第三十天-加强2-多表查询&JDBC&连接池&DBUtils&综合案例【悟空教程】

1074
来自专栏Bug生活2048

Spring Boot学习笔记(五)整合MyBatis实现数据库访问

这里主要依赖两个,一个是连接MySql的`mysql-connector-java`,还一个是SpringBoot整合MyBatis的核心依赖`mybatis-...

632
来自专栏https://www.cnblogs.com/L

【Linux篇】--awk的使用

awk是一个强大的文本分析工具。相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。 简单来说awk就是把文件逐行的读入,(空格...

1052
来自专栏施炯的IoT开发专栏

windows mobile窗口之间传递数据的方法

    在windows mobile上设计UI的时候,经常会碰到多个窗口的情况。有时候,我们需要将一个窗口中的用户输入信息反应到另一个窗口中去,这就涉及到窗口...

1829
来自专栏MasiMaro 的技术博文

PE文件解析器的编写(二)——PE文件头的解析

之前在学习PE文件格式的时候,是通过自己查看各个结构,自己一步步计算各个成员在结构中的偏移,然后在计算出其在文件中的偏移,从而找到各个结构的值,但是在使用C语言...

852
来自专栏大内老A

.NET Core采用的全新配置系统[7]: 将配置保存在数据库中

我们在《聊聊默认支持的各种配置源》和《深入了解三种针对文件(JSON、XML与INI)的配置源》对配置模型中默认提供的各种ConfigurationSource...

1898
来自专栏GreenLeaves

SQL学习之分组数据Group by

简介:"Group By"根据字面上的意思理解,就是根据"By"后面指定的规则对数据进行分组(分组就是将一个数据集按照"By"指定的规则分成若干个子数据集),然...

1655
来自专栏代码世界

Django-admin管理工具

1222
来自专栏Java帮帮-微信公众号-技术文章全总结

Web-第十三天 基础加强-JDBC高级开发事务【悟空教程】

insert into account values (null,'jack',10000);

702

扫码关注云+社区