django's routing layer

Keywords: Python Django Database

Catalog

How to establish orm table relationship

One-on-one

There are too many field information in a table. You can manually separate a table

One to many

The foreign key field is built on the side of many

Many to many

Many to many foreign key relationships need a third table for special processing

Take the library system as an example to create the book list, author list and publishing house list

Taking the book management system as an example, establish table relationships in django orm:

  • For a one-to-one table relationship, foreign key fields can be built on either side, but it is recommended to build on the side with higher query frequency
  • The book and publishing house are one to many relationships, and the book is one side of many, so the foreign key field is built in the book table
  • The relationship between the book and the author is many to many. The foreign key field can be built on either side. It is recommended to build on the side with high query frequency
class Book(models.Model):
    title = models.CharField(max_length=32)
    # Eight decimal places in total, two decimal places
    price = models.DecimalField(max_digits=8, decimal_places=2)

    # The book and publishing house are one to many relationships, and the book is one side of many, so the foreign key field is built in the book table
    publish = models.ForeignKey(to='Publish')  # To is used to indicate which table is related to. By default, the primary key field is associated

    # The relationship between the book and the author is many to many. The foreign key field can be built on either side. It is recommended to build on the side with high query frequency
    author = models.ManyToManyField(to='Author')  # django orm will automatically help you create the third relationship table between the book and the author
    # The author field is a virtual field that can't be displayed in the table. It just tells orm to establish the third table relationship


class Publish(models.Model):
    title = models.CharField(max_length=32)
    email = models.EmailField()


class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    # For a one-to-one table relationship, foreign key fields can be built on either side, but it is recommended to build on the side with higher query frequency
    author_detail = models.OneToOneField(to='Author_detail')


class Author_detail(models.Model):
    phone = models.BigIntegerField()
    addr = models.CharField(max_length=32)

Note:

  • When one to many foreign key fields are created, they will be synchronized to the database, and the table fields will be automatically suffixed with "u id"; if you add "u id", another "u id" will be added later
  • publish = models.ForeignKey(to='Publish ') the primary key id is associated by default. If the primary key is not an id, you can associate it yourself by adding to field = to the specified field

django request lifecycle flowchart

url.py routing layer

urlpatterns = [
    url(r'^admin/', admin.site.urls), 
    url(r'test/', views.test), 
    url(r'testadd/', views.testadd)
]

If url.py is written in this way, the access path of test and testadd suffixes will return the same content for the following reasons:

  • The first parameter of url is a regular expression
  • Once it is ending immediately, the expression can match the content. It will immediately end the matching relationship and directly execute the subsequent corresponding function

Route matching

Start django, enter 127.0.0.1:8000/test in the browser, django will automatically add slash.

django matching routing law

Without slash (127.0.0.1:8000/test), first try to match. If it doesn't match, the browser will be redirected. Add a slash (127.0.0.1:8000/test /) to match again. If it doesn't match, an error will be reported.

Cancel the function of django to automatically slash the browser

In the configuration file, add:

APPEND_SLASH = False   # This parameter defaults to True

Restrict the url of the specified input

urlpatterns = [
    url(r'^admin/', admin.site.urls),   # The first parameter of url is a regular expression
    url(r'^test/$', views.test),  # Once it is ending immediately, the expression can match the content. It will immediately end the matching relationship and directly execute the subsequent corresponding function
    url(r'^testadd/$', views.testadd)
]

In this way, only 127.0.0.1:8000/test / or 127.0.0.1:8000/testadd can be entered/

Note: route matching only matches the URL part, and does not match the parameter after the parameter carried by get

Anonymous group

Anonymous grouping of regular expressions

urlpatterns = [
    url(r'^admin/', admin.site.urls),   
    url(r'^test/([0-9]{4})', views.test),   # Four numbers after test
    url(r'^testadd/', views.testadd)
]

When there is a regular expression in a packet in your route, when matching to the content to execute the view function, the content matched by the regular expression in the packet will be passed to the view function as a location parameter.

# In view function
def test(request, xxx):
    print('Redundant parameters:', xxx)
    return HttpResponse('test view')

Named grouping

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^test/(\d+)/', views.test), 
    url(r'^testadd/(?P<year>\d+)/', views.testadd)    # Regular expression name grouping
]

When there are packets in your route and the packets are aliased, when matching the contents, the contents matched by regular expressions in the packets will be passed to the view function as key parameters

# In view function
def test(request, year):
    print('Redundant parameters:', year)
    return HttpResponse('test view')

In this way, we can take advantage of the grouping of name and nameless, and we can pass additional parameters to the function before calling the view function

Note: name grouping and nameless grouping cannot be mixed, but in the same case, nameless grouping can be used multiple times, also known as namegrouping can also be used multiple times

Backward analysis

for instance:

# urls.py
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^test/(\d+)/', views.test),
    url(r'^testadd/(?P<year>\d+)/', views.testadd),
    url(r'^index/', views.index),
    url(r'^home/', views.home),
]


# views.py
def index(request):
    return render(request, 'index.html')


def home(request):
    return HttpResponse('home')

In the above code, there are many jump links in the index.html page, all pointing to the home route. If you want to change the url address of your home, many links in the index.html page will change. Is there a way to bind the url address dynamically? Reverse parsing is.

Definition

Reverse parsing: dynamically parse a result according to an alias, which can directly access the corresponding url

There is no regular expression in the route, which is directly written to death

