Quy tắc và Tối ưu hóa trong Django

  1. Quy tắc và Cấu trúc

Các lợi ích của việc thiết lập quy tắc:

  • Tăng tính dễ đọc của mã nguồn
  • Giúp dễ dàng định vị và tìm kiếm mã
  • Đơn giản hóa quá trình mở rộng mã trong tương lai

Trong trường hợp có nhiều ứng dụng (app) và mỗi app có nhiều chức năng URL, bạn có thể tổ chức code như sau:

Chia nhỏ các views thành các module khác nhau, và đặt tên cho các hàm theo cách tương tự với thư mục templates.

from cmdb.views import account
from cmdb.views import home
from cmdb.views import asset

urlpatterns = [
    # Chức năng tài khoản
    url(r'^login/$', account.login),
    url(r'^logout/$', account.logout),

    # Chức năng home
    url(r'^index/$', home.index),

    # Chức năng quản lý tài sản
    url(r'^lists/$', asset.lists),
    url(r'^save_hostinfo/$', asset.save_hostinfo),
    url(r'^del_hostinfo/$', asset.del_hostinfo),
    url(r'^add/$', asset.add),

    # URL mặc định
    url(r'', account.login),
]

Với form, cũng nên tạo các file riêng biệt để tổ chức tốt hơn.

  1. Tối ưu hóa Nhập tệp tĩnh

Khi nhập các tệp CSS và JS, chúng ta thường làm như sau:

{#CSS#}
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet"  href="/static/plugins/bootstrap/css/bootstrap.min.css"/>
    <link rel="stylesheet"  href="/static/plugins/font-awesome/css/font-awesome.min.css"/>
    <link rel="stylesheet"  href="/static/css/commons.css"/>
    <link rel="stylesheet"  href="/static/css/account.css"/>
</head>

{#JS#}
<script src='/static/js/jquery-1.8.2.min.js'></script>
<script src='/static/js/valid.js'></script>

Đường dẫn static được cấu hình trong settings.py:

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

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',
                'django.core.context_processors.static',
            ],
        },
    },
]

Nếu muốn thay đổi đường dẫn static thành content, chỉ cần thay đổi STATIC_URL trong settings.py.

