Django基础学习笔记

时间:2022-09-26 19:15:50

开始

1.创建项目:

django-admin startproject mysite 

2.创建app

cd mysite
python manage.py startapp cmdb

3.运行

python manage.py runserver 

目录结构与用途

mysite
    - mysite  项目配置
        - __init__
        - settings  配置文件
        - url       url路由配置
        - wsgi      遵循wsgi规范,上线uwsgi+nginx
        - manage.py     管理Django程序

    app:
        - migrations 数据库表结构修改记录
        - admin Django为我们的app程序自动创建的后台管理
        - apps 对当前app的配置
        - models 数据库orm,写指定的class,通过命令创建数据库结构
        - tests 单元测试
        - views app相关的所有业务,业务逻辑

配置

1.使用模板文件

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],   ##新加
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

2.静态文件配置

STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)
# TEMPLATE_DIRS = (os.path.join(BASE_DIR,  'templates'),)

3.暂时停止POST跨站请求伪造


MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    #'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

路由规则设定

  • FBV
from cmdb import views  # 在app中导入视图函数
 # Django会默认添加/,此处url路由写的什么,html的form表单中action也必须相同
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login', views.login),  
    url(r'^home', views.home),
]
  • CBV
from mytest import views
 
urlpatterns = [
    url(r‘^index/‘, views.Index.as_view()),
]

views视图函数:

  • 形参:request client发送过来的各种信息
request.POST 
request.GET
request.methed 为POST或者GET
  • 值获取举例
 # 单个值
request.POST.get("key",None) 
request.GET.get("key",None)

 # 多个值,返回一个list
request.GET.getlist("key",None)
request.POST.getlist("key",None)

视图函数返回

  • 页面返回
  1. render 返回一个完整的html页面
  2. HttpResponse 返回字符串
  3. redirect 重定向,跳转动作不是在后台做的,不能写html模板路径
  • 返回举例
return render(request, 'login.html', {"error_msg": error_msg})  模板中通过key来获取,返回必须为一个字典,字典简直对适量不限制
return redirect("http://www.baidu.com")  # 重定向
return redirect("/home")  # 重定向
return HttpResponse("string")

模板渲染:

  • 循环
    {% for row in user_list %} 
        <tr>
            <td>{{ row.username }}</td>  获得字典key对应的值
            <td>{{ row.gender }}</td>
            <td>{{ row.email }}</td>
        </tr>
    {% endfor %}
  • 值获取:索引
eg:
    return render(request, 'login.html', {"info": "Leon","user_list":[1,2,3,4,5],"user_dict":{"k1":"v1","k2":"v2"},}) 

列表或字典获取值:
    {{ user_list.0 }}
    {{ user_list.1 }}
    {{ user_dict.k1 }}
    {{ user_dict.k2 }}
  • 条件判断
    {% if info %}
        {% if user_list.0 > 18 %}
            <a>old</a>
        {% else %}
            <a>young</a>    
        {% endif %}
        <a>用户为:info</a>
    {% else %}  
        <a>用户为空</a>
    {% endif %}

html数据提交

1. 单选框,name相同,value不同,才可以区分开,单个值用get可以获取
2. 复选框,name相同,value不同,多个用getlist获取,得到一个列表
3. select,select只有一个name,option中的value不同,多选在select中设定:multiple="multiple",后端依然使用getlist获取


4. 文件上传 :

前端:form表单中新增属性:enctype=“multipart/form-data”
后端:使用 obj = request.FILES,get(name) 来获取文件数据句柄
    import os
    file_path = os.path.join('upload',obj.name)
    f = open(file_path,mode='wb')
    for i in obj.chunks():
        f.write(i)
    f.close()

FBV和CBV

  • urls中的区别在上面
  • 视图函数写法:
from django.views import View
 
class Index(View):  # 必须继承View

    # 链接进来首先调用的是dispatch方法
    def dispatch(self, request, *args, **kwargs):  # dispatch使用了类似反射的方法,来区分get、post
        # 调用父类中的dispatch
        print(‘before‘)  # 类似装饰器的功能
        result = super(Home,self).dispatch(request, *args, **kwargs)
        print(‘after‘)  # 类似装饰器的功能
        return result

    def get(self, req):
        print(‘method is :‘ + req.method)
        return render(req, ‘index.html‘)
 
    def post(self, req):
        print(‘method is :‘ + req.method)
        return render(req, ‘index.html‘)

