一、需求及注意事项

需求:
1.列出图书列表、出版社列表、作者列表
2.点击作者,会列出其出版的图书列表
3.点击出版社,会列出其下的图书列表
4.可以创建、修改、删除 图书、作者、出版社

完成及注意事项:
1.注册
/register/
2.登录
/login/
3.注销
/logout/
4.图书列表
/book_list/
/add_book/
/update_book/303/
/del_book/
5.出版社列表
/publisher_list/
/add_publisher/
/update_publisher/105/
/update_book/306/105/publisher/ # 通过出版社,修改该书,之后返回出版社页面
/del_publisher/
/book_list/105/publisher/ # 通过出版社,查看该出版社得图书列表
/add_book/105/publisher/ # 通过出版社,增加该出版社得某本书
/del_book/105/publisher/ # 通过出版社,删除该出版社得某本书
6.作者列表
/author_list/
/add_author/
/update_author/67/
/update_book/307/67/author/ # 通过作者,修改该书,之后返回作者页面
/del_author/
/book_list/67/author/ # 通过作者,查看该作者得图书列表
/add_book/67/author/ # 通过作者,增加该作者得某本书
/del_book/67/author/ # 通过作者,删除该作者得某本书

7.验证是否登录(session),跳转到之前访问得页面:
采用中间件 mymiddleware.py
def process_request(self,request):pass
白名单 黑名单

8.验证是否登录,装饰器!
def check_login(func):pass
最后采用中间件,
否则每一个函数都有要加装饰器。(@check_login)

9.批量插入测试数据
脚本 myscript.py
models.Book.objects.bulk_create(ret1)

10.自定义分页器
mypage.py
from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger
封装
上一页,下一页,首页,尾页

11.模板继承
base.html
{% extends 'base.html' %}
{{ block.super }} 可以引用基类模板的内容

12.静态文件
jquery-3.2.1.js
bootstrap-3.3.7

ajax发送post请求时
init_ajax.js
取 csrf token 的值发送

删除,页面得模态框 插件
sweetalert

13.settings配置文件
中间件
mysql

终端打印sql语句

logging
登录注册,会有日志记录

14.自定义过滤器和标签
templatetags/my_tag_filter.py
{% load my_tag_filter %}
{{ path|update_path:book.id}}

15.urls
分发,名称空间,有名分组,反向解析
re_path(r'^update_book/(?P<id>\d+)',views.update_book),
正则反向解析,需要赋值
return redirect(reverse('book:book_publisher',args=(type_id,)))

16.FBV CBV
FBV(function base views) 视图里使用函数处理请求
CBV(class base views) 视图里使用类处理请求

path('login/',views.LoginView.as_view(), name = 'login')
class LoginView(View):pass
给CBV加装饰器:
@method_decorator(check_login)
def dispatch(self, request, *args, **kwargs):pass

17.表单forms组件
myforms.py

为forms组件赋初值
https://docs.djangoproject.com/en/2.0/ref/forms/api/
publisher_form.initial = {'name':publisher.name}

表单控件
给每一个key添加样式
def __init__(self,*args,**kwargs):pass
select下拉框:新增加的出版社,想不重启,立刻就显示:
def __init__(self,*args,**kwargs):pass
新增加书时,选择新增加的出版社
不能立刻通过校验is_valid 需要等一会,就通过了

18.DateTimeField
    注意点:
      TIME_ZONE = 'Asia/Shanghai'
      USE_TZ = False

  https://blog.csdn.net/win_turn/article/details/53000770

    auto_now

auto_now_add
timezone

http://www.nanerbang.com/article/5488/
django:DateTimeField如何自动设置为当前时间并且能被修改:

DateTimeField.auto_now 如果为true 无法赋值,每次更新为最新时间;
DateTimeField.auto_now_add 如果为true 无法赋值,第一次创建时间

from django.db import models
import django.utils.timezone as timezone
class Doc(models.Model):
add_date = models.DateTimeField('保存日期',default = timezone.now)
mod_date = models.DateTimeField('最后修改日期', auto_now = True)

19.ORM表关系
一对一,(author authordetail)
删除author时,应该删除authordetail,关联的author就被删除了!

一对多,(book publisher)
删除出版社下面的某本书,拿到书的id,删除这本书;

多对多,(book author)
清除绑定关系,不应该删除书;

