• 01 权限菜单显示

  • 02 Django路径的自动添加问题

  • 03 原生form实现增删改查

  • 04 modelform实现增删改查

01 权限菜单显示

1.1 优先查找项目中的templates,如果没有,然后再去查找应用中的templates下的模板文件;

 1.1.2 如果每个应用下都有相同名称的templates或者templatetags,会根据应用的创建顺序进行查找;

 1.1.3 为避免以上情况发生,建议在templates或者templatestags目录下分别建立应用名称,然后再放置.html模板文件或者my_tag.py文件;

整个项目的完整目录结构:

总结一下整个项目的开发流程:

  • 使用Pycharm创建项目,进行项目的命名
  • 使用Pycharm下的Tools》Run manage.py task启动shell窗口
  • startapp app01
  • startapp rbac(Role-Based Access Control,即基于角色的访问权限控制)详情见:https://baike.baidu.com/item/RBAC/1328788?fr=aladdin
  • settings.py配置文件进行TEMPLATES以及INSTALLED_APPS的添加配置;
  • urls.py的配置;
  • app01/views.py的配置;
  • rbac/models.py的配置并进行数据库迁移操作 makemigrations\migrate
  • rbac/admin.py的注册配置,并引入class类;
  • 进行程序的解耦合操作,进行rbac/service/permissions.py以及rbac/service/rbac.py的配置;
  • 进行自定义templatetags的自定义,my_tags.py的配置;
  • 分别添加base.html menu.html users.html roles.html 等模板文件,进行extends、include、block等方法进行关联;
  • 将基础模板文件从根目录的templates目录迁移至rbac/templates目录下

settings.py

"""
Django settings for s9day82_rbac project. Generated by 'django-admin startproject' using Django 1.11.1. For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/ For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/
""" import os # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '0s(th#!ewf^xik5n&bqkqqjadz#q*vt+!hq(kzk5*-!t6@^0^i' # SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01.apps.App01Config',
'rbac.apps.RbacConfig',
] MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'rbac.service.rbac.ValidPermission',
]
from django.middleware.security import SecurityMiddleware ROOT_URLCONF = 's9day82_rbac.urls' 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',
],
},
},
] WSGI_APPLICATION = 's9day82_rbac.wsgi.application' # Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
} # Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
] # Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/ STATIC_URL = '/static/'

urls.py