路由系统url

1. 基本设定

url(r'^index/', views.index),   # FBV
url(r'^home/', views.Home.as_view()), CBV

2. 正则匹配之无指定参数

url(r'^detail-(\d+).html', views.detail), 

# 举例
url(r'^detail-(\d+)-(\d+).html', views.detail),
位置参数接收:前后对应
def func(request, nid, uid):
通用参数接收:都在args里
def func(request, *args):
def func(request, *args, **kwargs):

3. 有指定参数

url(r'^detail-(?P<nid>\d+)-(?P<uid>\d+).html', views.detail)

# 举例
url(r'^detail-(?P<nid>\d+)-(?P<uid>\d+).html', views.detail)
指定参数接收:
def func(request, nid, uid):
def func(request, nid, uid):
通用参数接收:
def funct(request, **kwargs):
    kwargs = {'nid': 1, 'uid': 3}

4. name 可以根据此名称生成自己想要的URL

# urls设定

url(r'^asdfasdfasdf/', views.index, name='i1'),
url(r'^yug/(\d+)/(\d+)/', views.index, name='i2'),
url(r'^buy/(?P<pid>\d+)/(?P<nid>\d+)/', views.index, name='i3'),
        
        
# views函数设定 
def func(request, *args, **kwargs):
    from django.urls import reverse
            
    url1 = reverse('i1')                              # asdfasdfasdf/
    url2 = reverse('i2', args=(1,2,))                 # yug/1/2/
    url3 = reverse('i3', kwargs={'pid': 1, "nid": 9}) # buy/1/9/
        
# 模板中设定
xxx.html
            
    {% url "i1" %}               # asdfasdfasdf/
    {% url "i2" 1 2 %}           # yug/1/2/
    {% url "i3" pid=1 nid=9 %}   # buy/1/9/
        
# 注:
# 当前的URL
    request.path_info

5. 多级路由 app区分,多个app并行开发

  • 项目主路由设定,分发到各个app
project/urls.py
    from django.conf.urls import url,include
        urlpatterns = [
            url(r'^cmdb/', include("app01.urls")),
            url(r'^monitor/', include("app02.urls")),
        ]

app01/urls.py
    from django.conf.urls import url
    from app01 import views
        urlpatterns = [
            url(r'^login/', views.login),
        ]

6.默认值

7.命名空间

django-orm

Django默认使用的为sqlite,所以在使用mysql的时候需要对其进行相关设定

1.settings.py

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME':'dbname',
        'USER': 'root',
        'PASSWORD': 'xxx',
        'HOST': '',
        'PORT': '',
    }
}

2. project项目下的__init__.py

由于Django默认使用MySQLdb,python3中无此模块,使用pymysql的话需要再次添加:
    import pymysql
    pymysql.install_as_MySQLdb()

3. 在settings中INSTALLED_APPS注册我们的app

4.app的models.py中创建表

from django.db import models
# Create your models here.
class UserInfo(models.Model):
    # django会默认帮你创建一个自增id字段作为主键
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=64)
    email = models.EmailField()

5. makemigrations

python manage.py makemigrations
创建更改的文件

6.migrate

python manage.py migrate
将生成的py文件应用到数据库

7. 生成的表:

+----------------------------+
| Tables_in_cmdb             |
+----------------------------+
| app_cmdb_userinfo          |
| auth_group                 |
| auth_group_permissions     |
| auth_permission            |
| auth_user                  |
| auth_user_groups           |
| auth_user_user_permissions |
| django_admin_log           |
| django_content_type        |
| django_migrations          |
| django_session             |
+----------------------------+ 

mysql> desc app_cmdb_userinfo;
+----------+--------------+------+-----+---------+----------------+
| Field    | Type         | Null | Key | Default | Extra          |
+----------+--------------+------+-----+---------+----------------+
| id       | int(11)      | NO   | PRI | NULL    | auto_increment |
| username | varchar(32)  | NO   |     | NULL    |                |
| password | varchar(64)  | NO   |     | NULL    |                |
| email    | varchar(254) | NO   |     | NULL    |                |
+----------+--------------+------+-----+---------+----------------+

Django ORM操作相关

