The third stage: Django framework day63 Django-- tab and form assembly

The third stage: Django framework day63 Django-- tab and form assembly

A, Django implement bulk insert data

Requirements : inserting data into the tables Books in 1000

method one

for i in range(1000):  # 这种插入方式 效率极低
  models.Book.objects.create(title='第%s本书'%i)

Method Two

book_list = []
for i in range(100000):  # 时间还是很短  两者差距很大
   book_list.append(models.Book(title='第%s本书'%i))
   models.Book.objects.bulk_create(book_list)  # 批量插入数据

Two, Django achieve pager

Use of a custom finisher py file a new code copied directly past
core code (directly into the form of packets can)

class Pagination(object):
    def __init__(self, current_page, all_count, per_page_num=10, pager_count=11):
        """
        封装分页相关数据
        :param current_page: 当前页
        :param all_count:    数据库中的数据总条数
        :param per_page_num: 每页显示的数据条数
        :param pager_count:  最多显示的页码个数

        用法:
        queryset = model.objects.all()
        page_obj = Pagination(current_page,all_count)
        page_data = queryset[page_obj.start:page_obj.end]
        获取数据用page_data而不再使用原始的queryset
        获取前端分页样式用page_obj.page_html
        """
        try:
            current_page = int(current_page)
        except Exception as e:
            current_page = 1

        if current_page < 1:
            current_page = 1

        self.current_page = current_page

        self.all_count = all_count
        self.per_page_num = per_page_num

        # 总页码
        all_pager, tmp = divmod(all_count, per_page_num)
        if tmp:
            all_pager += 1
        self.all_pager = all_pager

        self.pager_count = pager_count
        self.pager_count_half = int((pager_count - 1) / 2)

    @property
    def start(self):
        return (self.current_page - 1) * self.per_page_num

    @property
    def end(self):
        return self.current_page * self.per_page_num

    def page_html(self):
        # 如果总页码 < 11个:
        if self.all_pager <= self.pager_count:
            pager_start = 1
            pager_end = self.all_pager + 1
        # 总页码  > 11
        else:
            # 当前页如果<=页面上最多显示11/2个页码
            if self.current_page <= self.pager_count_half:
                pager_start = 1
                pager_end = self.pager_count + 1

            # 当前页大于5
            else:
                # 页码翻到最后
                if (self.current_page + self.pager_count_half) > self.all_pager:
                    pager_end = self.all_pager + 1
                    pager_start = self.all_pager - self.pager_count + 1
                else:
                    pager_start = self.current_page - self.pager_count_half
                    pager_end = self.current_page + self.pager_count_half + 1

        page_html_list = []
        # 添加前面的nav和ul标签
        page_html_list.append('''
                    <nav aria-label='Page navigation>'
                    <ul class='pagination'>
                ''')
        first_page = '<li><a href="?page=%s">首页</a></li>' % (1)
        page_html_list.append(first_page)

        if self.current_page <= 1:
            prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
        else:
            prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1,)

        page_html_list.append(prev_page)

        for i in range(pager_start, pager_end):
            if i == self.current_page:
                temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)
            else:
                temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
            page_html_list.append(temp)

        if self.current_page >= self.all_pager:
            next_page = '<li class="disabled"><a href="#">下一页</a></li>'
        else:
            next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1,)
        page_html_list.append(next_page)

        last_page = '<li><a href="?page=%s">尾页</a></li>' % (self.all_pager,)
        page_html_list.append(last_page)
        # 尾部添加标签
        page_html_list.append('''
                                           </nav>
                                           </ul>
                                       ''')
        return ''.join(page_html_list)

The actual quote

#后端
    from app01.utils.mypage import Pagination
    # 使用封装好的分页器代码
    def login(request):
        book_queryset = models.Book.objects.all()
        current_page = request.GET.get('page',1)
        all_count = book_queryset.count()
        # 1.实例化产生对象
        page_obj = Pagination(current_page=current_page,all_count=all_count)
        # 2.对真实数据进行切片操作
        page_queryset = book_queryset[page_obj.start:page_obj.end]
        return render(request,'login.html',locals())