启动:
配置sql
python manage.py makemigrations
python manage.py migrate


详情:
需查看代码!!

二、数据库

6.1 - 图书增删改查页面

三、页面效果

6.1 - 图书增删改查页面

 

6.1 - 图书增删改查页面

6.1 - 图书增删改查页面

 

6.1 - 图书增删改查页面

 

四、主要代码

6.1 - 图书增删改查页面

 

6.1 - 图书增删改查页面

 

urls.py

from django.urls import path,re_path

from book import views

urlpatterns = [
    # path('login/',views.login, name = 'login'),                 # FBV
    path('login/',views.LoginView.as_view(), name = 'login'),     # CBV
    # path('register/',views.register, name = 'register'),
    path('register/',views.RegisterView.as_view(), name = 'register'),
    path('exist_user/',views.exist_user),
    path('logout/',views.logout),

    path('book_list/',views.book_list, name = 'book_list'),
    # re_path(r'^book_list/(\d+)/(publisher)',views.book_list),
    re_path(r'^book_list/(?P<field_id>\d+)/(?P<field_type>publisher)',views.book_list),  # 有名分组
    # re_path(r'^book_list/(\d+)/(author)',views.book_list),
    re_path(r'^book_list/(?P<field_id>\d+)/(?P<field_type>author)',views.book_list),     # 有名分组

    path('del_book/',views.del_book, name = 'del_book'),
    re_path(r'^del_book/(\d+)/(publisher)',views.del_book),
    re_path(r'^del_book/(\d+)/(author)',views.del_book),

    path('add_book/',views.add_book,name='add_book'),
    re_path(r'^add_book/(\d+)/(publisher)',views.add_book),
    re_path(r'^add_book/(\d+)/(author)',views.add_book),

    re_path(r'^update_book/(?P<book_id>\d+)/(?P<field_id>\d+)/(?P<field_type>publisher)',views.update_book),
    re_path(r'^update_book/(?P<book_id>\d+)/(?P<field_id>\d+)/(?P<field_type>author)',views.update_book),
    re_path(r'^update_book/(?P<book_id>\d+)',views.update_book),
    # 这个得放到下面 否则会截走 上面两个 因为第一个也是正则

    path('publisher_list/',views.publisher_list, name = 'publisher_list'),
    path('del_publisher/',views.del_publisher, name = 'del_publisher'),
    path('add_publisher/',views.add_publisher, name = 'add_publisher'),
    re_path(r'^update_publisher/(\d+)',views.update_publisher),

    path('author_list/',views.author_list, name = 'author_list'),
    path('del_author/',views.del_author, name = 'del_author'),
    path('add_author/',views.add_author, name = 'add_author'),
    re_path(r'^update_author/(\d+)',views.update_author),

]

 

models.py

from django.db import models
from django.utils import timezone


# 出版社类
class Publisher(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32)

    def __str__(self):
        return self.name


# 书类
class Book(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_places=2)
    publish_date = models.DateTimeField(default=timezone.now())
    # 书只能关联一个出版社, 外键通常建在多的那一边
    publisher = models.ForeignKey(to='Publisher',on_delete=models.CASCADE)

    def __str__(self):
        return self.title


# 作者类
class Author(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=16)
    # 多对多, 建在哪边都可以
    books = models.ManyToManyField(to='Book',related_name='authors')

    detail = models.OneToOneField(to='AuthorDetail',null=True,on_delete=models.CASCADE)

    def __str__(self):
        return self.name


# 作者详情
class AuthorDetail(models.Model):
    age = models.IntegerField()
    addr = models.TextField()


# 登录注册的用户信息
class UserInfo(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=16)
    pwd = models.CharField(max_length=32)

 

myforms.py

# -*- coding:utf-8 -*-
from django import forms
from django.forms import widgets
from django.core.exceptions import ValidationError

from book import models

widget_input = widgets.TextInput(attrs={'class':'form-control'})
widg_num = widgets.NumberInput(attrs={'class':'form-control'})
widget_password = widgets.PasswordInput(attrs={'class':'form-control'})


class PublisherForm(forms.Form):
    name = forms.CharField(
        label='出版社名称',
        min_length=4,
        max_length=32,
        error_messages={
            'required':'不能为空',
            'min_length':'不能小于4位',
        },
        widget=widget_input
    )

    def clean_name(self):
        val = self.cleaned_data.get('name')
        if not val.isdigit():
            return val
        else:
            raise ValidationError('名称不能是纯数字')