url(r'^home/', views.home,name='xxx'),   # Alias the corresponding relationship between route and view function

Front end reverse parsing

<p><a href="{% url 'xxx'%}">111</a></p>

Back end reverse parsing

from django.shortcuts import render,HttpResponse,redirect,reverse

def get_url(request):
    url = reverse('xxx')
    print(url)
    return HttpResponse('get_url')

Reverse analysis of nameless grouping

When parsing, you need to manually specify what the regular matching content is

url(r'^home/(\d+)/', views.home, name='xxx'),

Front end reverse parsing

<p><a href="{% url 'xxx' 12 %}">111</a></p>

Back end reverse parsing

def get_url(request):
    url = reverse('xxx', args=(1,))
    url2 = reverse('xxx', args=(1231,))
    print(url)
    print(url2)
    return HttpResponse('get_url')

The parameters passed in manually only need to be matched by regular expressions

Reverse parsing of named groups

url(r'^home/(?P<year>\d+)/', views.home, name='xxx'),

Front end reverse parsing

Can be grouped directly with nameless

<p><a href="{% url 'xxx' 12 %}">111</a></p>

Standard writing:

<p><a href="{% url 'xxx' year=121 %}">111</a></p>

Back end reverse parsing

Can be grouped directly with nameless

You can also write:

def get_url(request):
    url = reverse('xxx', kwargs={'year': 13123})
    print(url)
    return HttpResponse('get_url')

Taking editing function as an example, the application of reverse parsing

# urls.py
url = (r'^edit_user/(\d+)/', views.edit_user, name='edit')

# views.py
def edit_user(request, edit_id):  # Edit? ID is the primary key value of the data that the user wants to edit
    pass
<!--page-->
{% for user_obj in user_list %}
<a href='/edit_user/{{user_obj.id}}/'>edit</a>
<a href='{% url 'edit' user_obj.id %}'>edit</a>
{% endfor %}

Routing dissemination

Premise:

All app s in django can have their own urls.py \ templates \ static
 It is because of the above characteristics that you can use django development project to completely achieve group development of multiple people without interfering with each other, and each person only develops their own app
 The team leader only needs to integrate all the app s developed by everyone into an empty django project,
Then register in the settings configuration file and use routing distribution to integrate multiple app s to complete the splicing of large projects

Routing distribution solves the problem that there are too many routing matching relationships in the project,

Using route distribution, you will see:

  • The total route no longer does matching work, but only does task distribution
  • After the request comes, the total route does not have a corresponding relationship. Only ask which app function you want to access and then forward the request to the corresponding app for processing

Use:

Total route (include)

Just import urls.py of all app s

from django.conf.urls import url, include
from app01 import urls as app01_urls
from app02 import urls as app02_urls


urlpatterns = [
    url(r'^app01/', include(app01_urls)),
    url(r'^app02/', include(app02_urls)),
]
# Routing dissemination

Subrouter

# app01 urls.py
from django.conf.urls import url
from app01 import views


urlpatterns = [
    url(r'^reg/', views.reg),

]


# app02 urls.py
from django.conf.urls import url
from app02 import views


urlpatterns = [
    url(r'^reg/', views.reg),

]

The easiest way to write:

# Not even import
url(r'^app01/',include('app01.urls')),
url(r'^app02/',include('app02.urls'))

Namespace (namespace)

When there is an alias conflict in multiple apps, you can create a namespace for each app when you do routing distribution
Then you can choose which namespace to search for aliases in reverse resolution

In the total route:

url(r'^app01/',include('app01.urls',namespace='app01')),
url(r'^app02/',include('app02.urls',namespace='app02'))

Front end:

<a href="{% url 'app01:reg' %}"></a>
<a href="{% url 'app02:reg' %}"></a>

Backend:

print(reverse('app01:reg'))
print(reverse('app02:reg'))

But it's not necessary. You just need to make sure that there is no conflict in the whole django project when you start aliasing

Pseudo static

It is to disguise a dynamic web page as a static web page, which can facilitate the search engine SEO (Search Engine Optimization) and improve the collection strength of the search engine.

virtual environment

  • Every time you create a virtual environment, it's like you download a pure python interpreter again

  • After that, you can install more than N virtual environments on one machine

django version difference

In urls.py, there are differences in the way of path matching

Django version 1.xx

url is used.

from django.conf.urls import url
urlpatterns = [
    url(r'^reg.html',views.reg,name='app01_reg')
]

Django version 2.xx

It's path

from django.urls import path

urlpatterns = [
    path('admin/', admin.site.urls),
]
  • The first parameter of path here is neither regular nor regular
  • Django 2. X also has a re path method, which is the url in Django 1. X
  • path provides five converters to automatically convert the matched data to the corresponding type
  • Custom converters are also supported

django backend get file object

What should be paid attention to in form expression

  • method must be changed to post
  • Change enctype to formdata format
# urls.py
from django.conf.urls import url
from app02 import views


urlpatterns = [
    url(r'^upload/', views.upload)
]


# views.py
def upload(request):
    if request.method == 'POST':
        print(request.FILES)   # django will automatically put the data of file type into request.FILES
        file_obj = request.FILES.get('myfile')  # File object
        # print(file_obj)
        # print(file_obj.name)
        with open(file_obj.name, 'wb') as f:
            for line in file_obj:
                f.write(line)
    return render(request, 'upload.html')

Posted by ganeshcp on Mon, 25 Nov 2019 11:31:01 -0800