Django framework 3-- model

Django database layer problem

In view of this example was used to connect pymysql library MySQL database, retrieve some records, providing them to the template to display a Web page:

from django.shortcuts import render
import pymysql
def book_list(request):
    db = pymysql.connect(user='me', db='mydb', passwd='secret',                                                   host='localhost',charset='utf8')
    cursor = db.cursor()
    cursor.execute('SELECT name FROM books ORDER BY name')
    names = [row[0] for row in cursor.fetchall()]
    db.close()
    return render('book_list.html', {'names': names})

This method can be used, but some problems will soon appear in front of you:

  • We'll database connection parameters hard-coded in line in the code. Ideally, these parameters should be stored in Django configuration.
  • We have to repeat the same code: create a database connection, create a database cursor, execute a statement, and then close the database. Ideal
    case, we should need only specify the desired results.
  • We tied it to die on MySQL. If over time, we change from MySQL to PostgreSQL, you have to use a different
    database adapter (eg psycopg instead pymysql), change the connection parameters, may also modify depending on the type of SQL statements
    SQL. Ideally, the database server used to deal with abstract, so that only you can modify a database conversion service
    is.

MTV development model

Django data-driven Web applications overall design:
Django is designed to encourage loose coupling and strict segmentation of the different parts of the application. Following this idea, then, to modify certain parts of the application without affecting the rest is relatively easy. In view function, we have discussed the importance of a template system business logic and presentation logic separated.
Data access logic, business logic and presentation logic combined concept is sometimes called View-software architecture-the Controller of the Model
(the MVC) pattern. In this mode, Model behalf of the data access layer, View represents any selection display system and a display unit how the
points, the Controller refers to a system based on user input as needed and access model, used to determine which view which section.

The following are the Django M, V C, and the respective meanings:
M, the data access portion by django database layer processing.
V, which select the display data to be displayed and how a display section of the template and processed by the view.
C, partial view of the delegated user input, according to the frame URLconf Django settings appropriate for a given URL call Python function.
Due to the discretion of the frame C, and is more concerned in Django model (the Model), the template (Template) and view (the Views),
Django frame is also referred to MTV. MTV in the development model:
M Representative model (Model), i.e., the data access layer. The transaction layer processing all data relating to: how to access and how to verify the effective
resistance, and the relationship between the behavior of which contains data and the like.

T represents the template (Template), ie, the presentation layer. This layer processing and performance-related decisions: how significant a page or other types of documents
are shown.
V represents a view (View), i.e., the business logic layer. The access layer includes associated logic model and retrieval of appropriate templates. You can think of it as
a bridge between the model and template.
If you are familiar with other MVC Web development framework, say Ruby on Rails, Django view you might think is the controller, and the
Django template is a view. Unfortunately, this is the wrong understanding of the MVC caused by different interpretations. In Django's interpretation of MVC, depending
diagram used to describe the data to be presented to the user; not data to show how, and what the data show. In contrast, Ruby on Rails and a number of
similar frameworks advocate controller is responsible for deciding what data presented to the user, and view only decide how to present the data, rather than what the data show.
Two Annotations are no more accurate number. It is important to understand the underlying concepts.

Database Configuration

https://docs.djangoproject.com/en/2.2/ref/settings/

Initial configuration; tell Django what database and how to connect to the database. Create a database (for example, using the CREATE DATABASE statement) settings.py:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mydb',
        'USER': 'Sroxi',
        'PASSWORD': '123',
        'HOST': '127.0.0.1',
        'PORT': '6379',
    }
}

The first application

Let's create a Django app: contains model, view and Django code, and in the form of a complete stand-alone Python Django application package . We have created a project, then in the end what is the difference between the project and the app do? Their difference is that one is the other configuration is the code :
a project contains a number of Django app as well as their configuration. Technically, the role of project is to provide a configuration file , for example where the app list defined database connection information, installation, TEMPLATE_DIRS, and so on. A Django app is a collection of functions, and generally includes a model view, the presence of the manner Python packet structure. For example, Django itself has some built-in app, such as automatic annotation system and management interface. app A key point is that they are easily ported to other project are multiplexed and the plurality of project .
Django framework for how the code is not fast set of rules. If you just build a simple Web site, then you may only need
a app on it; but if it is a module contains many unrelated complex sites, such as e-commerce and community sites like, then
what you might these need to be divided into different modules app, for later reuse.
Yes, you can not create the app, this should prove to be written by the example of our previous view function. In those instances, we just
simply create a file called views.py, the preparation of a number of mapping functions and settings of each function in the URLconf. These cases
do not need to use apps. but,There is a system app convention: If you use Django's database layer (models), you must create a Django app. Models must be stored in the apps. Therefore, in order to start the construction of our model, we have to create a new app.

