python(Django之数据库操作一对多)

创建数据库表结构:

  

#资产管理表格属于的业务线
class Business(models.Model):
    #业务线字段(汉字类型)
    caption = models.CharField(max_length=64)


#资产管理
class Assets(models.Model):
    #把nid这一列设置为主键
    nid = models.AutoField(primary_key=True)
    #主机字段,创建索引
    hostname = models.CharField(max_length=64,db_index=True)
    #设置为IP字段,(原models.IPAddressField在python3上已经更改为models.GenericIPAddressField)
    #protocol='',有两个参数,ipv4地址,或ipv6.默认是both(两种都支持)
    ip = models.GenericIPAddressField(protocol="ipv4",db_index=True)
    #设置为端口字段。
    port = models.CharField(max_length=32)
  #创建关联关系,跟Busioness数据库的id列做关联关系。
  b = models.ForeignKey(to="Business",to_field="id")

 

生成数据库结构:

  

#找到这个项目的文件路径,并执行下面语句(也可以直接在pycharm里面的Terminal中执行)

python manage.py makemigrations

python manage.py migrate

 

那么我想半中腰想新加一个字段code怎么办?看下面

#资产管理表格属于的业务线
class Business(models.Model):
    #业务线字段(汉字类型)
    caption = models.CharField(max_length=64)
    #新加字段,null表示可以为空(null=True),或者设置默认写的是什么(default="Finance")
    code = models.CharField(max_length=64)


#资产管理
class Assets(models.Model):
    #把nid这一列设置为主键
    nid = models.AutoField(primary_key=True)
    #主机字段,创建索引
    hostname = models.CharField(max_length=64,db_index=True)
    #设置为IP字段,(原models.IPAddressField在python3上已经更改为models.GenericIPAddressField)
    #protocol='',有两个参数,ipv4地址,或ipv6.默认是both(两种都支持)
    ip = models.GenericIPAddressField(protocol="ipv4",db_index=True)
    #设置为端口字段。
    port = models.CharField(max_length=32)
  #创建关联关系,跟Busioness数据库的id列做关联关系。
b = models.ForeignKey(to="Business",to_field="id")

 

如果就简单的写上

code = models.CharField(max_length=64)

 

当执行数据库生成的时候肯定会提示你下面信息。

  它让你选择要不选择1,并设置你的新增字段的默认值(必须要用引号引起来),要不选择2退出。

  其实我们都不用这么麻烦,上面我也写清楚了。要不写null表示可以为空(null=True),要不写上让它默认是什么default="Finance"。

 

D:\Python上课及作业\day22hw>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
>>> "Finance"
Migrations for 'cmdb':
  cmdb\migrations\0003_business_code.py:
    - Add field code to business
D:\Python上课及作业\day22hw>python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, cmdb, contenttypes, sessions
Running migrations:
  Applying cmdb.0003_business_code... OK

 

结果:

 

 

数据库数据的三种查法:

  *使用上面的Business数据库

views中的写法:

def assets(request):
    now = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
    #QuerySet(查到的是QuerySet对象)
    v1 = models.Business.objects.all()
    #QuerySet(查到的是字典形式)
    v2 = models.Business.objects.values('id','caption','code')
    #QuerySet(查到的是元祖的形式)
    v3 = models.Business.objects.values_list('id','caption','code')
    return  render(request,'assets.html',{'nowdate':now,"v1":v1,'v2':v2,'v3':v3})

 

 

前端页面写法:

 <h1>业务线列表(对象)</h1>
    <ul>
        {% for row in v1 %}
                <p>{{ row.id }}--{{ row.caption }}--{{ row.code }}</p>
        {% endfor %}
    </ul>
    <br />
    <h1>业务线列表(字典)</h1>
    <ul>
        {% for row in v2 %}
                <p>{{ row.id }}--{{ row.caption }}--{{ row.code }}</p>
        {% endfor %}
    </ul>
    <h1>业务线列表(元祖)</h1>
    <ul>
        {% for row in v3 %}
                <p>{{ row.0 }}--{{ row.1 }}--{{ row.2 }}</p>
        {% endfor %}
    </ul>

 

  坑一:

#如果使用get方式,如果id=1不存在会报错。
v4 = models.Business.objects.get(id=1)

#如果使用下面的方法,就算没有id=1的数据,也不会报错。
v5 = models.Business.objects.filter(id=1).first()

 

 

 

一对多(增删改查)

   查询(对象)(一):