{#CSS#}
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet"  href="{{ STATIC_URL }}plugins/bootstrap/css/bootstrap.min.css"/>
    <link rel="stylesheet"  href="{{ STATIC_URL }}plugins/font-awesome/css/font-awesome.min.css"/>
    <link rel="stylesheet"  href="{{ STATIC_URL }}css/commons.css"/>
    <link rel="stylesheet"  href="{{ STATIC_URL }}css/account.css"/>
    <link rel="stylesheet"  href="{{ STATIC_URL }}css/login.css"/>
</head>

{#JS#}
<script src='{{ STATIC_URL }}js/jquery-2.1.4.min.js'></script>
<script src='{{ STATIC_URL }}js/valid.js'></script>

Một cách khác là sử dụng simple_tag để nhập tệp:

{% load staticfiles %}
<script src='{% static "js/jquery-2.1.4.min.js" %}'></script>
  1. Form

Để tránh sự nhầm lẫn, chúng ta có thể sử dụng alias cho các module:

from cmdb.forms import account as AccountForm

3.1. Lưu dữ liệu từ Form

Khi người dùng nhập sai thông tin, dữ liệu đã được gửi đi, nhưng nếu họ phải nhập lại tất cả, điều này không thân thiện. Ví dụ:

def login(request):
    login_form = AccountForm.LoginForm(request.POST)
    if request.method == 'POST':
        if login_form.is_valid():
            username = request.POST.get('username')
            password = request.POST.get('password')
            user_info_list = models.UserInfo.objects.all()
            for i in user_info_list:
                if username == i.email and password == i.passwords:
                    request.session['auth_user'] = username
                    return redirect('/index/')
            else:
                return render(request, 'account/login.html', {'model': login_form, 'backend_autherror': 'Tên người dùng hoặc mật khẩu không chính xác'})
        else:
            error_msg = login_form.errors.as_data()
            return render(request, 'account/login.html', {'model': login_form, 'errors': error_msg})
    return render(request, 'account/login.html', {'model': login_form})

3.2. Hiển thị lỗi từ Form

Có 3 loại lỗi phổ biến:

  • error_msg = errors
  • error_msg = errors.as_json()
  • error_msg.as_ul()

Khi trả về dữ liệu cho Ajax, chúng ta không thể trả về đối tượng, nhưng có thể sử dụng error_msg = errors.as_json().

print(type(login_form.errors))
print(type(login_form.errors.as_json()))

Kết quả:

<class 'django.forms.utils.ErrorDict'> <type 'str'>

Để hiển thị lỗi trong template, sử dụng simple_tag:

@register.simple_tag
def error_message(arg):
    if arg: 
        return arg[0][0]
    else:
        return ''

3.3. Cập nhật FormSelect

Để cập nhật select tag, sử dụng __init__ method:

class ImportForm(forms.Form):
    host = forms.IntegerField(widget=forms.Select())

    def __init__(self, *args, **kwargs):
        super(ImportForm, self).__init__(*args, **kwargs)
        f = open('db_admin')
        data = f.read()
        data_tuple = json.loads(data)
        f.close()
        self.fields['host'].widget.choices = data_tuple
  1. Model

Django sử dụng ORM (Object Relational Mapping) để thao tác với cơ sở dữ liệu. Các lớp trong ORM đại diện cho các bảng, và các đối tượng từ lớp đó đại diện cho các dòng dữ liệu.

class UserInfo(models.Model):
    username = models.CharField(max_length=64)
    email = models.EmailField(max_length=64, null=True)
    email2 = models.EmailField(max_length=64, default="luotianshuai@qq.com")

4.1. Thêm, Sửa, Xóa, và Truy vấn

# Thêm
models.UserInfo.objects.create(username='luotianshuai', password='dashuaige')

# Truy vấn
models.UserInfo.objects.filter(name='seven')

# Xóa
models.UserInfo.objects.filter(name='seven').delete()

# Sửa
models.UserInfo.objects.filter(username='update_username').update(**user_input)

4.2. Truy vấn nâng cao

Sử dụng double underscore (__) để truy vấn phức tạp:

# Số lượng
models.UserInfo.objects.filter(name='seven').count()

# Lớn hơn, nhỏ hơn
models.UserInfo.objects.filter(id__gt=1)
models.UserInfo.objects.filter(id__lt=10)

# In
models.UserInfo.objects.filter(id__in=[11, 22, 33])

# Contains
models.UserInfo.objects.filter(name__contains="ven")

# Range
models.UserInfo.objects.filter(id__range=[1, 2])

# Sắp xếp
models.UserInfo.objects.filter(name='seven').order_by('id')
models.UserInfo.objects.filter(name='seven').order_by('-id')

# Phân trang
models.UserInfo.objects.all()[10:20]

# Nhóm
from django.db.models import Count, Min, Max, Sum
models.UserInfo.objects.all().values('name').annotate(content=Count('scores'))
  1. Liên kết giữa các Model
  • One-to-Many: models.ForeignKey(OtherModel)
  • Many-to-Many: models.ManyToManyField(OtherModel)
  • One-to-One: models.OneToOneField(OtherModel)

Ví dụ:

class UserGroup(models.Model):
    caption = models.CharField(max_length=64)

class Host(models.Model):
    hostname = models.CharField(max_length=64)
    ip = models.CharField(max_length=64)
    user_group = models.ForeignKey(UserGroup, on_delete=models.CASCADE)

Thêm và truy vấn:

# Thêm
models.UserGroup.objects.create(caption='CEO')
models.Host.objects.create(hostname='a01.shuaige.com', ip='1.1.1.1', user_group=models.UserGroup.objects.get(id=1))

# Truy vấn
models.Host.objects.filter(user_group__caption='CEO')

Thẻ: Django orm form model Static Files

Đăng vào ngày 20 tháng 7 lúc 00:38