In mysiteEnter the following command to create a project file booksapp:

python manage.py startapp books

In Python code model definition

MTV where M represents the model. Django Python code data model is expressed in the form defined in the database. The data layer is that it is equivalent to the CREATE TABLE statement, but the execution is the Python code instead of SQL, but also contains more meaning than the definition of database fields. Django execute SQL code used in the background and the model data structure of the result Python be described. Django also uses models to present advanced concepts SQL can not handle.
With Python and SQL to define the data model is a bit redundant? Django This is done are the following reasons:

  • Introspection (automatic identification database runtime) can lead to overload and data integrity issues. In order to provide convenient data access API, Django
    need to somehow know the internal information database layer, implemented in two ways. The first way is to explicitly define a mold Python data
    type, the second way is to automatically detect the identification data model by introspection.
  • The second way to look sharper, because the data table information only in one place - the database, but can cause problems. First, transport
    runtime scanning the database will cause serious system overload. If every request to scan the table structure of the database, or even when the service starts
    to do is bring a system overload unacceptable. (Some people think that this level of system overload is acceptable, and Django developers
    goal is to reduce as much as possible the framework of the system overload). Second, some of the database, especially in older versions of MySQL, did not complete store those
    accurate metadata introspection.
  • Is very interesting to write Python code, holding Python's way of thinking will prevent your brain to switch back and forth in different areas. As much as possible
    to keep under a single programming environment / state of mind can help you increase productivity. I had to repeat write SQL, write Python code to write
    SQL, ....
  • The presentation of the data model used to code so you can easily version control them. In this way, you can easily understand the changed data layers
    moving situation.
  • SQL can only describe the specific types of data fields. For example, most do not have a dedicated database field types to describe Email address, URL.
    The model with the Django can do it. The benefits of advanced data types that bring higher efficiency and better code reuse.
  • There are compatibility issues in different SQL database platform. Publish Web applications when using the Python module to describe the database structure information
    in order to avoid having to write MySQL, PostgreSQL, and SQLite different CREATE TABLE.

Of course, this method also has a drawback, is synchronization Python code and database tables. If you modify a Django model, you have to modify their own model and database to ensure synchronization.

The first model

A basic book / author / publisher database structure. Such concepts below, fields and relationships:

  • The author has a name, well-known and email address.
  • The publisher has a name, address, city, state, country, website.
  • There are books title and publication date. It has one or more authors (and authors are associated with many relationships [many-to-many]) , only one
    publisher will (and publishers are many associations [one-to-many], also referred to as foreign keys [foreign key])

The first step is to describe them Python code. Opened by startappmodels.py command to create and enter the following:

from django.db import models
class Publisher(models.Model):
    name = models.CharField(max_length=30)
    address = models.CharField(max_length=50)
    city = models.CharField(max_length=60)
    state_province = models.CharField(max_length=30)
    country = models.CharField(max_length=50)
    website = models.URLField()
class Author(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField()
class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher,on_delete=models.CASCADE)
    publication_date = models.DateField()

First thing to notice is a subclass of each data models are django.db.models.Model. Its parent Model contains all the necessary database and interactive approach, and provides a concise syntax beautiful custom database fields. Each model corresponds to a single database table, each property that is a field in a table. Attribute name is the field name, its type (e.g., as CharField) corresponds to a database field types (e.g. varchar). For example, Publisher this module is equivalent to the following table (with the CREATE TABLE syntax described MYSQL)

CREATE TABLE books_publisher(
    id serial NOT NULL PRIMARY KEY,
    name varchar(30) NOT NULL,
    address varchar(50) NOT NULL,
    city varchar(60) NOT NULL,
    state_province varchar(30) NOT NULL,
    country varchar(50) NOT NULL,
    website varchar(200) NOT NULL
);

Finally, it should be noted that we did not explicitly define any primary key for these models. Unless you specify a separate, otherwise every Django will automatically
generate a model from a growing integer primary key fields for each Django models are required to have a separate primary key id

Model installation

'Books' indicate books app we're writing.

setting.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'books',
]

Version change: Remove: python manage.py syncdb ---> read: python manage.py makemigrations

carried out:

 python manage.py makemigrations    # 负责将模型更改打包到单个迁移文件中(类似于提交) 

The following errors:

raise ImproperlyConfigured('mysqlclient 1.3.13 or newer is required; you have %s.' % Database.__version__)
django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 0.9.3.

MySQLclient currently only supports to python3.4, so if you use a later version of python, by finding the path \ Python \ Python37-32 \ Lib \ site-packages \ django \ db \ backends \ mysql this path in the file

base.py: Notes following content

if version < (1, 3, 3):
     raise ImproperlyConfigured("mysqlclient 1.3.3 or newer is required; you have %s" % Database.__version__)

Perform again: python manage.py makemigration, another error appears below:

query = query.decode(errors='replace')
AttributeError: 'str' object has no attribute 'decode'

Modifications python installation directory: \ Python Python37-32 \ Lib \ site-packages \ django \ db \ backends \ mysql of operations.py \.

把其中的 
query = query.decode(errors='replace')
修改为
query = query.encode(errors='replace') 

Perform again: python manage.py makemigration, successful execution; books folder migrations folder will appear 0001_initial.pyat this time the model is not synchronized to the database.

We need to perform:

python manage.py migrate          #负责将更改应用到数据库中

After the execution, synchronized to the database model

View the table name in the database is of the form: books_publisher

ps: if you want to print model conversion process sql, settings need to be arranged in the following:

`LOGGING ``=` `{``  ``'version'``: ``1``,``  ``'disable_existing_loggers'``: ``False``,``  ``'handlers'``: {``    ``'console'``:{``      ``'level'``:``'DEBUG'``,``      ``'class'``:``'logging.StreamHandler'``,``    ``},``  ``},``  ``'loggers'``: {``    ``'django.db.backends'``: {``      ``'handlers'``: [``'console'``],``      ``'propagate'``: ``True``,``      ``'level'``:``'DEBUG'``,``    ``},``  ``}``}  `

Basic Data Access

Run python manage.py shell and enter:

>>> from books.models import Publisher
>>> p1 = Publisher(name='Apress', address='2855 Telegraph Avenue',
... city='Berkeley', state_province='CA', country='U.S.A.',
... website='http://www.apress.com/')
>>> p1.save()
>>> p2 = Publisher(name="O'Reilly", address='10 Fawcett St.',
... city='Cambridge', state_province='MA', country='U.S.A.',
... website='http://www.oreilly.com/')
>>> p2.save()
>>> publisher_list = Publisher.objects.all()
>>> publisher_list
<QuerySet [<Publisher: Publisher object (1)>, <Publisher: Publisher object (2)>]>
  • First, import the Publisher model class, we can interact with the data table contains the Press by the class.
  • Next, create an Publisherinstance of the class and sets a field name, addressvalue and the like.
    Call the object's save () method to save objects to the database. Django executes an INSERT statement in the background.
  • Finally, using the Publisher.objectsattribute information removed from the database publishers, this property can be considered a record that contains the publisher's
    record collection. This property has a number of ways, first introduced here call the Publisher.objects.all()method to get the database Publisher
    for all object classes. Behind the scenes of this operation, Django execute a SQL SELECTstatement.

When you create objects using Django modle API, Django will not save objects to the database, unless you call the save()method.

If you need one step object creation and storage to the database , use objects.create()the method. Examples of previous examples following the like
price:

>>> p1 = Publisher.objects.create(name='Apress',
... address='2855 Telegraph Avenue',
... city='Berkeley', state_province='CA', country='U.S.A.',
... website='http://www.apress.com/')

Add module string performance

When we print the entire publisher list (<QuerySet [<Publisher: Publisher object (1)>, <Publisher: Publisher object (2)>]>), we do not want to get useful information, not to separate the object area:

django official website: https://docs.djangoproject.com/en/1.11/topics/python3/#str-and-unicode-methods

from django.db import models
class Publisher(models.Model):
    name = models.CharField(max_length=30)
    address = models.CharField(max_length=50)
    city = models.CharField(max_length=60)
    state_province = models.CharField(max_length=30)
    country = models.CharField(max_length=50)
    website = models.URLField()
    def __str__(self):  #python2 使用__unicode__
        return u'%s %s' % (self.name, self.address)

Django model not just for objects define the structure of the database table and also defines the behavior of the object. str () is an example to demonstrate the model knows how to display themselves.

Insert and update data

p = Publisher(name='Apress',
... address='2855 Telegraph Ave.',
... city='Berkeley',
... state_province='CA',
... country='U.S.A.',
... website='http://www.apress.com/')
>>>p.save()
>>> p.name = 'Apress Publishing'
>>> p.save()

Note that not only updates modified the field, all fields will be updated. This operation may cause a race condition, depending on your
application. See the following "Updating multiple objects" section to learn how to implement this modification lightweight (only part of a word to modify the object
segment).

Select the object

Of course, create a new database, and the data in the update is necessary, however, for Web applications, more often in the search
query the database. We already know how to remove all records from a given model:

Publisher.objects.all()

Sql statement is equivalent to:

SELECT id, name, address, city, state_province, country, website
FROM books_publisher;

Django is not used when selecting all data SELECT *, but explicitly lists all fields. When the design is such:
the SELECT * slower, but the most important is to list all the fields followed a creed Python community: made it clear rather than implied.

That Publisher.objects.all is () of each part of the line:

  • First, we have a Publisher model have been defined. No surprise: you want to find data, you can use the model to get the number of
    data.

  • Then, a property objects. It is called the manager, the manager for the management of all data contained, as well as table-level operations of the most important data queries. All models are objects automatically have a manager; you can use it when you want to find data.
  • Finally, there are all () method. This method returns return all the records in the database. Although this looks like a target list (List), which is actually a QuerySet object that is a collection of records in the database.

Data filtering (filter)

We rarely a one-time remove all the data from the database; usually only operate for part of the data. In Django API, we
can use the filter()method to filter the data:

>>> Publisher.objects.filter(name='Apress')
<QuerySet [<Publisher: Apress 2855 Telegraph Avenue>]>

filter () keyword parameters to convert WHERE SQL statements. This is equivalent to the previous example:

SELECT id, name, address, city, state_province, country, website
FROM books_publisher
WHERE name = 'Apress';

You can pass a plurality of parameters to the filter () to narrow the range of selection:

Publisher.objects.filter(country="U.S.A.", state_province="CA")

Fuzzy query

>>>Publisher.objects.filter(name__contains="press")
<QuerySet [<Publisher: Apress 2855 Telegraph Avenue>]>

Find some other types: icontains (case-insensitive LIKE), startswith and endswith, as well as range (SQLBETWEEN search
query)

Gets a single object (get)

Examples of the above filter()functions return a record set, this set is a list of record. List relatively speaking, there are times when we need
to get a single object, get()a method that is used in this case:

>>>Publisher.objects.get(name="Apress")
<Publisher: Apress 2855 Telegraph Avenue>

If the query does not return results will throw an exception:

Publisher.objects.get(name='Aprs')

books.models.Publisher.DoesNotExist: Publisher matching query does not exist.

DoesNotExist Publisher exception is an attribute of the model class, that Publisher.DoesNotExist. In the application
, you can catch and handle the exception, like this:

try:    p = Publisher.objects.get(name='Apress')except Publisher.DoesNotExist:    print("Apress isn't in the database yet.")else:    print("Apress is in the database.")

If the result is more than one object, it will cause an exception:

>>>Publisher.objects.get(country="U.S.A.")

books.models.Publisher.MultipleObjectsReturned: get() returned more than one Publisher -- it returned 2!

Sorting data

Publisher.objects.order_by("name")