1.添加数据

from app_cmdb import models
# 有几个字段,传几个参数就行了
models.UserInfo.objects.create(username="leon", password="123123", email='4641231@qq.com')

# 方法2
stu1 = user(username="leon", password="123123", email='4641231@qq.com')
stu1.save() # flush到数据库中

2.数据修改

# 单个数据的多个字段同时跟新
models.UserInfo.objects.get(username="leon", password="123123", email='4641231@qq.com').update(username="Leon",password="qweasdC")

# 跟新某个字段
user_obj = models.UserInfo.objects.get(username="leon", password="123123")
user_obj.username="Jack"
user_obj.save()

# 多条数据同时跟新
models.UserInfo.objects.all().update(username='Zhang') 

3.数据删除

# 删除表中所有数据
models.UserInfo.objects.all().delete()
# 筛选单个删除
models.UserInfo.objects.get(username="leon").delete()
# 过滤多个删除
models.UserInfo.objects.filter(username="leon").delete()

4.数据查询,所有查询、过滤、排序、取值方法可以结合自己的使用场景来使用,以达到最佳的效果

# 查询所有记录
models.UserInfo.objects.all()


# 带字段名的所有记录,就是将所有记录以key-value的形式保存在字典中
models.UserInfo.objects.all().values()
>>><QuerySet [{'id': 1, 'username': 'leon', 'password': '123123', 'email': '4641231@qq.com'}, {'id': 2, 'username': 'leon', 'password': '1123123', 'email': '4641231@qq.com'}]>

# 查询单条记录,使用get查询单条数据,如果没有查到,会直接报错,结合try来使用
models.UserInfo.objects.get(name='Aaron')

# 查询多条中的第一条记录,多个过滤条件,需要在filter中用逗号分隔开
models.UserInfo.objects.filter(username='leon', password="123123").first()

# 模糊过滤,字段只要包含就可以
models.UserInfo.objects.filter(username__contains='leo').first()

# 模糊-不区分大小写
models.UserInfo.objects.filter(username__icontains='leo').first()


# 将字段内容排序后显示
models.UserInfo.objects.order_by('username')


# 查询记录的个数
models.UserInfo.objects.filter().conut()

# 筛选之大于小于,多个用逗号分开
models.UserInfo.objects.filter(id__gt=1)  # 大于1
models.UserInfo.objects.filter(id__gte=1)  # 大于等于1
models.UserInfo.objects.filter(id__lt=1)  # 小于1
models.UserInfo.objects.filter(id__lte=1)  # 小于等于1
models.UserInfo.objects.filter(id_gt=1,id__lte=10) # 大于1小于等于10


# in,not in
models.UserInfo.objects.filter(id__in=[11, 22, 33]) # 获取id等于11、22、33的数据
models.UserInfo.objects.exclude(id__in=[11, 22, 33])  # not in


# 排序值逆序
models.UserInfo.objects.order_by('-username')

# 限制数据条数,因为返回的是一个QuerySet类型的列表,我们可以使用列表的分片来获取想要的数据内容,依然按照`顾首不顾尾`的原则
models.UserInfo.objects.filter(username="leon")[0]  # 第一条数据
models.UserInfo.objects.filter(username="leon")[0:3]  # 去前三条数据

5.数据字段类型

  • 几种主要的类型之-数字类型
1. AutoField int类型(1 to 2147483647)的自增id列,须加参数 primary_key=True
2. BigAutoField bigint类型(1 to 9223372036854775807),同上
3. BigIntegerField
4. IntegerField
5. FloatField 
6. SmallIntegerField
7. PositiveIntegerField
8. PositiveSmallIntegerField
  • 字符串类型
1. CharField
2. EmailField (admin)
3. GenericIPAddressField (admin)
4. URLField (admin)
5. UUIDField
  • 时间类型
1. DateField (Python:datetime.date)
2. DateTimeField (Python: datetime.datetime )
3. DecimalField (python : Decimal)
4. DurationField (python :  timedelta)
5. TimeField  (python : datetime.time)
  • 二进制类型
1. BinaryField
  • 布尔类型
1. BooleanField
  • 文件类型
1. FileField

6.参数

  • 基本