class AuthorForm(forms.Form):
    name = forms.CharField(
        label='姓名',
        min_length=2,
        max_length=16,
        error_messages={
            'required':'不能为空',
            'min_length':'不能小于2位',
        },
        # widget = widget_input
    )
    age = forms.IntegerField(
        label='年龄',
        min_value=1,
        max_value=150,
        error_messages={
            'required':'不能为空',
            'invalid':'格式错误',
            'min_value':'不能小于1岁',
            'max_value':'不能大于100岁',
        },
        # widget = widget_input
    )
    addr = forms.CharField(
        label='地址',
        min_length=2,
        max_length=32,
        error_messages={
            'required':'不能为空',
            'min_length':'不能小于2位'
        },
        # widget=widget_input,

    )

    # 给每一个key 添加样式
    def __init__(self,*args,**kwargs):
        super(AuthorForm, self).__init__(*args,**kwargs)
        for field in iter(self.fields):
            self.fields[field].widget.attrs.update({
                'class':'form-control'
            })

    def clean_name(self):
        val = self.cleaned_data.get('name')
        if not val.isdigit():
            return val
        else:
            raise ValidationError('姓名不能是纯数字')

    def clean_addr(self):
        val = self.cleaned_data.get('addr')
        if not val.isdigit():
            return val
        else:
            raise ValidationError('地址不能是纯数字')


class BookForm(forms.Form):
    title = forms.CharField(
        label='书名称',
        max_length=32,
        error_messages={
            'required':'不能为空',
        },
        widget=widget_input
    )
    price = forms.DecimalField(
        label='价格',
        max_digits=8,
        decimal_places=2,
        error_messages={
            'required':'不能为空',
            'max_digits':'不能超过8位',
        },
        widget=widg_num
    )

    # 最后选择了自己去添加 select 。。。。。。

    # publisher = forms.ChoiceField(
    #     label='出版社',
    #     # choices=((1,'篮球'),(2,'足球')),
    #     choices=models.Publisher.objects.all().values_list('id','name'),
    #     initial=1,
    #     widget=widgets.Select(attrs={'class':'form-control'})
    # )
    #
    # # 可以不用重启 刷新就有新的数据
    # def __init__(self,*args,**kwargs):
    #     super(BookForm, self).__init__(*args,**kwargs)
    #     self.fields['publisher'].widget.choices = models.Publisher.objects.all().values_list('id','name')

    def clean_title(self):
        val = self.cleaned_data.get('title')
        if not val.isdigit():
            return val
        else:
            raise ValidationError('名称不能为纯数字')

    def clean_price(self):
        val = self.cleaned_data.get('price')
        if val < 0:
            raise ValidationError('价格不能为负数')
        else:
            return val


class LoginForm(forms.Form):
    username = forms.CharField(
        label='用户名',
        min_length=2,
        max_length=16,
        error_messages={
            'required':'不能为空',
            'min_length':'不能小于2位'
        },
        widget=widget_input
    )
    password = forms.CharField(
        label='密码',
        min_length=6,
        max_length=16,
        error_messages={
            'required':'不能为空',
            'min_length':'不能小于6位'
        },
        widget=widget_password

    )

    def clean_username(self):
        val = self.cleaned_data.get('username')
        if not val.isdigit():
            return val
        else:
            raise ValidationError('用户名不能是纯数字')

 

views.py

from django.shortcuts import render,HttpResponse,redirect,reverse
from django.utils.decorators import method_decorator
from django.core import serializers
from django.views import View
import json
import datetime
import logging
from functools import wraps

from book import models
from book import myforms
from utils.mypage import MyPaginator
from utils.hash_pwd import salt_pwd

logger = logging.getLogger(__name__)
# 生成一个名为collect的实例
collect_logger = logging.getLogger('collect')


def check_login(func):
    '''
    判断用户有没有登录得装饰器
    :param func:
    :return:
    '''
    @wraps(func)
    def inner(request,*args,**kwargs):
        # 拿到当前访问网址
        url = request.get_full_path()
        if request.session.get('user'):
            return func(request,*args,**kwargs)
        else:
            return redirect('/login/?next={}'.format(url))

    return inner


