• Django基础--3


    ORM

    django一对多的操作

    获取表单的三种方式:views

    获取对象            .all()      html中获取方式为 row.id,row,host

    获取字典            .all().values("字段","字段","字段",……)  row.id,row,host

    获取元祖            .all().values_list("字段","字段","字段",……) row.0,row.1

    #views
    
    from django.shortcuts import render
    from app import models
    # Create your views here.
    def home(request):
        v1 = models.Host.objects.all()
        print(v1)
        #<QuerySet [<Host: Host object (1)>, <Host: Host object (2)>, <Host: Host object (3)>]> 对象
        v2 = models.Host.objects.all().values("host","port")
        print(v2)
        #< QuerySet[{'host': 'a', 'port': 80}, {'host': 'b', 'port': 81}, {'host': 'c', 'port': 82}] >  字典类型
        v3 = models.Host.objects.all().values_list("host","port")
        print(v3)
        #<QuerySet [('a', 80), ('b', 81), ('c', 82)]>  元祖类型
        retur
    
    #html中
    
    <body>
        <h1>主机信息</h1>
        <ul>
            {% for row in v1 %}
                <li>{{ row.id }}--- {{ row.host }}--- {{ row.ip }}--- {{ row.port }}--- {{ row.dept_id }}</li>
            {% endfor %}
        </ul>
    
        <h1>主机信息</h1>
        <ul>
            {% for row in v2 %}
                <li>{{ row.host }}--- {{ row.port }}</li>
            {% endfor %}
        </ul>
    
        <h1>主机信息</h1>
        <ul>
            {% for row in v3 %}
                <li>{{ row.0 }}--- {{ row.1 }}</li>
            {% endfor %}
        </ul>
    </body>
    View Code

    一对多的跨表操作

    获取对象 filter(id__gte=1)

    #views
    
    def host(request):
        v1 = models.Host.objects.filter(id__gte=1)
        return render(request,"host.html",{"v1":v1})
    
    
    #urls.py
    
    
    from app import views
    path('host/', views.host),
    
    
    
    
    #host.html
    <body>
        <table border="1">
            <thead>
                <tr>
                    <th>id</th>
                    <th>主机名</th>
                    <th>主机ip</th>
                    <th>主机端口</th>
                    <th>业务线</th>
                    <th>部门</th>
                    <th>部门代码</th>
                </tr>
            </thead>
            <tbody>
                {% for row in v1 %}
                    <tr>
                        <td>{{ row.id }}</td>
                        <td>{{ row.host }}</td>
                        <td>{{ row.ip }}</td>
                        <td>{{ row.port }}</td>
                        <td>{{ row.dept_id }}</td>
                        <td>{{ row.dept.dept }}</td>
                        <td>{{ row.dept.dept_en }}</td>
                    </tr>
                {% endfor %}
            </tbody>
        </table>
    </body>
    View Code

    以上将所有的数据都显示出来了,然而实际中并用不到这么多,这里可以隐藏两个表的id,因每次都会循环tr,直接在<tr>中定义两个属性放id

    这里修改下tbody里面内容即可

    <tbody>
                {% for row in v1 %}
                    <tr hid = "{{ row.id }}" bid = "{{ row.dept.id }}">
                        <td>{{ row.host }}</td>
                        <td>{{ row.ip }}</td>
                        <td>{{ row.port }}</td>
                        <td>{{ row.dept.dept }}</td>
                    </tr>
                {% endfor %}
            </tbody>

    获取字典 filter(id__gte=1).values("id","ip", "port", "dept_id","dept__dept")

    #views.py
    
    #获取类型为字典
        v2 = models.Host.objects.filter(id__gte=1).values("id","ip", "port", "dept_id","dept__dept")
        #print(v2)
        # <QuerySet [{'ip': '1.1.1.1', 'host': 'a', 'dept__dept': '运维'}, {'ip': '1.1.1.2', 'host': 'b', 'dept__dept': '销售'}, {'ip': '1.1.1.3', 'host': 'c', 'dept__dept': '信息部'}]>
        for i in v2:
            print(i["id"],i["ip"],i["port"],i["dept__dept"])
      return render(request,"host.html",{"v2":v2})
    前端操作:
    
    <h2>业务线-字典</h2>
        <table border="1">
            <thead>
                <tr>
                    <th>主机ip</th>
                    <th>主机端口</th>
                    <th>部门</th>
                </tr>
            </thead>
            <tbody>
                {% for row in v2 %}
                    <tr hid = "{{ row.id }}" bid = "{{ row.dept_id }}">
                        <td>{{ row.ip }}</td>
                        <td>{{ row.port }}</td>
                        <td>{{ row.dept__dept }}</td>
                    </tr>
                {% endfor %}
            </tbody>
        </table>

    获取元祖  filter(id__gte=1).values_list("id","ip", "port", "dept_id","dept__dept")

    v3 =  models.Host.objects.filter(id__gte=1).values_list("id","ip", "port", "dept_id","dept__dept")
        for j in v3:
            print(j[0],j[1],j[2],j[3],j[4],)
        return render(request,"host.html",{"v3":v3})
    <h2>业务线-元祖</h2>
        <table border="1">
            <thead>
                <tr>
                    <th>主机ip</th>
                    <th>主机端口</th>
                    <th>部门</th>
                </tr>
            </thead>
            <tbody>
                {% for row in v3 %}
                    <tr hid = "{{ row.0 }}" bid = "{{ row.3 }}">
                        <td>{{ row.1 }}</td>
                        <td>{{ row.2 }}</td>
                        <td>{{ row.4}}</td>
                    </tr>
                {% endfor %}
            </tbody>
        </table>

     总结

    获取数据的3种方法中的第一种,页面中获取到的元素直接是对象,对对象用点就可以进行跨表
    另外的两种方法,获取到的不再是对象了,而是字典和元组。这时候取值要传字符串,要跨表就得在字符串中使用双下划线

    显示序号-for循环中的forloop

    在模板语言的for循环里还有一个forloop,通过这个可以取到到序号:

    • forloop.counter :序号,从1开始
    • forloop.counter0 :序号,从0开始
    • forloop.revcounter :序号,倒序,从1开始
    • forloop.revcounter0 :序号,倒序,从0开始
    • forloop.first :是否是第一个
    • forloop.last :是否是最后一个
    • forloop.parentloop :有嵌套循环的情况下,获取父类的以上6个值。字典的形式,可以继续通过点来取到具体的值
    <h2>forloop</h2>
        <table border="1">
            <thead>
                <tr>
                    <th>forloop.counter </th>
                    <th>forloop.counter0</th>
                    <th>forloop.revcounter</th>
                    <th>forloop.revcounter0</th>
                    <th>forloop.first</th>
                    <th>forloop.last</th>
                    <th>forloop.parentloop</th>
                    <th>主机ip</th>
                    <th>主机端口</th>
                    <th>部门</th>
                </tr>
            </thead>
            <tbody>
                {% for i in v3 %}
                    {% for row in v3 %}
                        <tr hid = "{{ row.0 }}" bid = "{{ row.3 }}">
                            <td>{{ forloop.counter }}</td>
                            <td>{{ forloop.counter0 }}</td>
                            <td>{{ forloop.revcounter }}</td>
                            <td>{{ forloop.revcounter0 }}</td>
                            <td>{{ forloop.first}}</td>
                            <td>{{ forloop.last}}</td>
                            <td>{{ forloop.parentloop}}</td>
                            <td>{{ row.1 }}</td>
                            <td>{{ row.2 }}</td>
                            <td>{{ row.4}}</td>
                        </tr>
                    {% endfor %}
                {% endfor %}
            </tbody>
        </table>

    上面使用了两层循环,是为了显示forloop.parentloop的效果,其他效果只用看上面三行就行,后面六行都是重复的内容

    下拉框-添加数据的示例

    添加静态文件到settings

    STATICFILES_DIRS = (
        os.path.join(BASE_DIR,"static"),
    )
    View Code

    host.html中

    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/commons.css" />
    </head>
    <body>
        <h2>业务线-对象</h2>
        <p>
            <input class="add" type="button" value="添加" />
        </p>
        <table border="1">
            <thead>
                <tr>
                    <th>序号</th>
                    <th>主机名</th>
                    <th>主机ip</th>
                    <th>主机端口</th>
                    <th>部门</th>
                </tr>
            </thead>
            <tbody>
                {% for row in v1 %}
                    <tr hid = "{{ row.id }}" bid = "{{ row.dept.id }}">
                        <td>{{ forloop.counter }}</td>
                        <td>{{ row.host }}</td>
                        <td>{{ row.ip }}</td>
                        <td>{{ row.port }}</td>
                        <td>{{ row.dept.dept }}</td>
                    </tr>
                {% endfor %}
            </tbody>
        </table>
        <div class="shade hide"></div>
        <div class="add-host hide">
            <form action="/host/" method="post">
                <p>
                    <input class="group" type="text"  name="host" placeholder="主机名"/>
                </p>
                <p>
                    <input class="group" type="text"  name="ip" placeholder="ip"/>
                </p>
                <p>
                    <input class="group" type="text"  name="port" placeholder="端口号"/>
                </p>
                <p>
                    <select name="dept_id">
                        {% for op in dept %}
                            <option value="{{ op.id }}">{{ op.dept }}</option>
                        {% endfor %}
                    </select>
                </p>
                <p>
                    <input type="submit" value="提交" />
                    <input class="cancel" type="button" value="取消" />
                </p>
            </form>
        </div>
    
        <script src="/static/jquery-3.2.1.min.js"></script>
        <script src="/static/js.js"></script>
    </body>
    View Code

    static中的css和js

    #commons.css
    
    .hide{
        display: none;
    }
    .shade {
        position: fixed;
        left: 0;
        top: 0;
        right: 0;
        bottom: 0;
        background: black;
        opacity: 0.6;
        z-index: 100;
    }
    .add-host {
         500px;
        height: 400px;
        position: fixed;
        left: 50%;
        top: 200px;
        background: white;
        z-index: 101;
        margin-left: -300px;
        text-align: center;
    
    }
    
    #js.js
    
    $(function () {
        $(".add").click(function () {
            $(".shade,.add-host").removeClass("hide")
        })
        $(".cancel").click(function () {
            $(".shade,.add-host").addClass("hide")
        })
    })
    View Code

    views.py

    def host(request):
        if request.method == "GET":
            v1 = models.Host.objects.filter(id__gte=1)
            v2 = models.Host.objects.filter(id__gte=1).values("id","ip", "port", "dept_id","dept__dept")
            v3 =  models.Host.objects.filter(id__gte=1).values_list("id","ip", "port", "dept_id","dept__dept")
            dept = models.Bussines.objects.all()
            return render(request,"host.html",{"v1":v1,"v2":v2,"v3":v3,"dept":dept})
        elif request.method == "POST":
            h = request.POST.get("host")
            i = request.POST.get("ip")
            p = request.POST.get("port")
            d = request.POST.get("dept_id")
            models.Host.objects.create(host = h,ip = i,port = p,dept_id = d)
            return redirect("/host/")  //这里重新获取get请求,从而刷新页面

    AJAX

    数据验证

    这里是在后台验证

    模态对话框里提交表单的页面增加一个按钮,然后在jQuery里绑定事件

    下面为绑定的事件

    $(".ajax").click(function () {
            $.ajax({
                url:"/test/",
                type:"POST",
                data:{
                    "host":$("#host").val(),
                    "ip":$("#ip").val(),
                    "port":$("#port").val(),
                    "dept_id":$("#sel").val()},
                success:function (data) {
                    if (data == "OK"){
                        location.reload()
                    }
                    else {
                        alert(data)
                        location.reload()
                    }
                }
            })
        })

    htm中添加一个按钮

    在上个实例中只添加一个按钮
    
    <p>
                    <input type="submit" value="提交" />
                    <input class="ajax" type="button" value="Ajax提交方式" />
                    <input class="cancel" type="button" value="取消" />
                </p>
    View Code

    urls.py中修改

    path('host/', views.host),
        path('test/', views.test),
    View Code

    views.py在上面的实例中只添加

    def test(request):
        h = request.POST.get("host")
        i = request.POST.get("ip")
        p = request.POST.get("port")
        d = request.POST.get("dept_id")
        if h and len(h) > 5:
            models.Host.objects.create(host=h, ip=i, port=p, dept_id=d)
            return HttpResponse("OK")
        else:
            return HttpResponse("太短了") 

    优化验证

    上面的验证只是个很简单的验证,还没考虑类型是否满足数据库的要求。如果数据不符合数据库的数据格式,例如将端口号填写为字符串,此时程序就会报错,报错系统并不会崩溃,我们调试的时候可以看到错误信息,但是客户端是不知道发生了什么的。

    下面就通过try来捕获异常,之后可以返回自定义的消息内容,或者也可以把异常信息返回

    def test(request):
        import json
        dic = {"static":True,"error":None,"data":None}
        try:
            h = request.POST.get("host")
            i = request.POST.get("ip")
            p = request.POST.get("port")
            d = request.POST.get("dept_id")
            if h and len(h) > 5:
                models.Host.objects.create(host=h, ip=i, port=p, dept_id=d)
            else:
                dic["static"] = False
                dic["error"] = "太短了……"
        except Exception as e:
            dic["static"] = False
            dic["error"] = "请求错误……"
        return HttpResponse(json.dumps(dic))

    上面返回都用HttpResponse()方式返回,并且返回的最好都是一个字典形式的

    在提交按钮后面添加个span标签,用来提示用户,提示信息由后台提供

    <p>
                    <input type="submit" value="提交" />
                    <input class="ajax" type="button" value="Ajax提交方式" />
                    <input class="cancel" type="button" value="取消" />
                    <span class=error style="color: red"></span>
                </p>

    在AJAX验证中,修改下上个例子的判断

    $(".ajax").click(function () {
            $.ajax({
                url:"/test/",
                type:"POST",
                data:{
                    "host":$("#host").val(),
                    "ip":$("#ip").val(),
                    "port":$("#port").val(),
                    "dept_id":$("#sel").val()},
                success:function (data) {
    //data是服务器发送过来的数据,就是HttpResponse中的内容
    //将字符串转为对象:字典 var data = JSON.parse(data) if (data.static){ location.reload() } else { $(".error").text(data.error) } } }) })

    序列化返回的消息(JSON)

    HttpResponse返回的内容是字符串,使用JSON序列化字符串,就可以返回更多的信息了,并且客户端处理起来也很方便。上面的例子已经这么做了。

    1.先导入json模块

    2.然后序列化字典    :   return HttpResponse(json.dumps(dic))

    3.在jQ中处理字符串:使用 JSON.parse()  将字符串转为对象           var data = JSON.parse(data)

    4.在jQ中可以直接使用data.key名   获取到值

    示例-编辑功能

    编辑页面和添加页面内容基本相同,只要把上面的添加复制过来稍加修改即可,样式用一样就行

    <div class="edit-form hide">
            <form action="/host/" method="post" hid = "" >
                <p>
                    <input type="text" name="id" style="display: none"  />
                </p>
                <p>
                    <input type="text" name="host" placeholder="主机名"/>
                </p>
                <p>
                    <input type="text" name="ip"  placeholder="ip"/>
                </p>
                <p>
                    <input type="text"  name="port" placeholder="端口号"/>
                </p>
                <p>
                    <select  name="dept_id">
                        {% for op in dept %}
                            <option value="{{ op.id }}">{{ op.dept }}</option>
                        {% endfor %}
                    </select>
                </p>
                <p>
                    <input class="ajax" type="button" value="编辑" />
                    <input class="cancel" type="button" value="取消" />
                </p>
            </form>
        </div>

    然后就是处理函数了

    
    
    $(".edit").click(function () {
    $(".shade,.edit-form").removeClass("hide");
    //获取部门id
    var bid = $(this).parent().parent().attr("bid");
    //获取主机id
    var hid = $(this).parent().parent().attr("hid");
    $(".edit-form").find("select").val(bid);
    $(".edit-form").find("input[name = 'id']").val(hid);
    //获取编辑框中的值
    var obj = $(this).parent().siblings("td").first();
    //将表格中的值循环填入编辑框
    $(".edit-form :text").each(function () {
    $(this).val(obj.text());
    obj = obj.next();
    });
    });
    $(".ajax1").click(function () {
    $.ajax({
    url:"/edit/",
    type:"POST",
    //将edit-form表单的值打包发送到后台
    data:$(".edit_form").serialize(),
    success:function (data) {
    //将字符串转为对象:字典
    var data = JSON.parse(data)
    console.log(data.static)
    if (data.static){
    location.reload()
    }
    else {
    $(".error").text(data.error)
    }
    }
    });

    });
    $(".cancel").click(function () {
    $(".shade,.edit-form").addClass("hide")
    });
     

    点击编辑按钮,之后去掉隐藏的样式

    因为是编辑,因此要获取到当前点击的hid和nid,这里可以通过点击编辑按钮是获取,因为在tr标签我们设置了hid和nid

    然后添加一个带id的输入框,默认肯定是不能让用户修改的,隐藏把该标签隐藏掉

    然后是下拉框,进入编辑页面,默认是要显示当前的部门的,这里可以通过bid来修改值,使其显示相应的部门

    在使用Ajax时,我们有更简单的方式获取form表单的内容,就是使用serialize(),他可以将form表单的内容都打包一起

    然后我们使用Ajax发送到后台

    data:$(".edit-form").serialize(),

    后台获取数据后处理如下

    def edit(request):
        dic = {"static": True, "error": None, "data": None}
        try:
            id = request.POST.get("id")
            edit_data = {
                'host':request.POST.get("host"),
                'ip':request.POST.get("ip"),
                'port':request.POST.get("port"),
                'dept_id':request.POST.get("dept_id"),
            }
            for i ,j in edit_data.items():
                if j:
                    models.Host.objects.filter(id = id).update(**edit_data)
                else:
                    dic["static"] = False
                    dic["error"] = "内容错误……"
        except Exception as e:
            dic["static"] = False
            dic["error"] = "内容错误……"
        return HttpResponse(json.dumps(dic))

    url中添加

     path('edit/', views.edit),

    示例-删除功能

    上面的例子中已经添加了删除按钮,这里就不用改html了

    只需要在js中处理点击删除按钮的操作

    $('.delete').click(function () {
            var hid = $(this).parent().parent().attr('hid')
            $.ajax({
                url:"/delete/",
                type:"POST",
                //将edit-form表单的值打包发送到后台
                data:{"hid":hid},
                success:function (data) {
                    //将字符串转为对象:字典
                    var data = JSON.parse(data)
                    console.log(data.static)
                    if (data.static){
                        location.reload()
                    }
                    else {
                        $(".error").text(data.error)
                    }
                }
            })
        });

    先获取hid,然后将hid传给后台

    在urls中添加

    path('delete/', views.delete),

    后台处理如下

    def delete(request):
        dic = {"static": True, "error": None, "data": None}
        try:
            id = request.POST.get("hid")
            if id:
                models.Host.objects.filter(id=id).delete()
            else:
                dic["static"] = False
                dic["error"] = "内容错误……"
        except Exception as e:
            dic["static"] = False
            dic["error"] = "内容错误……"
        return HttpResponse(json.dumps(dic))

    获取到nid,根据nid查找数据库相应的对象,删除掉

    外键操作-多对多

    多对多关系表的创建--两种方式

    一般两种方式都用,自定义方式可以关联多个信息,自动创建的关联表只有三个属性:第三张表的id,host表的id,应用表的id

    创建应用对应主机的关系表,一个应用可以属于多台主机,一个主机可以多个应用

    先创建一个应用表

    class Apply(models.Model):
        name = models.CharField(max_length=32)

    然后创建主机和应用的关联表

    1.自定义关系表

     class Host_to_apply(models.Model):
         hobj = models.ForeignKey(Host,to_field='id',on_delete=models.CASCADE)
         aobj = models.ForeignKey(Apply,to_field='id',on_delete=models.CASCADE)

    2.自动创建关系表

    通过创建应用表时自动创建

    class Apply(models.Model):
        name = models.CharField(max_length=32)
        #  第二种方式
        r = models.ManyToManyField('Host')

    自动创建只能帮我们创建一张3个字段的表:自增id,关联表的主键,被关联表的主键。如果想加额外的数据就只能用自定义关系表来创建额外的字段了。

    设置关联关系

    ORM都是通过类来进行数据库操作的。自定义关系表,直接可以获得结合表的类,直接操作结合表就可以进行数据库操作了

    Host_to_apply.objects.create(aobj_id=1, hobj_id=1)

    对于自动创建关联关系表,由于并没有结合表的类,无法直接对结合表进行操作。这里可以获取到对象,比如客户表id=1的那条数据对象,使用提供的方法对这个对象的关联系进行操作,添加、删除、清除、设置。

    obj = Apply.objects.get(id=1)  # 先获取到一个对象,下面都是对id=1的关联关系进行操作
    obj.r.add(1)  # 添加一个关系
    obj.r.add(2, 3, 4)  # 多个参数添加多个关系
    obj.r.add(*[2, 3, 4])  # 通过列表添加多个关系
    obj.r.remove(1)  # 删除一个关系,同样支持多个参数或列表
    obj.r.clear()  # 清除这个id的所有的关系
    obj.r.set([3, 5, 7])  # 设置关系。这个id的其他关系都会清除,最后只有这个列表中的关系。相当于先清除在添加。这里没星号

    上面没有获取的方法,获取的方法和之前获取数据的方法一样。models.Apply.objects 后面能使用什么方法,这里的obj就可以使用什么方法。比如:.all() 所有被关联的表的对象。all() 方法获取到的一定是一个QuerySet对象,在这里里面的每个元素是一个被关联的表 Apply 的对象。

    多对多实例

    应用到:查询,添加

     apply.html中

    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="/static/commons.css" />
    </head>
    <body>
        <h2>应用列表</h2>
        <p>
            <input class="add" type="button" value="添加" />
        </p>
        <table border="1">
            <thead>
                <tr>
                    <th>应用名称</th>
                    <th>应用主机名称</th>
                </tr>
            </thead>
            <tbody>
                {% for row in apply_list %}
                    <tr aid = "{{ row.id }}" >
                        <td>{{ row.name }}</td>
                        <td>
                            {% for i in row.r.all %}
                                <span class="td">{{i.host}}</span>
                            {% endfor %}
                        </td>
                    </tr>
    
                {% endfor %}
            </tbody>
        </table>
        <div class="shade hide"></div>
        <div class="add-host hide">
            <form action="/apply/" method="post">
                <p>
                    <input id="name" class="group" type="text"  name="name" placeholder="应用名称"/>
                </p>
                <p>
                    <select id="apply_name" name="apply_name" multiple>
                        {% for op in host_list %}
                            <option value="{{ op.id }}">{{ op.host }}</option>
                        {% endfor %}
                    </select>
                </p>
                <p>
                    <input class="ajax2" type="button" value="Ajax提交" />
                    <input class="cancel" type="button" value="取消" />
                    <span class=error style="color: red"></span>
                </p>
            </form>
        </div>
    
        <script src="/static/jquery-3.2.1.min.js"></script>
        <script src="/static/js.js"></script>
    </body>
    View Code

    URLS.py中添加

    path('apply/', views.apply),
    View Code

    js中添加

    
    
    $(".add").click(function () {
    $(".shade,.add-host").removeClass("hide")
    });

    $(".ajax2").click(function () {
    $.ajax({
    url:"/apply/",
    type:"POST",
    data:$(this).parent().parent().serialize(),
    //data是服务器发送过来的数据,就是HttpResponse中的内容
    datatype:JSON,//这里用jq获取就转为对象,下面就不需要在使用JSON.parse(data)
    success:function (data) {
    //将字符串转为对象:字典
    if (data.static){
    location.reload()
    }
    else {
    $(".error").text(data.error)
    }
    },
    error:function () {
    //用来处理
    }
    });
    });
    $(".cancel").click(function () {
    $(".shade,.add-host").addClass("hide")
    });
    datatype:JSON,//这里用jq获取就转为对象,下面就不需要在使用JSON.parse(data)

    views.py

    def apply(request):
        if request.method == 'GET':
            apply_list = models.Apply.objects.all()
            host_list = models.Host.objects.all()
            # for i in apply_list:
            #     print(i.name,i.r.all())
            return render(request, "apply.html", {'apply_list': apply_list, 'host_list': host_list})
        elif request.method == 'POST':
            dic = {"static": True, "error": None, "data": None}
            try:
                name = request.POST.get("name")
                host_list = request.POST.getlist('apply_name')
                if name:
                    obj = models.Apply.objects.create(name = name)
                    obj.r.add(*host_list)
                else:
                    dic["static"] = False
                    dic["error"] = "内容错误……"
            except Exception as e:
                dic["static"] = False
                dic["error"] = "内容错误……"
                print(e)
            return HttpResponse(json.dumps(dic))
  • 相关阅读:
    每天一个linux命令(57):ss命令
    [原][osg][osgearth]我眼中的osgearth
    [osg]osgDB的加载机制,使用3DS插件做参考(转,整理现有osgDB资料)
    [原][osgearth]osgearthviewer读取earth文件,代码解析(earth文件读取的一帧)
    [原][译][osgearth]Model Source Drivers模型驱动源(OE官方文档翻译)
    [原][译][osgearth]样式表style中参数总结(OE官方文档翻译)
    [原][osgearth]API加载earth文件的解析
    [原][译][osgearth]API加载地球(OE官方文档翻译)
    [osgearth]Earth文件详解
    [osgearth]通过API创建一个earth模型
  • 原文地址:https://www.cnblogs.com/Aline2/p/10189863.html
Copyright © 2020-2023  润新知