Django 学习5--DetailView

1. 与LIstView不同

LIstView是获取一个表的内容,或一个表的部分内容

DetailView是获取一个条内容,所以这样知道要拿哪一条数据呢,就需要通过primary key(pk)

在template/personal_info目录下创建person_detail.html文件

# first_project/personal_info/views.py
from django.urls import reverse, reverse_lazy
from django.views import View
from django.views.generic import ListView, CreateView, DetailView

from personal_info.forms import PersonCreateForm
from personal_info.models import Person


class PersonList(ListView):
    model = Person
    template_name = 'personal_info/person_list.html'  # 会直接上templates目录下找

    def get_context_data(self, *, object_list=None, **kwargs):
        context = super().get_context_data(object_list=object_list, **kwargs)  # 先把父类的context拿到
        context.update({'list': [1.23, 2.34, 3.45]})
        return context


class PersonCreate(CreateView):# 注意这里改成了CreateView
    # 需要定义以下四个变量
    form_class = PersonCreateForm
    model = Person
    template_name = 'personal_info/person_create.html'
    success_url = reverse_lazy('personal_info:person_list')

class PersonDetail(DetailView):
    model = Person
    template_name = 'personal_info/person_detail.html'
first_project/personal_info/views.py
# first_project/personal_info/urls.py
from django.urls import path
from personal_info import views

app_name = 'personal_info'

urlpatterns = [

    # name值就是用来html中请求的url,会进行拼接,例如:personal_info:person_list
    path('', views.PersonList.as_view(), name="person_list"),
    path('create/', views.PersonCreate.as_view(), name="person_create"),
    # pk是DetailView中的pk_url_kwarg
    path('<int:pk>/', views.PersonDetail.as_view(), name="person_detail"),
]
first_project/personal_info/urls.py
{% extends 'personal_info/base.html' %} <!-- 引入基础模版 -->
{% load mytags %} <!-- 导入自定义tag -->
{% block title_content %}疫情人员登记表{% endblock %}
{% block body_content %}
    <table class="table">
        <thead>
        <tr>
            <th scope="col">ID</th>
            <th scope="col">名字</th>
            <th scope="col">年龄</th>
            <th scope="col">性别</th>
            <th scope="col">疑似</th>
        </tr>
        </thead>
        <tbody>
        {{ list|add_filter }} <!-- 调用自定义filter -->
        {% add_tag list %} <!-- 调用自定义tag -->
        <!-- 默认是object_list 模板语言for循环语法 -->
        {% for item in object_list %}
            <tr>
                <td>{{ item.id }}</td>
                <td><a href="{% url 'personal_info:person_detail' item.pk %}">{{ item.name }}</a></td>
                <td>{{ item.age }}</td>
                <!-- 不加get_display会显示数字 -->
                <td>{{ item.gender|yesno:"男,女"}}</td>
                <td>{% if item.temperature > 37 %}是{% else %}否{% endif %}</td>
            </tr>
        {% empty %}
            <tr>
                <!-- 意思是将5列合并成1列  -->
                <td colspan="5">暂无数据</td>
            </tr>
        {% endfor %}

        </tbody>
    </table>
    <!-- 这个地方跳转到 personal_info:person_create url -->

{% endblock %}
first_project/personal_info/templates/personal_info/person_detail.html

启动服务效果

点击名字后->

2.DeleteView和UpdateView

都是对一条数据进行操作的,所以需要传pk

personal_info项目主要代码:

{% extends 'personal_info/base.html' %} <!-- 引入基础模版 -->
{% load mytags %}
{% block title_content %}修改{{ object.name }}的信息{% endblock %} <!--object就是查出来的person-->
{% block body_content %}
    <form action="{% url 'personal_info:person_update' object.pk %}" method="post"> <!--如果是前后端分离,这里要改为put请求-->
        {% csrf_token %}
        {% for item in form %}
            <div class="col-md-6 mb-3">
                {{ item|label_class:"form-label" }}
                {{ item }}
                {{ item.errors}}
            </div>
        {% endfor %}
        <p><button type="submit" class="btn btn-primary">保存</button></p>
    </form>
{% endblock %}
first_project/personal_info/templates/personal_info/person_update.html
{% extends 'personal_info/base.html' %} <!-- 引入基础模版 -->
{% load mytags %} <!-- 导入自定义tag -->
{% block title_content %}疫情人员登记表{% endblock %}
{% block body_content %}
    <table class="table">
        <thead>
        <tr>
            <th scope="col">ID</th>
            <th scope="col">名字</th>
            <th scope="col">年龄</th>
            <th scope="col">性别</th>
            <th scope="col">疑似</th>
            <th scope="col"></th>
        </tr>
        </thead>
        <tbody>
        {{ list|add_filter }} <!-- 调用自定义filter -->
        {% add_tag list %} <!-- 调用自定义tag -->
        <!-- 默认是object_list 模板语言for循环语法 -->
        {% for item in object_list %}
            <tr>
                <td>{{ item.id }}</td>
                <td><a href="{% url 'personal_info:person_detail' item.pk  %}">{{ item.name }}</a></td>
                <td>{{ item.age }}</td>
                <!-- 不加get_display会显示数字 -->
                <td>{{ item.gender|yesno:"男,女"}}</td>
                <td>{% if item.temperature > 37 %}是{% else %}否{% endif %}</td>
                <td><a class="btn btn-sm btn-outline-success" href="{% url 'personal_info:person_update' item.pk %}">更新</a></td>

            </tr>
        {% empty %}
            <tr>
                <!-- 意思是将5列合并成1列  -->
                <td colspan="5">暂无数据</td>
            </tr>
        {% endfor %}

        </tbody>
    </table>
    <!-- 这个地方跳转到 personal_info:person_create url -->
    <p><a href="{% url 'personal_info:person_create' %}" class="btn btn-primary">登记</a></p>
{% endblock %}
first_project/personal_info/templates/personal_info/person_list.html
{% extends 'personal_info/base.html' %} <!-- 引入基础模版 -->
{% load mytags %}
{% block title_content %}{{ object.name }}的信息{% endblock %} <!--object就是查出来的person-->
{% block body_content %}
    <div class="card {% if object.temperature > 37 %}text-white bg-danger"{% endif %} style=" 18rem;">
        <div class="card-body">
            <h5 class="card-title">{{ object.name }}的信息</h5>
            <p class="card-text">
                <span class="badge rounded-pill bg-info text-dark">年龄:{{ object.age }}岁</span>
                <span class="badge rounded-pill bg-info text-dark">性别:{{ object.gender|yesno:'男,女' }}</span>
            </p>
        </div>
        <ul class="list-group list-group-flush">
            <li class="list-group-item">身份证:{{ object.id_card }}</li>
            <li class="list-group-item">住址:{{ object.address }}</li>
        </ul>
        <div class="card-body">
            <a href="{% url 'personal_info:person_update' object.pk %}" class="card-link">编辑</a>
            <a href="{% url 'personal_info:person_delete' object.pk %}" class="card-link">删除</a>
            <a class="card-link" href="{% url 'personal_info:person_list' %}">返回</a>
        </div>
    </div>
{% endblock %}
first_project/personal_info/templates/personal_info/person_detail.html
{% extends 'personal_info/base.html' %} <!-- 引入基础模版 -->
{% load mytags %}
{% block title_content %}删除{{ object.name }}的信息{% endblock %} <!--object就是查出来的person-->
{% block body_content %}
    <div class="col-4">
        <div class="alert-danger mb-3">是否删除{{ object.name }}的信息</div>
        <form action="{% url 'personal_info:person_delete' object.pk %}" method="post">
            {% csrf_token %}
            <button class="btn btn-danger" type="submit">删除</button>
        </form>
    </div>
{% endblock %}
first_project/personal_info/templates/personal_info/person_delete.html
{% extends 'personal_info/base.html' %} <!-- 引入基础模版 -->
{% load mytags %}
{% block title_content %}登记人员信息{% endblock %}
{% block body_content %}
<form action="{% url 'personal_info:person_create' %}" method="post">
    {% csrf_token %}
    {% for item in form %}
    <div class="col-md-6 mb-3">
        {{ item|label_class:"form-label" }}
        {{ item }}
        {{ item.errors}}
    </div>
    {% endfor %}
    <p><button type="submit" class="btn btn-primary">保存</button></p>
</form>
{% endblock %}
first_project/personal_info/templates/personal_info/person_create.html
{% extends 'personal_info/base.html' %} <!-- 引入基础模版 -->
{% load mytags %}
{% block title_content %}登记人员信息{% endblock %}
{% block body_content %}
<form action="{% url 'personal_info:person_create' %}" method="post">
    {% csrf_token %}
    {% for item in form %}
    <div class="col-md-6 mb-3">
        {{ item|label_class:"form-label" }}
        {{ item }}
        {{ item.errors}}
    </div>
    {% endfor %}
    <p><button type="submit" class="btn btn-primary">保存</button></p>
</form>
{% endblock %}
first_project/personal_info/templates/personal_info/base.html
# first_project/personal_info/models.py
from django.db import models

# Create your models here.
from django.db import models

class Person(models.Model): # 继承Model
    GENDER_CHOICES = (
        (1, ''),
        (0, ''),
    )

    name = models.CharField(max_length=32) # 定义VARCHAR类型字段,max_length是必须的
    age = models.IntegerField() # 定义整形字段
    gender = models.BooleanField(choices=GENDER_CHOICES) # 定义布尔类型变量,可选择的
    id_card = models.CharField(max_length=18)
    address = models.CharField(max_length=256)
    temperature = models.FloatField() # 定义浮点型字段

    class Meta: # model中的配置中心
        permissions = () # 将数据库权限设置为空