"""s9day82_rbac URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^users/$', views.users),
url(r'^users/add', views.add_user),
url(r'^users/delete/(\d+)', views.del_user),
url(r'^roles/', views.roles),
url(r'^login/', views.login),
]

views.py

import re
from django.shortcuts import render, HttpResponse # Create your views here. from rbac.models import *
from rbac.service.permissions import * class Per(object):
def __init__(self, actions):
self.actions = actions def add(self):
return "add" in self.actions def delete(self):
return "delete" in self.actions def edit(self):
return "edit" in self.actions def list(self):
return "list" in self.actions def users(request):
user_list = User.objects.all()
# permission_list = request.session.get("permission_list")
# print(permission_list) # ['/users/', '/users/add', '/users/delete/(\\d+)', '/users/edit/(\\d+)']
# 查询当前登录人的名字;
id = request.session.get("user_id")
user = User.objects.filter(id=id).first()
per = Per(request.actions) return render(request, "users.html", locals()) def add_user(request):
return HttpResponse("Add User......") def del_user(request, id):
return HttpResponse("Delete User..." + id) def roles(request):
role_list = Role.objects.all()
per = Per(request.actions)
return render(request, "roles.html", locals()) def login(request):
if request.method == "POST":
user_obj = request.POST.get("user")
pwd = request.POST.get("pwd")
user = User.objects.filter(name=user_obj, pwd=pwd).first()
if user:
# #################在session中注册用户ID###########################;
request.session["user_id"] = user.pk
initial_session(user, request)
'''
此处的values()相当于:
temp = []#定义一个空列表;
for role in user.roles.all();#values属性,相当于循环该对象[<Role: 保洁>, <Role: 销售>]>
temp.append({
"title":role.title,
"permissions__url":role.permissions.all()
})
'''
return HttpResponse("登录成功!")
return render(request, "login.html")

permissions.py

def initial_session(user, request):
# 方案1
# #################在session注册权限列表###########################;
# 查询当前登录用户的所有角色;
# ret = user.roles.all()
# print("ret", ret) # <QuerySet [<Role: 保洁>, <Role: 销售>]>
#
# # 查询当前用户的所有权限;
# permissions = user.roles.all().values(
# "permissions__url").distinct() # ret_role <QuerySet [{'permissions__url': '/users/'},
# # {'permissions__url': '/users/add'}]>
#
# # 进行数据的处理,生成列表;
# permission_list = []
# for item in permissions:
# permission_list.append(item["permissions__url"])
# print("permission_list", permission_list) # permission_list ['/users/', '/users/add']
#
# request.session["permission_list"] = permission_list # 方案2;
permissions = user.roles.all().values("permissions__url", "permissions__group_id", "permissions__action").distinct()
print("permissions ", permissions) # <QuerySet [{'permissions__url': '/users/',
# 'permissions__group_id': 1, 'permissions__action': 'list'}]>
permission_dict = {}
for item in permissions:
gid = item.get('permissions__group_id')
if not gid in permission_dict: permission_dict[gid] = {
"urls": [item["permissions__url"], ],
"actions": [item["permissions__action"], ]
}
else:
permission_dict[gid]["urls"].append(item["permissions__url"])
permission_dict[gid]["actions"].append(item["permissions__action"])
print(permission_dict)
request.session["permission_dict"] = permission_dict
# 注册菜单权限;
permissions = user.roles.all().values("permissions__url", "permissions__action",
"permissions__group__title").distinct()
print("permissions", permissions)
menu_permission_list = []
for item in permissions:
if item["permissions__action"] == "list":
menu_permission_list.append((item["permissions__url"], item["permissions__group__title"]))
print(menu_permission_list)
request.session["menu_permission_list"] = menu_permission_list

admin.py

from django.contrib import admin

# Register your models here.

from .models import *

class PerConfig(admin.ModelAdmin):
list_display = ["title", "url", "group", "action"] admin.site.register(User)
admin.site.register(Role)
admin.site.register(Permission, PerConfig)
admin.site.register(PermissionGroup)

rbac.py

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse, redirect
import re # 自定义中间件!
class ValidPermission(MiddlewareMixin):
def process_request(self, request):
# 当前访问权限;
current_path = request.path_info
# 1、校验权限,是否是与白名单;
valid_url_list = ["/login/", "/reg/", "/admin/.*"]
for valid_url in valid_url_list:
ret = re.match(valid_url, current_path)
if ret:
return None
user_id = request.session.get("user_id")
if not user_id:
return redirect("/login/")
# # 2、判断是否登录
# permission_list = request.session.get(
# "permission_list",
# []) # permission_list ['/users/', '/users/add', '/users/delete/(\\d+)', '/users/edit/(\\d+)']
#
# flag = False
# for permission in permission_list:
# permission = "^%s$" % permission
# ret = re.match(permission, current_path)
# if ret:
# flag = True
# break
# if not flag:
#
# return None
# 3、校验是否登录;
permission_dict = request.session.get("permission_dict")
for item in permission_dict.values():
urls = item['urls']
for reg in urls:
reg = "^%s$" % reg
ret = re.match(reg, current_path)
if ret:
print("actions", item['actions'])
request.actions = item['actions']
return None
return HttpResponse("没有访问权限!")

models.py

from django.db import models

# Create your models here.

class User(models.Model):
name = models.CharField(max_length=32)
pwd = models.CharField(max_length=32)
roles = models.ManyToManyField(to="Role") def __str__(self):
return self.name class Role(models.Model):
title = models.CharField(max_length=32)
permissions = models.ManyToManyField(to="Permission") def __str__(self):
return self.title class Permission(models.Model):
title = models.CharField(max_length=32)
url = models.CharField(max_length=32)
action = models.CharField(max_length=32, default="")
group = models.ForeignKey("PermissionGroup", default=1) def __str__(self):
return self.title class PermissionGroup(models.Model):
title = models.CharField(max_length=32) def __str__(self):
return self.title

base.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<style>
.header {
width: 100%;
height: 60px;
background-color: #336699; } .menu {
background-color: bisque;
position: fixed;
top: 60px;
bottom: 0;
left: 0;
width: 200px;
} .content {
position: fixed;
top: 60px;
bottom: 0;
right: 0;
left: 200px;
overflow: auto;
padding: 30px;
} .menu_btn {
font-size: 18px;
text-align: center;
padding: 50px 0;
}
</style>
</head>
<body>
<div class="header">
<p>{{ user.name }}</p>
</div>
<div class="contain">
{% load my_tags %}
<div class="menu">
{% get_menu request %}
</div>
<div class="content ">
{% block con %} {% endblock %}
</div> </div>
</body>
</html>

menu.html

<div>
{% for item in menu_permission_list %}
<p class="menu_btn"><a href="{{ item.0 }}">{{ item.1 }}</a></p>
{% endfor %}
</div>

users.html

{% extends 'base.html' %}
{% block con %}
<h4>用户列表</h4>
{% if per.add %}
<a href="/users/add/" class="btn btn-primary">添加用户</a>
{% endif %} <table class="table table-bordered table-striped">
<thead>
<tr>
<th>序号</th>
<th>姓名</th>
<th>角色</th>
<th>操作</th>
</tr>
</thead>
<tbody> {% for user in user_list %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ user.name }}</td>
<td>
{% for role in user.roles.all %}
{{ role.title }}
{% endfor %}
</td>
<td>
{% if per.delete %}
<a href="/users/delete/{{ user.pk }}" class="btn btn-danger">删除</a>
{% endif %}
{% if per.edit %}
<a href="/users/edit/{{ user.pk }}" class="btn btn-info">编辑</a>
{% endif %}
</td>
</tr>
{% endfor %} </tbody>
</table>
{% endblock %}

login.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h4>登录页面</h4> <form action="" method="post">
{% csrf_token %}
用户名:<input type="text" name="user">
密码:<input type="password" name="pwd">
<input type="submit">
</form>
</body>
</html>

my_tags.py

from django import template

register = template.Library()

@register.inclusion_tag("menu.html")
def get_menu(request, ):
# 获取当前用户可以放到菜单栏中的权限;
menu_permission_list = request.session["menu_permission_list"]
return {"menu_permission_list": menu_permission_list}

02 Django路径的自动添加问题

2.1 settings.py文件中,APPEND_SLASH默认值为True;

2.2 在setings.py中,将APPEND_SLASH调整为False;

#设置项是否开启URL访问地址后面不为/跳转至带有/的路径;

03 原生form实现增删改查

3.1 创建Django项目并制定Python解释器下安装的Django==“1.11.1” version;

3.2 基于form实现的图书管理系统的增删改查步骤;

  • 创建django项目并指定app及Python内置解释器;
  • 检查settings.py是否配置了TEMPLATES以及INSTALLED_APPS;
  • 配置urls.py;
  • 编写视图函数views.py;
  • 编写ORM——models.py;
  • 进行admin.py的注册;
  • 通过Pycharm下的Run manage.py task进行数据库的迁移以及createsuperuser操作;
  • 编写模板——add.html\books.html\edit.html;

urls.py;

"""FormsDemo URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.conf.urls import url, include
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin
from app01 import views urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^books/', views.books),
url(r'^book/add', views.add_book),
url(r'^book/edit/(\d+)', views.edit_book),
]