# def login(request):
#     '''
#     登录
#     :param request:
#     :return:
#     '''
#     login_form = myforms.LoginForm()
#     return render(request,'login.html',{'login_form':login_form})
#
#
# def register(request):
#     '''
#     注册
#     :param request:
#     :return:
#     '''
#     register_form = myforms.LoginForm()
#     return render(request,'register.html',{'register_form':register_form})


class LoginView(View):
    '''
    CBV 登录视图
    '''

    def get(self,request):
        login_form = myforms.LoginForm()
        return render(request, 'login.html', {'login_form': login_form})

    def post(self,request):
        login_form = myforms.LoginForm(request.POST)
        if login_form.is_valid():
            username = login_form.cleaned_data.get('username')
            password = login_form.cleaned_data.get('password')
            password = salt_pwd(password, username)
            if models.UserInfo.objects.filter(name=username,pwd=password):
                # 设置session
                request.session['user'] = username
                # request.session.set_expiry(1800) # 设置session得失效时间

                # 登录成功 写log
                logger.info('用户:'+username+' 登录成功')

                next_url = request.GET.get('next')
                if next_url:
                    return redirect(next_url)   # 跳转到之前访问得页面
                else:
                    return redirect(reverse('book:book_list'))

            else:
                # 登录失败,写log
                logger.error('用户:'+username+' 登录时,用户名或密码错误')

                return render(request, 'login.html', {'login_form': login_form,'error_msg':'用户名或密码错误'})
        else:
            return render(request, 'login.html', {'login_form': login_form})


class RegisterView(View):
    '''
    CBV 注册视图
    '''
    # @method_decorator(check_login)  给cbv 加装饰器 逻辑上不应该加在这里,但可以验证装饰器加成功了
    def dispatch(self, request, *args, **kwargs):
        return super(RegisterView, self).dispatch(request,*args,**kwargs)

    def get(self,request):
        register_form = myforms.LoginForm()
        return render(request,'register.html',{'register_form':register_form})

    def post(self,request):
        register_form = myforms.LoginForm(request.POST)
        if register_form.is_valid():
            username = register_form.cleaned_data.get('username')
            password = register_form.cleaned_data.get('password')
            r_password = request.POST.get('r_password')
            if r_password == password:
                # 后台也需要判断用户名是否已存在,
                if not models.UserInfo.objects.filter(name=username).first():
                    password = salt_pwd(password,username)
                    models.UserInfo.objects.create(name=username,pwd=password)

                    # 注册成功之后,设置session登录状态
                    request.session['user'] = username

                    # 注册成功 写入log  并收集特定信息的日志
                    collect_logger.info('用户:'+username+' 注册')

                    return redirect(reverse('book:book_list'))
            else:
                return render(request,'register.html',{'register_form':register_form,'error_msg':'确认密码不符合'})

        return render(request,'register.html',{'register_form':register_form})


def exist_user(request):
    '''
    查看用户是否已经存在
    :param request:
    :return:
    '''
    if request.method == 'POST':
        username = request.POST.get('username')
        user_obj = models.UserInfo.objects.filter(name=username).first()

        reg = {'status':1,'msg':'用户已存在'} if user_obj else {'status':0,'msg':'用户不存在'}

        return HttpResponse(json.dumps(reg))


def logout(request):
    '''
    注销
    :param request:
    :return:
    '''
    request.session.delete()
    return redirect(reverse('book:login'))


# @check_login
def book_list(request,field_id = 0, field_type = 'src'):
    '''
    书列表 3中情况 从book_list下来的书  从publisher_list 下来的书 从author_list下来的书
    :param request:
    :param field_id:
    :param field_type:  /publisher_list / author_list
    :return:
    '''
    books = None

    filter_field = {
        'publisher': 'publisher_id',
        'author': 'authors__id'
    }
    field_dict = {filter_field.get(field_type): field_id} if field_type in ('publisher', 'author') else {}
    books = models.Book.objects.filter(**field_dict).values('id', 'title', 'price', 'publish_date', 'publisher__name').order_by('-id')

    ''' 注意上面得简化方法
    if field_type == 'publisher':
        books = models.Book.objects.filter(publisher_id=field_id).values('id','title','price','publish_date','publisher__name').order_by('-id')
    elif field_type == 'author':
        books = models.Book.objects.filter(authors__id=field_id).values('id','title','price','publish_date','publisher__name').order_by('-id')
    else:
         books = models.Book.objects.all().values('id', 'title', 'price', 'publish_date', 'publisher__name').order_by('-id')
    '''

    current_page_num = request.GET.get('page', 1)
    page_obj = MyPaginator(books,current_page_num)

    current_path ={'path':request.path}
    ret_dic = page_obj.show_page  # 页码返回的是字典
    ret_dic.update(current_path)  # 两个字典拼接

    # return render(request,'book_list.html',page_obj.show_page)
    return render(request,'book_list.html',ret_dic)