//前端
    {% for book_obj in page_queryset %}
        <p>{{ book_obj.title }}</p
    {% endfor %}
    {{ page_obj.page_html|safe }}

Three, Django three ways to create a table-many relationship

3.1 Automatic (recommended)

Django orm benefits that will automatically help you create a third table
, but it will help you create a relationship between two tables field will not add extra fields
is convenient but scalability third table of the poor can not be arbitrarily add additional fields
class Book (models.Model):
...
in the authors = models.ManyToManyField (to = 'Author')

​ class Author(models.Models):
...

3.2 Pure manual (not recommended)

The third benefit is that the tables can add any additional fields
downside is that a lot of time orm query methods are not supported when the query is very troublesome
class Book (models.Model):
...

class Author(models.Models):
...

class Book2Author(models.Model):
book_id = models.ForeignKey(to='Book')
author_id = models.ForeignKey(to='Author')
create_time = models.DateField(auto_now_add=True)
...

3.3 Semi-Automatic (recommended ******)

Manually build the table but you will tell orm third table is your own built
orm just give me provide a convenient method of inquiry
third orm Although you can use the query method
but does not support the use of
the Add ()
the SET ()
the Remove ()
the Clear ()

class Book(models.Model):
    ...
    authors = models.ManyToManyField(to='Author', through='Book2Author', through_fields=('book','author'))
class Author(models.Model):
    ...
    books = models.ManyToManyField(to='Book', through='Book2Author', through_fields=('author', 'book'))

class Book2Author(models.Model):
    book = models.ForeignKey(to='Book')
    author = models.ForeignKey(to='Author')
    create_time = models.DateField(auto_now_add=True)
    ...
# 1.半自动 一定要加两个额外的参数
    through='Book2Author', through_fields=('book','author')
# 2.后面字段的顺序
    由第三张表通过哪个字段查询单表 就把哪个字段放前面

In the design project must give their go backward to prevent subsequent iterations update

Four, form examination form (today focus)

Usually we use the form at the time of submission of the form to do, must do data validation, this check can also be front-end back-end verification. But the need to note that:

  • Check data parity typically have front and rear ends
  • But even then regressed distal optional check
  • Anyway, check the rear end also must have a word may have no front-end back-end verification must check! ! !

Usually we are doing back-end data submitted when the general has the following steps:

1. set up the front page >>> rendering the page
2. Obtain data validation >>> check the data submitted by the front-end user
3. Results of the data check presentation to the front page to display the error message users to view >>>

However, when we use a form components when it can automatically help us to complete the above three things

Next we look for how to use the components of the form

Use 4.1 form components

  • Write yourself a first class
from django import forms
class MyRegForm(forms.Form):
    username = forms.CharField(min_length=3,max_length=8)
    password = forms.CharField(min_length=3,max_length=8)
    email = forms.EmailField()
  • How to check data
from app01 import views
# 1.给自定义的类传一个字典
obj = views.MyRegForm({'username':'jason','password':'12','email':'123'})
# 2.判断数据是否全部合法
obj.is_valid()  # 只有数据全部符合要求才会是True
Out[4]: False
# 3.查看符合校验规则的数据
obj.cleaned_data
Out[5]: {'username': 'jason'}
# 4.查看不符合条件的数据以及不符合的原因是什么
obj.errors
Out[6]: 
{
    'password': ['Ensure this value has at least 3 characters (it has 2).'],
    'email': ['Enter a valid email address.']
 }