def assets(request):
    now = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
    #gt表示大于,lt表示小于。大于等于gte,小于等于lte,写法跟下面相同
    v4 = models.Assets.objects.filter(nid__gt=0)
    # v4 = models.Assets.objects.all()
    return  render(request,'assets.html',{'nowdate':now,'v4':v4})

 

  

  html文件(因为直接打印b字段的话,显示的是一个对象,所以使用的是row.b.关联关系表的字段名称)

    <h1>业务线列表</h1>
    <ul>
        {% for row in v4 %}
                <p>{{ row.id }}--{{ row.hostname }}--{{ row.ip }}--{{ row.port }}--{{ row.b_nid }}--{{ row.b.caption }}--{{ row.b.code }}</p>
        {% endfor %}
    </ul>

 

 

 

  查询(字典)(二):

  神奇的下划线(注意python程序里面取值跟html取值方式不一样)

 v5 = models.Assets.objects.values('nid','hostname','b_id','b__caption')
    for row in v5:
        print(row['nid'],row['hostname'],row['b_id'],row['b__caption'])

return  render(request,'assets.html',{'nowdate':now,'v5':v5})

 

  html:

    <h1>一对多查询(神奇的下划线)</h1>
    <ul>
        {% for row in v5 %}
                <p>{{ row.nid }}--{{ row.hostname }}--{{ row.b_id }}--{{ row.b__caption }}</p>
        {% endfor %}
    </ul>

 

  

  

 

  查询(元祖)(三):

  *注意

  我们用神奇的下划线从数据库中只取到自己数据库的nid和hostname字段及关联关系的b_id(也就是b,只是数据库根据关联关系给我们生成了b_id),b__caption是业务线(跨表查询)

  因为我们就从数据库里面查到了3个字段的数据,所以就是row[0-x]

    v5 = models.Assets.objects.values_list('nid','hostname','b_id','b__caption')
    for row in v5:
        print(row[0],row[1],row[2],row[3])
return  render(request,'assets.html',{'nowdate':now,'v5':v5})

 

 

  html:

    <h1>一对多查询((元祖)神奇的下划线)</h1>
    <ul>
        {% for row in v5 %}
                <p>{{ row.0 }}--{{ row.1 }}--{{ row.2 }}--{{ row.3 }}</p>
        {% endfor %}
    </ul>
    <br />

 

  增加:

    表结构:  

#资产管理表格属于的业务线
class Business(models.Model):
    #业务线字段(汉字类型)
    caption = models.CharField(max_length=64)
    #新加字段,null表示可以为空(null=True),或者设置默认写的是什么(default="Finance")
    code = models.CharField(max_length=64,null=True)


#资产管理
class Assets(models.Model):
    #把nid这一列设置为主键
    nid = models.AutoField(primary_key=True)
    #主机字段,创建索引
    hostname = models.CharField(max_length=64,db_index=True)
    #设置为IP字段,(原models.IPAddressField在python3上已经更改为models.GenericIPAddressField)
    #protocol='',有两个参数,ipv4地址,或ipv6.默认是both(两种都支持)
    ip = models.GenericIPAddressField(protocol="ipv4",db_index=True)
    #设置为端口字段。
    port = models.CharField(max_length=32)
    #创建关联关系,跟Busioness数据库的id列做关联关系。
    b = models.ForeignKey(to="Business",to_field="id")

 

 

  前端html文件: 

<form action="/cmdb/assets/" method="post">
                {% csrf_token %}
                <div>
                    <input type="text" placeholder="服务器名称" name="h">
                </div>
                <div>
                    <input type="text" placeholder="IP地址" name="ip">
                </div>
                <div>
                    <input type="text" placeholder="端口号" name="port">
                </div>
                <div>
                    <select name="b_id">
                        {% for row in v1 %}
                            <option value="{{ row.id }}">{{ row.caption }}</option>
                        {% endfor %}
                    </select>
                </div>
                <span><input type="submit" value="提交"></span>
                <span><input id = quxiao type="button" value="取消"></span>
            </form>

 

  

 

  views函数:

def assets(request):
    now = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
    if request.method == "GET":
        #QuerySet(查到的是QuerySet对象)
        v1 = models.Business.objects.all()
        #gt表示大于,lt表示小于。大于等于gte,小于等于lte,写法跟下面相同
        v2 = models.Assets.objects.filter(nid__gt=0)
        return  render(request,'assets.html',{'nowdate':now,"v1":v1,'v2':v2})
    elif request.method == "POST":
        n = request.POST.get('h')
        i = request.POST.get('ip')
        po = request.POST.get('port')
        bid = request.POST.get('b_id')
        try:
            #因为我们没做form表单验证,所以这里先用try一下
            #增加的时候涉及到跨表操作,我们知道ForeignKey这个字段关联了Business的id列(一一对应的关系)
            #所以我们只要拿到Business的id列的数字,并把它写入到b__id这列就行(神奇的下划线),减少了跨表操作。
            models.Assets.objects.create(hostname=n,ip=i,port=po,b_id=bid)
        except:
            error = "数据不能为空"
        return  redirect("/cmdb/assets")

 

posted @ 2017-01-15 15:54  Charles.L  阅读(700)  评论(0)    收藏  举报