def del_book(request, field_id = 0, field_type = 'src'):
    '''
    删除一本书 3中情况 从book_list下来的书  从publisher_list 下来的书 从author_list下来的书
    :param request:
    :param field_id:
    :param field_type:
    :return:
    '''
    delete_id = request.POST.get('delete_id')
    if field_type == 'author':   # 清除绑定关系
        author_id = field_id
        author_obj = models.Author.objects.filter(id = author_id).first()
        try:
            author_obj.books.remove(delete_id)
            reg = {'status': 1, 'msg': '删除成功'}
        except Exception as e:
            reg = {'status':0,'msg':'删除失败'}

    else:  # 其他情况都删除书 book_list  publishe_list下来的书
        try:
            models.Book.objects.filter(id=delete_id).delete()
            reg = {'status':1,'msg':'删除成功'}
        except Exception as e:
            reg = {'status':0,'msg':'删除失败'}

    return HttpResponse(json.dumps(reg))


def add_book(request,field_id = 0, field_type = 'src'):
    '''
    增加书
    :param request:
    :param field_id:
    :param field_type:
    :return:
    '''
    current_publisher_id = 0
    current_author_id = 0
    if field_type == 'publisher':
        current_publisher_id = int(field_id)
    elif field_type == 'author':
        current_author_id = int(field_id)

    book_form = myforms.BookForm()

    if request.method == 'POST':
        if current_publisher_id:
            # 前端设置select disbaled  不能传到后台了,因此需要需要这样做
            publisher_id = current_publisher_id
        else:
            publisher_id = int(request.POST.get('publisher'))

        if request.POST.get('publish_date') != '':
            publish_date = request.POST.get('publish_date')
        else:
            publish_date = datetime.datetime.now()

        book_form = myforms.BookForm(request.POST)

        if book_form.is_valid():
            book_obj = models.Book.objects.create(
                title = book_form.cleaned_data.get('title'),
                price = book_form.cleaned_data.get('price'),
                publish_date = publish_date,
                publisher_id = publisher_id,
            )
            if current_author_id:
                book_obj.authors.add(current_author_id)  # 绑定多对多关系

            # return redirect(reverse('book:book_list')) #  因为有3种情况,分别跳到自己对应的页面下
            return redirect(request.path.replace('add_book','book_list'))

    publisher = models.Publisher.objects.all().values('id', 'name').order_by('-id')
    return render(request,'add_book.html',{'book_form':book_form,
                                            'publisher':publisher,
                                            "current_publisher_id":current_publisher_id})


def update_book(request, book_id, field_id = 0, field_type = 'src'):
    '''
    修改书
    :param request:
    :param book_id:
    :param field_id:
    :param field_type:
    :return:
    '''
    book = models.Book.objects.filter(id=book_id).first()
    book_form = myforms.BookForm()
    book_form.initial = {'title':book.title,'price':book.price}

    if request.method == 'POST':
        if request.POST.get('publish_date') != '':
            publish_date = request.POST.get('publish_date')
        else:
            publish_date = datetime.datetime.now()

        book_form = myforms.BookForm(request.POST)

        if book_form.is_valid():
            models.Book.objects.filter(id=book_id).update(
                title=book_form.cleaned_data.get('title'),
                price=book_form.cleaned_data.get('price'),
                publish_date=publish_date,
                publisher_id=request.POST.get('publisher'),
            )

            # 有3种情况,分别跳到自己对应的页面下

            if field_type in ('publisher','author'):
                new_url = reverse('book:book_list') + field_id + '/' + field_type
            else:
                new_url = reverse('book:book_list')

            return redirect(new_url)

    publisher = models.Publisher.objects.all().values('id', 'name').order_by('-id')
    return render(request,'update_book.html',{'book_form':book_form,
                                              'publisher':publisher,
                                              'current_publisher_id':book.publisher_id,
                                              'publish_date':book.publish_date})