# 5.校验数据的时候 默认情况下类里面所有的字段都必须传值
obj = views.MyRegForm({'username':'jason','password':'123'})
obj.is_valid()
Out[12]: False
obj.errors
Out[13]: {'email': ['This field is required.']}
# 6.默认情况下可以多传 但是绝对不能少传
obj = views.MyRegForm({'username':'jason','password':'1233','email':'[email protected]','xxx':'ooo'})
obj.is_valid()
Out[15]: True
  • How to render the page

    forms components will help you render obtain user input (input, select, drop-down box ...) label the submit button you need to manually write

    <p>三种渲染前端页面的方式</p>
    <p>第一种渲染前端页面的方式:封装程度太高了 标签样式及参数不方便调整 可扩展性差(不推荐使用)
    {{ form_obj.as_p }}
    {{ form_obj.as_ul }}
    </p>
    
    <p>第二种渲染页面的方式:扩展性较高 不足之处在于 需要你手写的代码量比较多(不推荐使用)</p>
    <p>
        {{ form_obj.username.label }}{{ form_obj.username }}
    </p>
    <p>
        {{ form_obj.password.label }}{{ form_obj.password }}
    </p>
    <p>
        {{ form_obj.email.label }}{{ form_obj.email }}
    </p>
    
    <p>第三种渲染前端页面的方式:代码量和扩展性都很高(推荐使用)</p>
    {% for foo in form_obj %}
    <p>{{ foo.label }}{{ foo }}</p>
    {% endfor %}
  • How to display an error message

    如何取消前端帮我们做的校验 form表单中添加一个参数即可
    <form action="" method="post" novalidate>
    
    展示错误信息   用对象点errors.0
    <form action="" method="post" novalidate>
        {% for foo in form_obj %}
        <p>
            {{ foo.label }}:{{ foo }}
            <span style="color: red">{{ foo.errors.0 }}</span>
        </p>
        {% endfor %}
        <input type="submit">
    </form>
    
    
    from django import forms
    
    
    class MyRegForm(forms.Form):
        username = forms.CharField(min_length=3,max_length=8,label='用户名',
                                   error_messages={
                                       'min_length':'用户名最短三位',
                                       'max_length':'用户名最长八位',
                                       'required':'用户名不能为空'
                                   },initial='我是初始值',required=False
                                   )
        password = forms.CharField(min_length=3,max_length=8,label='密码',error_messages={
                                       'min_length':'密码最短三位',
                                       'max_length':'密码最长八位',
                                       'required':'密码不能为空'
                                   })
        email = forms.EmailField(label='邮箱',error_messages={
                'required':'邮箱不能为空',
                'invalid':'邮箱格式不正确'
        },required=False)

4.2 forms assembly hook function

For field we can also do an additional check, if you want to do this step, we need to hook function

The hook function is divided into partial hook and global hook

  • Local hooks

    # 当你需要对某一个字段数据进行额外的一些列校验 你可以考虑使用钩子函数
    # 针对单个字段的  使用局部钩子
    def clean_username(self):
        username = self.cleaned_data.get('username')
        if '金瓶x' in username:
            # 给username字段下面提示错误信息
            self.add_error('username','用户名不符合社会主义核心价值观')
        return username
  • Global hook

    # 针对多个字段的校验 使用全局钩子      eg:校验两次密码是否一致
    def clean(self):
        password = self.cleaned_data.get('password')
        confirm_password = self.cleaned_data.get('confirm_password')
        if not password == confirm_password:
            self.add_error('confirm_password','两次密码不一致')
        return self.cleaned_data

4.3 form the frame assembly to change the type attribute value input

 widget= widgets.TextInput()
    widget=widgets.PasswordInput()
如何让forms组件渲染出来的input框有form-control类属性
    widget= widgets.TextInput(attrs={'class':'form-control others'})  # 如果有多个类属性 空格隔开
    widget=widgets.PasswordInput(attrs={'class':'form-control others'})

4.4 form component supports regular check

from django import forms
from django.forms import Form
from django.core.validators import RegexValidator
 
class MyForm(Form):
    user = forms.CharField(
        validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
    )

Guess you like

Origin www.cnblogs.com/foreversun92/p/11761540.html