first_project/personal_info/models.py
# first_project/personal_info/forms.py
from django import forms
from personal_info.models import Person


class PersonCreateForm(forms.ModelForm):
    class Meta:  # 配置中心,前端的东西都可以在这里修改,比如css,需要的时候再查一下就可以
        model = Person  # 把model导进来
        fields = '__all__'  # 代表所有字段,也可以挨个写一下

        widgets = {
            'name': forms.TextInput(attrs={'id': 'name_id', 'class': 'form-control'}),  # 可以开发模式打开网页,找到name那行,看到新加了id的字段
            'gender': forms.Select(attrs={'id': 'gender_id', 'class': 'form-select'}),
            'age': forms.NumberInput(attrs={'id': 'age_id', 'class': 'form-control'}),
            'address': forms.TextInput(attrs={'id': 'address_id', 'class': 'form-control'}),
            'id_card': forms.TextInput(attrs={'id': 'id_card_id', 'class': 'form-control'}),
            'temperature': forms.NumberInput(attrs={'id': 'temperature_id', 'class': 'form-control', 'step': '0.1'}),
        }
        labels = {  # labels没办法在这里加class, 通过filter去做
            'name': '名字'  # 可以看到页面中的原本英文'name'变成了'名字'
        }


# 直接用PersonCreateForm就可以
class PersonUpdateForm(PersonCreateForm):
    pass


class PersonDeleteForm(PersonCreateForm):
    pass
first_project/personal_info/forms.py
# first_project/personal_info/templatetags/mytags.py
from functools import reduce
from django import template

register = template.Library()  # register的名字是固定的,不可改变


@register.filter(is_safe=False)
def add_filter(value, rounded=2):
    assert isinstance(value, list)
    return round(sum(value), rounded)


@register.simple_tag  # 官方推荐方式
def add_tag(*args, **kwargs):
    args = args[0]
    assert isinstance(args, list)
    result = reduce(lambda x, y: x + y, args)
    rounded = kwargs.get('rounded') or 2
    result = round(result, rounded)
    return result


@register.filter(is_safe=False)
def label_class(value, cls): # 为了改label加class
    return value.label_tag(attrs={'class': cls})
first_project/personal_info/templatetags/mytags.py
# first_project/personal_info/views.py
from django.http import HttpResponseRedirect
from django.shortcuts import render

# Create your views here.
from django.urls import reverse, reverse_lazy
from django.views import View
from django.views.generic import ListView, CreateView, DetailView, UpdateView, DeleteView

from personal_info.forms import PersonCreateForm, PersonUpdateForm
from personal_info.models import Person


class PersonList(ListView):
    model = Person
    template_name = 'personal_info/person_list.html'  # 会直接上templates目录下找

    def get_context_data(self, *, object_list=None, **kwargs):
        context = super().get_context_data(object_list=object_list, **kwargs)  # 先把父类的context拿到
        context.update({'list': [1.23, 2.34, 3.45]})
        return context


class PersonCreate(CreateView):  # 注意这里改成了CreateView
    # 需要定义以下四个变量
    form_class = PersonCreateForm
    model = Person
    template_name = 'personal_info/person_create.html'
    success_url = reverse_lazy('personal_info:person_list')


class PersonDetail(DetailView):
    model = Person
    template_name = 'personal_info/person_detail.html'


# update用到的属性和create一样
class PersonUpdate(UpdateView):
    model = Person
    template_name = 'personal_info/person_update.html'
    form_class = PersonUpdateForm #这里就是用来form验证的,所以detail和delete不需要用
    success_url = reverse_lazy('personal_info:person_list')


class PersonDelete(DeleteView):
    model = Person
    success_url = reverse_lazy('personal_info:person_list')
    template_name = 'personal_info/person_delete.html'
first_project/personal_info/views.py
# first_project/personal_info/urls.py
from django.urls import path
from personal_info import views

app_name = 'personal_info'

urlpatterns = [

    # name值就是用来html中请求的url,会进行拼接,例如:personal_info:person_list
    path('', views.PersonList.as_view(), name="person_list"),
    path('create/', views.PersonCreate.as_view(), name="person_create"),
    # pk是DetailView中的pk_url_kwarg
    path('<int:pk>/', views.PersonDetail.as_view(), name="person_detail"),
    path('<int:pk>/update/', views.PersonUpdate.as_view(), name="person_update"),
    path('<int:pk>/delete/', views.PersonDelete.as_view(), name="person_delete"),
]
first_project/personal_info/urls.py

 效果图

      

愿有志之人,成就非凡之事。
原文地址:https://www.cnblogs.com/damon-song/p/15257132.html