# @check_login
def publisher_list(request):
    '''
    出版社列表
    :param request:
    :return:
    '''
    publishers = models.Publisher.objects.all().order_by('-id')
    current_page_num = request.GET.get('page',1)
    page_obj = MyPaginator(publishers,current_page_num)

    return render(request,'publisher_list.html',page_obj.show_page)


def del_publisher(request):
    '''
    删除一个出版社
    :param request:
    :return:
    '''
    delete_id = request.POST.get('delete_id')
    try:
        models.Publisher.objects.filter(id=delete_id).delete()
        reg = {'status':1,'msg':'删除成功'}
    except Exception as e:
        reg = {'status':0,'msg':'删除失败'}

    return HttpResponse(json.dumps(reg))


def add_publisher(request):
    '''
    增加出版社
    :param request:
    :return:
    '''
    publisher_form = myforms.PublisherForm()
    if request.method == 'POST':
        publisher_form = myforms.PublisherForm(request.POST)
        if publisher_form.is_valid():
            models.Publisher.objects.create(**publisher_form.cleaned_data)
            return redirect(reverse('book:publisher_list'))

    return render(request,'add_publisher.html',{'publisher_form':publisher_form})


def update_publisher(request,publisher_id):
    '''
    修改出版社
    :param request:
    :param publisher_id:
    :return:
    '''
    publisher = models.Publisher.objects.filter(id=publisher_id).first()
    publisher_form = myforms.PublisherForm()
    publisher_form.initial = {'name': publisher.name}  # 对forms组件初始化

    if request.method == 'POST':
        publisher_form = myforms.PublisherForm(request.POST)
        if publisher_form.is_valid():
            models.Publisher.objects.filter(id=publisher_id).update(**publisher_form.cleaned_data)
            return redirect(reverse('book:publisher_list'))

    return render(request, 'update_publisher.html', {'publisher_form': publisher_form})


# @check_login
def author_list(request):
    '''
     作者列表
    :param request:
    :return:
    '''
    authors = models.Author.objects.all().values('id','detail_id','name','detail__age','detail__addr').order_by('-id')
    current_page_num = request.GET.get('page')
    page_obj = MyPaginator(authors,current_page_num)

    return render(request,'author_list.html',page_obj.show_page)


def del_author(request):
    '''
    删除一个作者
    :param request:
    :return:
    '''
    delete_id = request.POST.get('delete_id')
    try:
        # 删Author关联的不会被删掉
        # models.Author.objects.filter(id=delete_id).delete()

        # 删AuthorDetail关联的才会被删掉
        models.AuthorDetail.objects.filter(id=delete_id).delete()
        reg = {'status':1,'msg':'删除成功'}
    except Exception as e:
        reg = {'status':0,'msg':'删除失败'}

    return HttpResponse(json.dumps(reg))


def add_author(request):
    '''
    增加作者
    :param request:
    :return:
    '''
    author_form = myforms.AuthorForm()
    if request.method == 'POST':
        author_form = myforms.AuthorForm(request.POST)
        if author_form.is_valid():
            name = author_form.cleaned_data.get('name')
            age = author_form.cleaned_data.get('age')
            addr = author_form.cleaned_data.get('addr')

            authordetail = models.AuthorDetail.objects.create(age=age,addr=addr)
            models.Author.objects.create(name=name,detail=authordetail)

            return redirect(reverse('book:author_list'))

    return render(request,'add_author.html',{'author_form':author_form})


def update_author(request,author_id):
    '''
    修改作者
    :param request:
    :param author_id:
    :return:
    '''
    author = models.Author.objects.filter(id=author_id).values('name','detail__age','detail__addr').first()
    author_form = myforms.AuthorForm()
    author_form.initial = {'name':author.get('name'),'age':author.get('detail__age'),'addr':author.get('detail__addr')}

    if request.method == 'POST':
        author_form = myforms.AuthorForm(request.POST)
        if author_form.is_valid():
            name = author_form.cleaned_data.get('name')
            age = author_form.cleaned_data.get('age')
            addr = author_form.cleaned_data.get('addr')

            models.Author.objects.filter(id=author_id).update(name=name)
            models.AuthorDetail.objects.filter(author__id=author_id).update(age=age,addr=addr)

            return redirect(reverse('book:author_list'))

    return render(request,'update_author.html',{'author_form':author_form})
views

相关文章: