zoukankan      html  css  js  c++  java
  • Django之 Models组件

    本节内容

    • 路由系统
    • models模型
    • admin 
    • views视图
    • template模板

    引子

    讲django的models之前, 先来想一想, 让你通过django操作数据库,你怎么做? 做苦思冥想,可能会这样写。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import pymysql
     
     
    def index(request):
        # 创建连接
        conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='alex123', db='luffy_dev')
        # 创建游标
        cursor = conn.cursor()
     
        cursor.execute("select username,email,mobile from web_account")
        data_set = cursor.fetchall()
     
        cursor.close()
        conn.close()
     
        return HttpResponse(data_set)

    很方便就实现了从数据库里取数据,事实上,很多人确实就是这么做的。但这样做会带来2个问题

    • SQL注入危险,因为有的时候你操作数据库的语句不是写死在代码里的,而是通过前端传参数拼接的,这就给黑客有了可趁之机,通过拼接参数实现sql注入。
    • 语句跟代码揉在一起了,增加后续维护成本

    那怎么办呢?ORM提供了新思路。

    什么是ORM呢?

    对象关系映射(Object Relational Mapping),它的实质就是将关系数据(库)中的业务数据用对象的形式表示出来,并通过面向对象(Object-Oriented)的方式将这些对象组织起来,实现系统业务逻辑的过程。

    在ORM过程中最重要的概念是映射(Mapping),通过这种映射可以使业务对象与数据库分离。从面向对象来说,数据库不应该和业务逻辑绑定到一起,ORM则起到这样的分离作用,使数据库层透明,开发人员真正的面向对象。

    上面的解释有点蒙蔽对不?其实你只需要抓住2个关键词, “映射” 和 “对象”,就能知道orm是什么干什么的了。

    • 映射(Mapping) —— 把表结构映射成类
    • 对象 —— 像操作类对象一样,操作数据库里的数据

    映射

    看下面的图,就是直观的例子,把右边的表结构映射成了左边的类

     Sql语句到对象

    ORM可以使你不用再写原生SQL, 而是像操作对象一样就可以实现对表里数据的增删改查

    好棒棒,妈妈再也不用逼你写原生sql啦!

    但是不要开心太早,ORM确实提高了开发效率,并且降低了数据操作与代码之间的耦合,不过有利就有弊,我们总结一下orm的优缺点。

    优点:

    1. 实现了代码与数据操作的解耦合
    2. 不需自己写原生sql, 提高开发效率
    3. 防止SQL注入, 通过对象操作的方式,默认就是防止sql注入的。

    缺点:

    1. 牺牲性能, 对象到原生SQL势必会有转换消耗,对性能有一定的影响 
    2. 复杂语句力不从心, 一些复杂的sql语句,用orm对象操作的方式很难实现,就还得用原生sql

    讲Django为什么说ORM? 哈,  好啦,是时候该引出主角啦,因为Django的models基于架构ORM实现的。

    Models模型

    Django 的models把数据库表结构映射成了一个个的类, 表里的每个字段就是类的属性。我们都知道数据库有很多字段类型,int,float,char等, Django的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
    AutoField         #An IntegerField that automatically increments according to available IDs
    BigAutoField      #A 64-bit integer, guaranteed to fit numbers from 1 to 9223372036854775807.
    BigIntegerField   #-9223372036854775808 to 9223372036854775807
    BinaryField       #A field to store raw binary data. It only supports bytes assignment
    BooleanField   
    CharField
    DateField         #e.g 2019-04-27
    DateTimeField     #e.g 2019-04-27 17:53:21
    DecimalField     
    DurationField     #storing periods of time ,e.g [DD] [HH:[MM:]]ss[.uuuuuu]"
    EmailField
    FileField         #存储文件
    FloatField
    ImageField        #Inherits all attributes and methods from FileField, but also validates that the uploaded object is a valid image.
    IntegerField
    GenericIPAddressField #IP地址,支持ipv4
    NullBooleanField      #Like a BooleanField, but allows NULL as one of the options
    PositiveIntegerField  #Like an IntegerField, but must be either positive or zero (0). Values from 0 to 2147483647
    PositiveSmallIntegerField #only allows positive  values from 0 to 32767
    SlugField # A slug is a short label for something, containing only letters, numbers, underscores or hyphens.
    SmallIntegerField
    TextField   #A large text field.
    TimeField   #A time, represented in Python by a datetime.time instance.
    URLField
    UUIDField   #A field for storing universally unique identifiers. Uses Python’s UUID class.

    除了普通的表字段,针对外键也有映射

    1
    2
    3
    4
    ForeignKey  # 外键关联
    ManyToManyField  #多对多
     
    OneToOneField  # 1对1

      

    好啦,接下来就用django的orm来设计一个博客表。

    需求

    1. 每个用户有自己的账户信息
    2. 用户可以发文章
    3. 文章可以打多个标签

    根据需求,我们设计3张表

    注意Article表和Tag表是属于多对多关系,什么是多对多?即一个文章有多个标签,一个标签又可以属于多个文章。 

    比如上图的Article表中id为3的文章 ,它的标签是4,26, 即投资、大文娱、社交, 你看“投资”这个标签同时还属于文章2。 这就是多对多关系 , 即many to many . 

    那这种多对多的关系如何在表中存储呢?难道真的像上图中一样,在Article表中加个tags字段,关联Tag表里的多条数据,通过逗号区分?

    这倒确实是个解决办法。但是也有问题,一个字段里存多条纪录的id,就没办法做查询优化了。比如不能做索引等。

    所以若想实现多对多关系的高效存储+查询优化,可以在Article and Tag表之间再搞出一张表。

    这样是不是就实现了多对多关联?

    yes, 没错, django也是这么做的, django 有个专门的字段,叫ManyToManyField, 就是用来实现多对多关联的,它会自动生成一个如上图一样的第3张表来存储多对多关系。

    正式的表结构

    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
    from django.db import models
     
    # Create your models here.
     
     
    class Account(models.Model):
        username = models.CharField(max_length=64,unique=True)
        email = models.EmailField()
        password = models.CharField(max_length=128)
        register_date = models.DateTimeField("注册日期",auto_now_add=True)
        signature = models.CharField(verbose_name="签名",max_length=128,blank=True,null=True)
     
     
    class Article(models.Model):
        """文章表"""
        title = models.CharField(max_length=255,unique=True)
        content = models.TextField("文章内容")
        account = models.ForeignKey("Account",verbose_name="作者",on_delete=models.CASCADE)
        tags = models.ManyToManyField("Tag",blank=True)
        pub_date = models.DateTimeField()
        read_count = models.IntegerField(default=0)
     
     
    class Tag(models.Model):
        """文章标签表"""
        name = models.CharField(max_length=64,unique=True)
        date = models.DateTimeField(auto_now_add=True)

      

    我们发现,每个字段其实都是一个独立的对象,一张表其实是很多类的组合。

    上面好多字段里还跟了些参数,我们来看以下常用的:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    null        #If True, Django will store empty values as NULL in the database. Default is False.
    blank       #If True, the field is allowed to be blank. Default is False.
     
    db_column   #The name of the database column to use for this field. If this isn’t given, Django will use the field’s name.
    db_index    #If True, a database index will be created for this field.
    default     #The default value for the field. This can be a value or a callable object. If callable it will be called every time a new object is created.
    editable    # django admin中用,后面讲
    help_text   # django admin中用,后面讲
    primary_key # If True, this field is the primary key for the model.
    unique      #If True, this field must be unique throughout the table
    unique_for_date    #Set this to the name of a DateField or DateTimeField to require that this field be unique for the value of the date field. For example, if you have a field title that has unique_for_date="pub_date", then Django wouldn’t allow the entry of two records with the same title and pub_date.
     
    unique_for_month   #Like unique_for_date, but requires the field to be unique with respect to the month.
    unique_for_year   
    verbose_name    #A human-readable name for the field. If the verbose name isn’t given, Django will automatically create it using the field’s attribute name

    还有几个特殊的字段属性需要单独介绍下

    choices

    An iterable (e.g., a list or tuple) consisting itself of iterables of exactly two items (e.g. [(A, B), (A, B) ...]) to use as choices for this field.

    The first element in each tuple is the actual value to be set on the model, and the second element is the human-readable name.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Student(models.Model):
        YEAR_IN_SCHOOL_CHOICES = (
            ('FR''Freshman'),
            ('SO''Sophomore'),
            ('JR''Junior'),
            ('SR''Senior'),
        )
        year_in_school = models.CharField(
            max_length=2,
            choices=YEAR_IN_SCHOOL_CHOICES,
            default=FRESHMAN,
        )

    ForeignKey.on_delete

    当一条记录关联的外键纪录被删除时,django 也会根据外键关联限制的配置来决定如何处理当前这条纪录。举例,如果你有个可以为null的外键关联,并且你想在本纪录关联的数据被删除时,把当前纪录的关联字段设为null,那就配置如下

    1
    2
    3
    4
    5
    6
    user = models.ForeignKey(
        User,
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
    )

    这个on_delete就是决定在关联对象被删除时,如何处理当前纪录的,常用的参数如下:

    • CASCADE——Cascade deletes. Django emulates the behavior of the SQL constraint ON DELETE CASCADE and also deletes the object containing the ForeignKey.
    • PROTECT——Prevent deletion of the referenced object by raising ProtectedError, a subclass of django.db.IntegrityError.
    • SET_NULL——Set the ForeignKey null; this is only possible if null is True.
    • SET_DEFAULT——Set the ForeignKey to its default value; a default for the ForeignKey must be set.

    配置Django数据库连接信息

    Django支持多种数据库,Sqlite、Mysql、Oracle、PostgreSQL,默认的是小型文件数据库Sqlite

    1
    2
    3
    4
    5
    6
    DATABASES = {
        'default': {
            'ENGINE''django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        }
    }

    咱们是干大事的人,怎么也得用个Mysql呀, 改成mysql 也so easy.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    DATABASES = {
        'default': {
            'ENGINE''django.db.backends.mysql',
            'NAME''my_db',
            'USER''mydatabaseuser',
            'PASSWORD''mypassword',
            'HOST''127.0.0.1',
            'PORT''3306',
        }
    }

    不过注意,python3 连接mysql的得使用pymysql,MysqlDB模块300年没更新了,但django默认调用的还是MySQLdb, so pymysql有个功能可以让django以为是用了MySQLdb. 即在项目目录下的__init__.py中加上句代码就好

    1
    2
    3
    import pymysql
     
    pymysql.install_as_MySQLdb()

    不加的话,一会连接数据时会报错噢 。

    同步数据库  

    你在ORM定义的表结构如何同步到真实的数据库里呢? 只需2条命令。但django只能帮你自动创建表,数据库本身还是得你自己来。

    1
    create database my_db charset utf8;  

      

    好了,可以同步了,说好只需2步。

    1. 生成同步文件, django自带一个专门的工具叫migrations, 负责把你的orm表转成实际的表结构,它不旦可以帮自动创建表,对表结构的修改,比如增删改字段、改字段属性等也都能自动同步。只需通过下面神奇的命令。

    1
    python manage.py makemigrations  

     不出意外的话,会显示类似以下信息

    1
    2
    3
    4
    5
    6
    7
    $ python manage.py makemigrations
    Migrations for 'app01':
      app01/migrations/0001_initial.py
        - Create model Account
        - Create model Article
        - Create model Tag
        - Add field tags to article

    此时你会发现,你的app下的migrations目录里多了一个0001_initial.py的文件 ,这个文件就是因为你这条命令而创建的,migrations工具就会根据这个文件来创建数据库里的表。

    2. 同步到数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    $ python manage.py migrate
    Operations to perform:
      Apply all migrations: admin, app01, auth, contenttypes, sessions
    Running migrations:
      Applying contenttypes.0001_initial... OK
      Applying auth.0001_initial... OK
      Applying admin.0001_initial... OK
      Applying admin.0002_logentry_remove_auto_add... OK
      Applying app01.0001_initial... OK
      Applying contenttypes.0002_remove_content_type_name... OK
      Applying auth.0002_alter_permission_name_max_length... OK
      Applying auth.0003_alter_user_email_max_length... OK
      Applying auth.0004_alter_user_username_opts... OK
      Applying auth.0005_alter_user_last_login_null... OK
      Applying auth.0006_require_contenttypes_0002... OK
      Applying auth.0007_alter_validators_add_error_messages... OK
      Applying auth.0008_alter_user_username_max_length... OK
      Applying auth.0009_alter_user_last_name_max_length... OK
      Applying sessions.0001_initial... OK
    (venv_django2) Alexs-MacBook-Pro:mysite alex$

    此时登录你的数据库,会发现创建了好多张表

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    mysql> show tables;
    +----------------------------+
    | Tables_in_luffy_dev2       |
    +----------------------------+
    | app01_account              |  #对应Account表
    | app01_article              |  #对应Article表
    | app01_article_tags         |  #自动创建的Article to Tag的多对多关联表
    | app01_tag                  |  #对应Tag表
    | auth_group                 |  #下面这些,都是django 自带的表,这个是自动用户系统的组
    | auth_group_permissions     |  #自带的组与权限的多对多关联表
    | auth_permission            |  #自带权限表
    | auth_user                  |  #用户表
    | auth_user_groups           |
    | auth_user_user_permissions |
    | django_admin_log           |  #现在你的无法理解  
    | django_content_type        |  #现在你的无法理解
    | django_migrations          |  #纪录migartions工具同步纪录的表
    | django_session             |  #现在你的无法理解
    +----------------------------+
    14 rows in set (0.00 sec)

      

    好啦,表结构也有了,我们可以往里面插数据啦。

    之前说好的是可以不用SQL语句的,一点不骗你。

    用orm对表数据进行增删改查

    先进入已经连接好数据库的django python环境

    1
    2
    3
    4
    5
    6
    7
    (venv_django2) Alexs-MacBook-Pro:mysite alex$ python manage.py shell 
    Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 26 2016, 10:47:25)
    [GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
    Type "help""copyright""credits" or "license" for more information.
    (InteractiveConsole)
    >>>
    >>> from app01 import models

      

    创建

    创建数据简单的令人发指

    filter 支持很多的过滤条件,我们来看下:

     

    contains

    包含,相当于sql的like条件

    1
    Entry.objects.get(headline__contains='Lennon')

    SQL equivalent:

    1
    SELECT ... WHERE headline LIKE '%Lennon%';

    Note this will match the headline 'Lennon honored today' but not 'lennon honored today'.

    icontains  大小写不敏感  

      

    in

    In a given iterable; often a list, tuple, or queryset.

    1
    Entry.objects.filter(id__in=[134])

    SQL equivalent:

    1
    SELECT ... WHERE id IN (1, 3, 4);

    You can also use a queryset to dynamically evaluate the list of values instead of providing a list of literal values:

    1
    2
    inner_qs = Blog.objects.filter(name__contains='Cheddar')
    entries = Entry.objects.filter(blog__in=inner_qs)

    This queryset will be evaluated as subselect statement:

    1
    SELECT ... WHERE blog.id IN (SELECT id FROM ... WHERE NAME LIKE '%Cheddar%')

      

    gt

    1
    Entry.objects.filter(id__gt=4)

    SQL equivalent:

    1
    SELECT ... WHERE id > 4;

    gte
    Greater than or equal to.

    lt
    Less than.

    lte
    Less than or equal to.

    startswith
    Case-sensitive starts-with.

    1
    Entry.objects.filter(headline__startswith='Lennon')

    SQL equivalent:

    1
    SELECT ... WHERE headline LIKE 'Lennon%';

    SQLite doesn’t support case-sensitive LIKE statements; startswith acts like istartswith for SQLite  

    istartswith
    Case-insensitive starts-with.

    endswith
    Case-sensitive ends-with.

    iendswith
    Case-insensitive ends-with

      

    range
    区间过渡,可对数字、日期进行过滤

    1
    2
    3
    4
    import datetime
    start_date = datetime.date(200511)
    end_date = datetime.date(2005331)
    Entry.objects.filter(pub_date__range=(start_date, end_date))

    SQL equivalent:

    1
    SELECT ... WHERE pub_date BETWEEN '2005-01-01' and '2005-03-31';

    Warning!

    Filtering a DateTimeField with dates won’t include items on the last day, because the bounds are interpreted as “0am on the given date”. If pub_date was a DateTimeField, the above expression would be turned into this SQL:

    SELECT ... WHERE pub_date BETWEEN '2005-01-01 00:00:00' and '2005-03-31 00:00:00';
    Generally speaking, you can’t mix dates and datetimes. 

      

    date

    For datetime fields, casts the value as date. Allows chaining additional field lookups. Takes a date value.  

    1
    2
    Entry.objects.filter(pub_date__date=datetime.date(200511))
    Entry.objects.filter(pub_date__date__gt=datetime.date(200511))

    year
    For date and datetime fields, an exact year match. Allows chaining additional field lookups. Takes an integer year.

    1
    2
    Entry.objects.filter(pub_date__year=2005)
    Entry.objects.filter(pub_date__year__gte=2005)

    SQL equivalent:

    1
    2
    SELECT ... WHERE pub_date BETWEEN '2005-01-01' AND '2005-12-31';
    SELECT ... WHERE pub_date >= '2005-01-01';

    When USE_TZ is True, datetime fields are converted to the current time zone before filtering. 简单解决办法是把USE_TZ=False

    month
    For date and datetime fields, an exact month match. Allows chaining additional field lookups. Takes an integer 1 (January) through 12 (December).

    1
    2
    Entry.objects.filter(pub_date__month=12)
    Entry.objects.filter(pub_date__month__gte=6)

    When USE_TZ is True, datetime fields are converted to the current time zone before filtering. This requires time zone definitions in the database.

    SQL equivalent:

    1
    2
    SELECT ... WHERE EXTRACT('month' FROM pub_date) = '12';
    SELECT ... WHERE EXTRACT('month' FROM pub_date) >= '6';

    day
    For date and datetime fields, an exact day match. Allows chaining additional field lookups. Takes an integer day.

    1
    2
    Entry.objects.filter(pub_date__day=3)
    Entry.objects.filter(pub_date__day__gte=3)

    SQL equivalent:

    1
    2
    SELECT ... WHERE EXTRACT('day' FROM pub_date) = '3';
    SELECT ... WHERE EXTRACT('day' FROM pub_date) >= '3';

      

    week

    New in Django 1.11.

    For date and datetime fields, return the week number (1-52 or 53) according to ISO-8601, i.e., weeks start on a Monday and the first week contains the year’s first Thursday.

    Example:

    1
    2
    Entry.objects.filter(pub_date__week=52)
    Entry.objects.filter(pub_date__week__gte=32, pub_date__week__lte=38)

    week_day

    For date and datetime fields, a ‘day of the week’ match. Allows chaining additional field lookups.

    Takes an integer value representing the day of week from 1 (Sunday) to 7 (Saturday).

    Example:

    1
    2
    Entry.objects.filter(pub_date__week_day=2)
    Entry.objects.filter(pub_date__week_day__gte=2)

    hour

    For datetime and time fields, an exact hour match. Allows chaining additional field lookups. Takes an integer between 0 and 23.

    Example:

    1
    2
    3
    Event.objects.filter(timestamp__hour=23)
    Event.objects.filter(time__hour=5)
    Event.objects.filter(timestamp__hour__gte=12)

    SQL equivalent:

    1
    2
    3
    SELECT ... WHERE EXTRACT('hour' FROM timestamp) = '23';
    SELECT ... WHERE EXTRACT('hour' FROM time) = '5';
    SELECT ... WHERE EXTRACT('hour' FROM timestamp) >= '12';同  

    同时,还支持mintue,second

    1
    2
    3
    4
    Event.objects.filter(time__minute=46)
     
     
    Event.objects.filter(timestamp__second=31)

    isnull

    Takes either True or False, which correspond to SQL queries of IS NULL and IS NOT NULL, respectively.

    Example:

    1
    Entry.objects.filter(pub_date__isnull=True)

    SQL equivalent:

    1
    SELECT ... WHERE pub_date IS NULL;

    regex

    Case-sensitive regular expression match.

    Example:

    1
    Entry.objects.get(title__regex=r'^(An?|The) +')

    SQL equivalents:

    1
    2
    3
    4
    5
    6
    7
    SELECT ... WHERE title REGEXP BINARY '^(An?|The) +'-- MySQL
     
    SELECT ... WHERE REGEXP_LIKE(title, '^(An?|The) +''c'); -- Oracle
     
    SELECT ... WHERE title ~ '^(An?|The) +'-- PostgreSQL
     
    SELECT ... WHERE title REGEXP '^(An?|The) +'-- SQLite  

    iregex 大小写不敏感    

       

    改删

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    # 批量修改
    models.Account.objects.filter(username='elina').update(password="Luffy#21")
     
    # 单条修改
    obj = models.Account.objects.get(username='linux')
    obj.username = 'python'
    obj.save()
     
     
    # 批量删除
    models.User.objects.get(password='oldboy').delete()
     
    # 单条删除
    obj = models.User.objects.get(id=3)
    obj.delete()

    数据返回后的展示

    values()

    values(*fields**expressions)

    Returns a QuerySet that returns dictionaries, rather than model instances, when used as an iterable.

    1
    2
    3
    4
    >>> Blog.objects.values()
    <QuerySet [{'id'1'name''Beatles Blog''tagline''All the latest Beatles news.'}]>
    >>> Blog.objects.values('id''name')
    <QuerySet [{'id'1'name''Beatles Blog'}]>

    order_by()

    order_by(*fields)

    By default, results returned by a QuerySet are ordered by the ordering tuple given by the ordering option in the model’s Meta. You can override this on a per-QuerySet basis by using the order_by method.

    1
    Entry.objects.filter(pub_date__year=2005).order_by('-pub_date''headline')

    The result above will be ordered by pub_date descending, then by headline ascending. The negative sign in front of "-pub_date"indicates descending order. Ascending order is implied. 

    reverse()

    Use the reverse() method to reverse the order in which a queryset’s elements are returned. Calling reverse() a second time restores the ordering back to the normal direction.

    To retrieve the “last” five items in a queryset, you could do this:

    1
    my_queryset.reverse()[:5]

      

    ORM对象操作

    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
    单表对象操作
    = models.Article.objects.all()[0]
    o.tilte
     
    外键关联
    >>> o.account.username
    'jack'
    >>> o.account.username = rain
     
    外键反向关联操作
    >>> a = models.Account.objects.get(username='alex')
    >>> a.article_set.all()
    <QuerySet [<Article: 你好,2018>]>
    >>> a.article_set.select_related()
    <QuerySet [<Article: 你好,2018>]>
     
     
    多对多操作
    >>> o = models.Article.objects.all()[1]
    >>> o.tags.all()
    <QuerySet [<Tag: 投资>, <Tag: 科技>]>
     
     
    多对多反向操作
    >>> t = models.Tag.objects.get(name="投资")
    >>> t.article_set.all()
    <QuerySet [<Article: 你好,2018>, <Article: 粉丝超过10万后,我经历了抖音盗号风波>]>

      

      

    好啦,orm的操作先点到为止,后面学项目时再带你搞复杂的。

    练习题

    1. 基于前面课程设计的表结构,完成以下练习:
    2. 创建5条account和5条新tag纪录
    3. 创建5条article信息,关联上面的不同的用户和tag
    4. 在account表里找到用户名包含al的纪录,然后把密码改掉
    5. 在article表找到文章内容包含“电影”2个字的,把这些文章加上”大文娱”tag
    6. 把用户elina发表的文章找出来,并且把作者都改成alex
    7. 找到用户表里注册日期在2018-04月,并且signature为空的纪录
    8. 打到文章中标签为“投资”的所有文章
    9. 找到每个月8号注册的用户
    10. 找到每年5月发表的文章 
    11. 找到2015-2017年5月发表的文章 
    12. 找到文章作者以’a’或’k’开头的文章

      

  • 相关阅读:
    关闭requests请求的长连接
    Python连接数据库
    429状态码
    scrapy框架查看请求状态码
    requests请求发送的次数太多的情况下会报错(max ......)
    将中文乱码(ÎÖ¶ûÂ꾩¶«×ÔÓª¹Ù·½Æì½¢µê)转换成正确的格式(沃尔玛京东自营官方旗舰店)
    inout用法浅析
    Thread系列——Thread.Sleep(0)
    构造函数
    [DllImport("kernel32.dll")]是什么意思??
  • 原文地址:https://www.cnblogs.com/shuai1991/p/11186937.html
Copyright © 2011-2022 走看看