views.py;

from django.shortcuts import render, redirect

# Create your views here.
from .models import * def books(request):
book_list = Book.objects.all()
return render(request, "books.html", locals()) def add_book(request):
if request.method == "POST":
title = request.POST.get("title")
price = request.POST.get("price")
date = request.POST.get("date")
publish_id = request.POST.get("publish_id")
author_pk_list = request.POST.getlist("author_pk_list")
book_obj = Book.objects.create(title=title, price=price, date=date, publish_id=publish_id)
book_obj.authors.add(*author_pk_list)
return redirect('/books/') publish_list = Publish.objects.all()
author_list = Author.objects.all()
return render(request, "add.html", locals()) def edit_book(request, edit_book_id):
if request.method == "POST":
title = request.POST.get("title")
price = request.POST.get("price")
date = request.POST.get("date")
publish_id = request.POST.get("publish_id")
author_pk_list = request.POST.getlist("author_pk_list") Book.objects.filter(pk=edit_book_id).update(title=title, price=price, date=date, publish_id=publish_id)
book_obj = Book.objects.filter(pk=edit_book_id).first()
book_obj.authors.set(author_pk_list)
return redirect('/books/')
edit_book = Book.objects.filter(pk=edit_book_id).first()
publish_list = Publish.objects.all()
author_list = Author.objects.all()
return render(request, "edit.html", locals())

models.py;

from django.db import models

# Create your models here.

class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8, decimal_places=2) # 999999.99
date = models.DateField()
publish = models.ForeignKey("Publish")
authors = models.ManyToManyField("Author") def __str__(self):
return self.title class Publish(models.Model):
name = models.CharField(max_length=32) def __str__(self):
return self.name class Author(models.Model):
name = models.CharField(max_length=32) def __str__(self):
return self.name

admin.py;

from django.contrib import admin

# Register your models here.
from .models import * admin.site.register(Book)
admin.site.register(Author)
admin.site.register(Publish)