- null 是否可以为空
- default 默认值
- primary_key 主键
- db_column 舍子数据库中的列名
- db_index  建立普通索引
- unique 唯一索引
- unique_for_data 只对时间做索引
- unique_for_month 只对月份做索引
- unique_for_year 只对年份做索引
- auto_now  添加还是修改对象,时间为你添加或者修改的时间,需要使用obj.save()来跟新,而update不能跟新
- auto_now_add 创建时自动创建时间,跟新不动
  • admin:

- choices 两个作用
    user_type_choices = (  # 将这些字段放进内存,而避免数据库连表操作
        (1,'root'),
        (2,'root1'),
        (3,'root1')
    ) 而且在django-admin中可以通过select直接选择
    user_type_id = models.IntegerField(choices=user_type_choices,default=1)
- blank admin中是否可以为空
- verbose_name="用户名"  前端显示的别名
- editable 是否可以被编辑
- error_messages 输入错误提示消息自定义   error_messages={'required':u'邮箱不能为空'}????
- help_text help_text="user_name"  输入框下的用户提示信息
- validators  Django的form自定义验证机制设置

7.外键的连表操作

  • 表结构
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, protocol='ipv4')
    port = models.IntegerField()
    b = models.ForeignKey(to='Business', to_field='id')


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

1.单表三种获取方式

# QuerySet内部为对象,模板获取的时候用"."来获取
v1 = models.Business.objects.all() 


# QuerySet内部为key、value的字典,因为是字典,在模板中获取的时候用"."来获取,
v2 = models.Business.objects.all().values('id', 'caption')  #只获取特定字段

# QuerySet内部为元组,因为是元组,在模板中获取的时候使用0,1,2的index来获取
v3 = models.Business.objects.all().values_list('id', 'caption')
  • 举例:
# urls.py
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^business/$', views.business),
    url(r'^host/$', views.Host.as_view()),
]

# views.py
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})


# business.html
<h1>(对象获取)</h1>
{% for foo in v1 %}
    <li>{{ foo.id }}--{{ foo.caption }}--{{ foo.code }}</li>
{% endfor %}
<h1>(字典获取)</h1>
{% for foo in v2 %}
    <li>{{ foo.id }}--{{ foo.caption }}</li>
{% endfor %}
<h1>(元祖获取)</h1>
{% for foo in v3 %}
    <li>{{ foo.0 }}--{{ foo.1 }}</li>
{% endfor %}

2.连表三种获取方式

# QuerySet内部为对象,模板获取的时候用"."来获取
v1 = models.Host.objects.filter(nid__gt=0)

# QuerySet内部为key、value的字典,因为是字典,在模板中获取的时候用"."来获取,
v2 = models.Host.objects.all().values('nid', 'hostname', 'b_id', 'b__caption', 'b__code')

# QuerySet内部为元组,因为是元组,在模板中获取的时候使用0,1,2的index来获取
v2 = models.Host.objects.all().values_list('nid', 'hostname', 'b_id', 'b__caption', 'b__code')
  • 举例
# urls.py

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

# views.py
class Host(View):
    def get(self, request):
        v1 = models.Host.objects.filter(nid__gt=0)
        v2 = models.Host.objects.all().values('nid', 'hostname', 'b_id', 'b__caption', 'b__code')
        v3 = models.Host.objects.all().values_list('nid', 'hostname', 'b_id', 'b__caption', 'b__code')
        return render(request, 'host.html', {'v1': v1, 'v2': v2, 'v3': v3})

    def post(self, request):
        pass


# host.html
<h1>对象</h1>
{% for row in v1 %}
            <tr host_id="{{ row.nid }}" b_id="{{ row.b_id }}">
            <td>{{ row.hostname }}</td>
            <td>{{ row.ip }}</td>
            <td>{{ row.port }}</td>
            <td>{{ row.b.caption }}</td>
            </tr>
{% endfor %}

<h1>字典</h1>
{% for row in v2 %}
            <tr host_id="{{ row.nid }}" b_id="{{ row.b_id }}">
            <td>{{ row.hostname }}</td>
            <td>{{ row.b__caption }}</td>
            </tr>
{% endfor %}

<h1>元组</h1>
{% for row in v3 %}
            <tr host_id="{{ row.0 }}" b_id="{{ row.2 }}">
            <td>{{ row.1 }}</td>
            <td>{{ row.3 }}</td>
            </tr>
{% endfor %}