<QuerySet [<Publisher: Apress 2855 Telegraph Avenue>, <Publisher: O'Reilly 10 Fawcett St.>]>

If you need to sort a plurality of standard fields (second field is the same value used in the case of the first field), using multiple reference
numbers on it, as follows:

Publisher.objects.order_by("state_province", "address")

Reverse order, preceded by a minus (-) prefix

>>> Publisher.objects.order_by("‐name")

Most of the time you would normally only certain fields to be sorted. In such cases, Django lets you specify the default sort model:

class Publisher(models.Model):
    name = models.CharField(max_length=30)
    address = models.CharField(max_length=50)
    city = models.CharField(max_length=60)
    state_province = models.CharField(max_length=30)
    country = models.CharField(max_length=50)
    website = models.URLField()
    def __unicode__(self):
    return self.name
    class Meta:
        ordering = ['name']

Chain inquiry

Operate simultaneously filtering and sorting query

Publisher.objects.filter(country="U.S.A.").order_by("‐name")

SQL query is converted into a combination of WHERE and ORDER BY:

SELECT id, name, address, city, state_province, country, website
FROM books_publisher
WHERE country = 'U.S.A'
ORDER BY name DESC;

Limit returned data

It does not support negative indexes

Publisher.objects.order_by('name')[0]

Equivalent to

SELECT id, name, address, city, state_province, country, website
FROM books_publisher
ORDER BY name
LIMIT 1;
Publisher.objects.order_by('name')[0:2]

Equivalent to

SELECT id, name, address, city, state_province, country, website
FROM books_publisher
ORDER BY name
OFFSET 0 LIMIT 2;

Update multiple objects

save () method, which will update all the columns in the row. And in some cases, we only need to update a row in the columns.

>>> p = Publisher.objects.get(name='Apress')
>>> p.name = 'Apress Publishing'
>>> p.save()

The same in the following SQL statement (assuming ID for the Apress 52):

SELECT id, name, address, city, state_province, country, website
FROM books_publisher
WHERE name = 'Apress';
UPDATE books_publisher SET
name = 'Apress Publishing',
address = '2855 Telegraph Ave.',
city = 'Berkeley',
state_province = 'CA',
country = 'U.S.A.',
website = 'http://www.apress.com'
WHERE id = 52;

Django's save () method updates the value of not only the name column, as well as update all the columns. If the next column other than the name is likely to be changes to other processes, the only change the name column is obviously wiser. Changing a specified column, we can call the result set (QuerySet) object update () method:

Publisher.objects.filter(id=52).update(name='Apress Publishing')

With equivalent SQL statements become more efficient:

UPDATE books_publisher
SET name = 'Apress Publishing'
WHERE id = 52;

pdate () method is valid for any result sets (QuerySet), which means you can update multiple records simultaneously.

update () method returns an integer value representing the number of records affected.

>>> Publisher.objects.all().update(country='USA')
2

Deleting objects

Delete objects in the database simply call the object's delete () method can be

>>> p = Publisher.objects.get(name="O'Reilly")
>>> p.delete()

Call the delete () method to delete multiple records simultaneously

>>> Publisher.objects.filter(country='USA').delete()
>>> Publisher.objects.all().delete()

Common query method summary

  1. all (): the caller: objects manager returns queryset
  2. filter (): the caller: objects manager returns queryset
  3. get (): the caller: objects manager returns to query the object model (Note: query results and only one was executed)
  4. first (), last () method: caller: queryset return the object model
  5. exclude (): the caller: objects manager returns exclude queryset #
  6. order_by (): Called by queryset the object, the return value is queryset
  7. COUNT (): Count: queryset object returned by the calling int
  8. reverse (): Called by queryset the object, the return value is queryset
  9. exists (): returns the object to call queryset Boolean value # Existence
  10. values ​​() method: queryset called by the object, the return value is QuerySet
  11. values_list (): Called by queryset the object, the return value is queryset
  12. distinct (): Called by queryset the object, the return value is queryset # deduplication

values ​​() method

>>> Ebook.objects.filter(id = 1).values()
<QuerySet [{'id': 1, 'title': 'Python语言设计', 'publication_date': datetime.date(2016, 6, 13), 'price': Decimal('56.00'), 'publisher': '机械工业出版社'}]>
>>> Ebook.objects.filter(id = 1).values()[0]['title']
'Python语言设计'

values_list () method

>>> Ebook.objects.filter(id = 1).values_list()
<QuerySet [(1, 'Python语言设计', datetime.date(2016, 6, 13), Decimal('56.00'), '机械工业出版社')]>
>>> Ebook.objects.filter(id = 1).values_list()[0][1]
'Python语言设计'
Fuzzy query

Ebook.objects.filter(price__in=[100,200,300])

Ebook.objects.filter(price__gt=100) more than the

Ebook.objects.filter(price__gte=100) greater or equal to

Ebook.objects.filter(price__lt=100)Less than
Ebook.objects.filter(price__range=[100,200])100 to 200

Ebook.objects.filter(title__contains="python")

Ebook.objects.filter(title__icontains="python") i not case-sensitive

Ebook.objects.filter(title__startswith="py")

Ebook.objects.filter(publication_date__year=2012)

Guess you like

Origin www.cnblogs.com/notfind/p/11691507.html