books.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Books</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<a href="/book/add"><button>添加书籍</button></a>
<ul>
<table border="">
{% for book in book_list %}
<tr>
<td>{{ book.title }}</td>
<td>{{ book.price }}</td>
<td>{{ book.date|date:"Y-m-d" }}</td>
<td>{{ book.publish.name }}</td>
<td>{{ book.authors.all }}</td>
<td><a href="/book/edit/{{ book.pk }}"><button>编辑</button></a></td>
</tr>
{% endfor %} </table>
</ul>
</body>
</html>

add.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>add</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h3>添加页面</h3>
<form action="" method="post">
{% csrf_token %}
<p>书籍名称<input type="text" name="title"></p>
<p>价格<input type="text" name="price"></p>
<p>日期<input type="date" name="date"></p>
<p>出版社
<select name="publish_id" id="">
{% for publish in publish_list %}
<option value="{{ publish.pk }}">{{ publish.name }}</option>
{% endfor %}
</select>
</p>
<p>作者
<select name="author_pk_list" id="" multiple>
{% for author in author_list %}
<option value="{{ author.pk }}">{{ author.name }}</option>
{% endfor %} </select>
</p>
<input type="submit">
</form>
</body>
</html>

edit.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>add</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h3>编辑页面</h3>
<form action="" method="post">
{% csrf_token %}
<p>书籍名称<input type="text" name="title" value="{{ edit_book.title }}"></p>
<p>价格<input type="text" name="price" value="{{ edit_book.price }}"></p>
<p>日期<input type="date" name="date" value="{{ edit_book.date|date:"Y-m-d" }}"></p>
<p>出版社
<select name="publish_id" id="">
{% for publish in publish_list %}
{% if edit_book.publish == publish %}
<option selected value="{{ publish.pk }}">{{ publish.name }}</option>
{% else %}
<option value="{{ publish.pk }}">{{ publish.name }}</option>
{% endif %}
{% endfor %}
</select>
</p>
<p>作者
<select name="author_pk_list" id="" multiple>
{% for author in author_list %}
{% if author in edit_book.authors.all %}
<option selected value="{{ author.pk }}">{{ author.name }}</option>
{% else %}
<option value="{{ author.pk }}">{{ author.name }}</option>
{% endif %} {% endfor %} </select>
</p>
<input type="submit">
</form>
</body>
</html>

04 modelform实现增删改查

4.1 使用forms组件代替form表单;

class BookForm(forms.Form):
title = forms.CharField(max_length=32, label="书籍名称")
price = forms.DecimalField(max_digits=8, decimal_places=2, label="价格") # 999999.99
date = forms.DateField(label="日期",
widget=widgets.TextInput(attrs={"type": "date"})
)
# gender = forms.ChoiceField(choices=((1, "男"), (2, "女"), (3, "其他"),))
# publish = forms.ChoiceField(choices=Publish.objects.all().values_list("pk", "name"))
publish = forms.ModelChoiceField(queryset=Publish.objects.all())
authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all())

4.2 基于ModelForm进行精简开发;

views.py

from django.shortcuts import render, redirect

# Create your views here.
from .models import *
from django import forms
from django.forms import widgets
from django.forms import ModelForm
from django.forms import widgets as wid '''
class BookForm(forms.Form):
title = forms.CharField(max_length=32, label="书籍名称")
price = forms.DecimalField(max_digits=8, decimal_places=2, label="价格") # 999999.99
date = forms.DateField(label="日期",
widget=widgets.TextInput(attrs={"type": "date"})
)
# gender = forms.ChoiceField(choices=((1, "男"), (2, "女"), (3, "其他"),))
# publish = forms.ChoiceField(choices=Publish.objects.all().values_list("pk", "name"))
publish = forms.ModelChoiceField(queryset=Publish.objects.all())
authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all())
''' class BookForm(ModelForm):
class Meta:
model = Book
fields = "__all__"
# fields = ["title", "price"]
labels = {
"title": "书籍名称",
"price": "价格",
"date": "书籍日期",
"publish": "出版社",
"authors": "作者",
}
widgets = {
"title": wid.TextInput(attrs={"class": "form-control"}),
"price": wid.TextInput(attrs={"class": "form-control"}),
"date": wid.TextInput(attrs={"class": "form-control"}),
"publish": wid.TextInput(attrs={"class": "form-control"}),
"authors": wid.TextInput(attrs={"class": "form-control"}),
} def books(request):
book_list = Book.objects.all()
return render(request, "books.html", locals()) def add_book(request):
if request.method == "POST":
form = BookForm(request.POST)
if form.is_valid():
form.save()
return redirect("/books/")
form = BookForm()
return render(request, "add.html", locals()) def edit_book(request, edit_book_id):
edit_book = Book.objects.filter(pk=edit_book_id).first()
if request.method == "POST":
form = BookForm(request.POST, instance=edit_book)
form.save()
return redirect("/books/")
form = BookForm(instance=edit_book)
return render(request, "edit.html", locals())

add.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>add</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<h3>添加页面</h3>
<div class="col-md-4 col-md-offset-3">
{% include 'form.html' %}
</div> </body>
</html>

books.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Books</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<a href="/book/add"><button>添加书籍</button></a>
<ul>
<table border="1">
{% for book in book_list %}
<tr>
<td>{{ book.title }}</td>
<td>{{ book.price }}</td>
<td>{{ book.date|date:"Y-m-d" }}</td>
<td>{{ book.publish.name }}</td>
<td>{{ book.authors.all }}</td>
<td><a href="/book/edit/{{ book.pk }}"><button>编辑</button></a></td>
</tr>
{% endfor %} </table>
</ul>
</body>
</html>

edit.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>add</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h3>编辑页面</h3>
{% include 'form.html' %}
</body>
</html>

form.html

<form action="" method="post" novalidate>
{% csrf_token %}
{% for field in form %}
<div>
{{ field.label }}
{{ field }}
</div>
{% endfor %} <input type="submit">
</form>

Python-S9——Day84-ORM项目实战之权限、form以及modelform的更多相关文章

  1. Asp.Net Core 项目实战之权限管理系统(3) 通过EntityFramework Core使用PostgreSQL

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

  2. Asp.Net Core 项目实战之权限管理系统(4) 依赖注入、仓储、服务的多项目分层实现

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

  3. Asp.Net Core 项目实战之权限管理系统(0) 无中生有

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

  4. Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

  5. Asp.Net Core 项目实战之权限管理系统(2) 功能及实体设计

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

  6. Asp.Net Core 项目实战之权限管理系统(5) 用户登录

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

  7. Asp.Net Core 项目实战之权限管理系统(6) 功能管理

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

  8. Asp.Net Core 项目实战之权限管理系统(7) 组织机构、角色、用户权限

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

  9. Net Core 项目实战之权限管理系统(0)

    0 前言 Net Core 项目实战之权限管理系统(0) 无中生有   0 http://www.cnblogs.com/fonour/p/5848933.html 学习的最好方法就是动手去做,这里以 ...

  10. Asp.Net Core 项目实战之权限管理系统(8) 功能菜单的动态加载

    0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...

随机推荐

  1. 签证-L1/L2

    http://blog.sina.com.cn/s/blog_7664b7f70102uweb.html 14年4月我接到公司通知,要从MICROSTRATEGY中国研发中心内部transfer到美国 ...

  2. mysqlbench使用

    看见不少人问mysqlbench怎么用,这个好像没什么困难的,基本看的懂英文就可以使用了,感觉像使用word一样. 下载地址http://www.mysql.com/products/workbenc ...

  3. HDU3308 线段树区间合并

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3308 ,简单的线段树区间合并. 线段树的区间合并:一般是要求求最长连续区间,在PushUp()函数中实 ...

  4. UVA 10564 Paths through the Hourglass(背包)

    为了方便打印路径,考虑从下往上转移.dp[i][j][S]表示在i行j列总和为S的方案, dp[i][j][S] = dp[i+1][left][S-x]+dp[i+1][right][S-x] 方案 ...

  5. 基于Dockerfile 构建redis5.0.0(包括持久化)及RedisDestopManager 监控

    一 创建Dockerfile [root@zxmrlc docker]# mkdir redis [root@zxmrlc docker]# cd redis && touch Doc ...

  6. linux用命令行运行matlab的.mat文件

    入m文件所在目录后,运行 $ matlab -nodesktop -nosplash -r matlabfile 只用文件名matlabfile,不能添加.m

  7. java程序换图标

    ImageIcon img = new ImageIcon("D:\\mahou-in-action\\ShiJuanFenXi\\src\\zoom-in.png"); inst ...

  8. HTML复选框checkbox默认样式修改

    此方法可以将复选框的默认样式替换成任意样式.如图: 未选择: 选择时: 思路:将复选框隐藏,利用lebal元素的焦点传递特性,用lebal的样式替代复选框. 代码如下: <!DOCTYPE ht ...

  9. Arguments Optional-freecodecamp算法题目

    Arguments Optional 1.要求 创建一个计算两个参数之和的 function.如果只有一个参数,则返回一个 function,该 function 请求一个参数然后返回求和的结果. 如 ...

  10. 牛客小白月赛5 F 圆(circle) 【欧拉定理】

    题目连接: https://www.nowcoder.com/acm/contest/135/F 签到题来了,送你们一个Python秒的题. Apojacsleam来到了OI大陆,经过了连年征战,成为 ...