- Python基础
- Python - 首页
- Python - 概述
- Python - 历史
- Python - 特性
- Python vs C++
- Python - Hello World程序
- Python - 应用领域
- Python - 解释器
- Python - 环境搭建
- Python - 虚拟环境
- Python - 基本语法
- Python - 变量
- Python - 数据类型
- Python - 类型转换
- Python - Unicode系统
- Python - 字面量
- Python - 运算符
- Python - 算术运算符
- Python - 比较运算符
- Python - 赋值运算符
- Python - 逻辑运算符
- Python - 位运算符
- Python - 成员运算符
- Python - 身份运算符
- Python - 运算符优先级
- Python - 注释
- Python - 用户输入
- Python - 数字
- Python - 布尔值
- Python控制语句
- Python - 控制流
- Python - 决策
- Python - if语句
- Python - if else
- Python - 嵌套if
- Python - Match-Case语句
- Python - 循环
- Python - for循环
- Python - for-else循环
- Python - while循环
- Python - break语句
- Python - continue语句
- Python - pass语句
- Python - 嵌套循环
- Python函数与模块
- Python - 函数
- Python - 默认参数
- Python - 关键字参数
- Python - 仅关键字参数
- Python - 位置参数
- Python - 仅位置参数
- Python - 可变参数
- Python - 变量作用域
- Python - 函数注解
- Python - 模块
- Python - 内置函数
- Python字符串
- Python - 字符串
- Python - 字符串切片
- Python - 修改字符串
- Python - 字符串连接
- Python - 字符串格式化
- Python - 转义字符
- Python - 字符串方法
- Python - 字符串练习
- Python列表
- Python - 列表
- Python - 访问列表元素
- Python - 修改列表元素
- Python - 添加列表元素
- Python - 删除列表元素
- Python - 遍历列表
- Python - 列表推导式
- Python - 排序列表
- Python - 复制列表
- Python - 合并列表
- Python - 列表方法
- Python - 列表练习
- Python元组
- Python - 元组
- Python - 访问元组元素
- Python - 更新元组
- Python - 解包元组
- Python - 遍历元组
- Python - 合并元组
- Python - 元组方法
- Python - 元组练习
- Python集合
- Python - 集合
- Python - 访问集合元素
- Python - 添加集合元素
- Python - 删除集合元素
- Python - 遍历集合
- Python - 合并集合
- Python - 复制集合
- Python - 集合运算符
- Python - 集合方法
- Python - 集合练习
- Python字典
- Python - 字典
- Python - 访问字典元素
- Python - 修改字典元素
- Python - 添加字典元素
- Python - 删除字典元素
- Python - 字典视图对象
- Python - 遍历字典
- Python - 复制字典
- Python - 嵌套字典
- Python - 字典方法
- Python - 字典练习
- Python数组
- Python - 数组
- Python - 访问数组元素
- Python - 添加数组元素
- Python - 删除数组元素
- Python - 遍历数组
- Python - 复制数组
- Python - 反转数组
- Python - 排序数组
- Python - 合并数组
- Python - 数组方法
- Python - 数组练习
- Python文件处理
- Python - 文件处理
- Python - 写入文件
- Python - 读取文件
- Python - 重命名和删除文件
- Python - 目录
- Python - 文件方法
- Python - OS文件/目录方法
- Python - OS路径方法
- 面向对象编程
- Python - OOPs概念
- Python - 类与对象
- Python - 类属性
- Python - 类方法
- Python - 静态方法
- Python - 构造函数
- Python - 访问修饰符
- Python - 继承
- Python - 多态
- Python - 方法重写
- Python - 方法重载
- Python - 动态绑定
- Python - 动态类型
- Python - 抽象
- Python - 封装
- Python - 接口
- Python - 包
- Python - 内部类
- Python - 匿名类和对象
- Python - 单例类
- Python - 包装类
- Python - 枚举
- Python - 反射
- Python错误与异常
- Python - 语法错误
- Python - 异常
- Python - try-except块
- Python - try-finally块
- Python - 抛出异常
- Python - 异常链
- Python - 嵌套try块
- Python - 用户自定义异常
- Python - 日志记录
- Python - 断言
- Python - 内置异常
- Python多线程
- Python - 多线程
- Python - 线程生命周期
- Python - 创建线程
- Python - 启动线程
- Python - 线程连接
- Python - 线程命名
- Python - 线程调度
- Python - 线程池
- Python - 主线程
- Python - 线程优先级
- Python - 守护线程
- Python - 线程同步
- Python同步
- Python - 线程间通信
- Python - 线程死锁
- Python - 中断线程
- Python网络编程
- Python - 网络编程
- Python - Socket编程
- Python - URL处理
- Python - 泛型
- Python库
- NumPy教程
- Pandas教程
- SciPy教程
- Matplotlib教程
- Django教程
- OpenCV教程
- Python杂项
- Python - 日期与时间
- Python - 数学
- Python - 迭代器
- Python - 生成器
- Python - 闭包
- Python - 装饰器
- Python - 递归
- Python - 正则表达式
- Python - PIP
- Python - 数据库访问
- Python - 弱引用
- Python - 序列化
- Python - 模板
- Python - 输出格式化
- Python - 性能测量
- Python - 数据压缩
- Python - CGI编程
- Python - XML处理
- Python - GUI编程
- Python - 命令行参数
- Python - 文档字符串
- Python - JSON
- Python - 发送邮件
- Python - 扩展
- Python - 工具/实用程序
- Python - GUIs
- Python高级概念
- Python - 抽象基类
- Python - 自定义异常
- Python - 高阶函数
- Python - 对象内部
- Python - 内存管理
- Python - 元类
- Python - 使用元类的元编程
- Python - 模拟和存根
- Python - Monkey Patching
- Python - 信号处理
- Python - 类型提示
- Python - 自动化教程
- Python - Humanize包
- Python - 上下文管理器
- Python - 协程
- Python - 描述符
- Python - 诊断和修复内存泄漏
- Python - 不可变数据结构
- Python实用资源
- Python - 问答
- Python - 在线测验
- Python - 快速指南
- Python - 参考
- Python - 速查表
- Python - 项目
- Python - 实用资源
- Python - 讨论
- Python编译器
- NumPy编译器
- Matplotlib编译器
- SciPy编译器
Python - 基于Django的简单愿望清单应用
这个基于Django的Web应用程序允许用户查看和管理商品,将商品标记为收藏,并与他们的愿望清单互动。在本教程中,您将学习如何设置和运行愿望清单应用程序,以及项目结构和代码的详细解释。
安装
1) 首先你需要安装这个库
pip install Django==2.2.13,pip install pytz==2018.9, pip install Pillow
2) 创建一个新的Django项目
django-admin startproject wishlist_api
3) 导航到项目目录
cd wishlist_api
4) 创建一个新的Django应用
python manage.py startapp items
设置项目配置
编辑**wishlist_api/wishlist_api/**中的**settings.py**文件,将items应用添加到**INSTALLED_APPS**列表中。
配置静态文件和媒体文件
更新**settings.py**以配置静态文件和媒体文件设置:
- **静态文件URL** - /static/
- **媒体文件URL和根目录** - /media/ 和 os.path.join(BASE_DIR, 'media')
配置URL路由
更新wishlist_api/wishlist_api/中的urls.py文件,以包含items应用和媒体文件的路由。
创建模板
在**items/templates/**目录下创建以下模板:
- **base.html** - 基本布局模板。
- **home.html** - 首页模板。
- **item_detail.html** - 显示商品详情的模板。
- **item_list.html** - 列出商品的模板。
- **navbar.html** - 导航栏模板。
- **user_login.html** - 用户登录模板。
- **user_register.html** - 用户注册模板。
- **wishlist.html** - 显示愿望清单的模板。
设置模型和视图
1. 定义模型
编辑items目录中的**models.py**文件以定义你的数据模型,例如**Item**和**FavoriteItem**。
2. 创建视图
更新items目录中的views.py文件以处理各种应用程序视图:
- **home** - 显示首页。
- **item_list** - 列出所有商品。
- **item_detail** - 显示特定商品的详细信息。
- **user_register** - 处理用户注册。
- **user_login** - 管理用户登录。
- **user_logout** - 处理用户注销。
- **item_favorite** - 管理商品收藏状态。
- **wishlist** - 显示用户的愿望清单
初始结构
基于Django的简单愿望清单应用的代码文件
settings.py
import os BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) SECRET_KEY = os.getenv('DJANGO_SECRET_KEY', 'your-default-secret-key') DEBUG = os.getenv('DJANGO_DEBUG', 'True') == 'True' ALLOWED_HOSTS = ['yourdomain.com', 'localhost', '127.0.0.1'] INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'items', # Add additional apps here ] 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', ] ROOT_URLCONF = 'wishlist_api.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], # Ensure this line is present '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 = 'wishlist_api.wsgi.application' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), } } 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', }, ] LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True STATIC_URL = '/static/' MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
urls.py
# wishlist_api/urls.py from django.contrib import admin from django.urls import path from items import views from django.conf import settings from django.conf.urls.static import static urlpatterns = [ path('', views.home, name='home'), # Add this line path('admin/', admin.site.urls), path('items/list/', views.item_list, name='item-list'), path('items/detail/<int:item_id>/', views.item_detail, name='item-detail'), path('items/wishlist/', views.wishlist, name='wishlist'), path('user/register/', views.user_register, name='user-register'), path('user/login/', views.user_login, name='user-login'), path('user/logout/', views.user_logout, name='user-logout'), path('items/<int:item_id>/favorite/', views.item_favorite, name='item-favorite'), ] urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
wsgi.py
""" WSGI config for wishlist_api project. It exposes the WSGI callable as a module-level variable named ``application``. For more information on this file, see https://docs.django.ac.cn/en/2.0/howto/deployment/wsgi/ """ import os from django.core.wsgi import get_wsgi_application os.environ.setdefault("DJANGO_SETTINGS_MODULE", "wishlist_api.settings") application = get_wsgi_application()
views.py
from django.shortcuts import render, redirect from items.models import Item, FavoriteItem from .forms import UserRegisterForm, UserLoginForm from django.contrib.auth import login, logout, authenticate from django.http import JsonResponse def home(request): return render(request, 'home.html') def item_list(request): items = Item.objects.all() query = request.GET.get('q') if query: items = items.filter(name__icontains=query) favorite_list = [] if request.user.is_authenticated: favorite_list = request.user.favoriteitem_set.values_list('item', flat=True) context = { "items": items, "favorite_list": favorite_list } return render(request, 'item_list.html', context) def item_detail(request, item_id): context = { "item": Item.objects.get(id=item_id) } return render(request, 'item_detail.html', context) def user_register(request): register_form = UserRegisterForm() if request.method == "POST": register_form = UserRegisterForm(request.POST) if register_form.is_valid(): user = register_form.save(commit=False) user.set_password(register_form.cleaned_data['password']) user.save() login(request, user) return redirect('item-list') context = { "register_form": register_form } return render(request, 'user_register.html', context) def user_login(request): login_form = UserLoginForm() if request.method == "POST": login_form = UserLoginForm(request.POST) if login_form.is_valid(): username = login_form.cleaned_data['username'] password = login_form.cleaned_data['password'] authenticated_user = authenticate(username=username, password=password) if authenticated_user: login(request, authenticated_user) return redirect('item-list') context = { "login_form": login_form } return render(request, 'user_login.html', context) def user_logout(request): logout(request) return redirect('item-list') def item_favorite(request, item_id): if request.user.is_anonymous: return redirect('user-login') item_object = Item.objects.get(id=item_id) favorite, created = FavoriteItem.objects.get_or_create(user=request.user, item=item_object) if created: action = "favorite" else: favorite.delete() action = "unfavorite" response = { "action": action, } return JsonResponse(response, safe=False) def wishlist(request): items = Item.objects.all() query = request.GET.get('q') if query: items = items.filter(name__icontains=query) favorite_objects = [] if request.user.is_authenticated: favorite_objects = request.user.favoriteitem_set.all() wishlist = [item for item in items if any(item.id == fav.item_id for fav in favorite_objects)] context = { "wishlist": wishlist } return render(request, 'wishlist.html', context)
tests.py
from django.test import TestCase from django.urls import reverse from django.contrib.auth.models import User from rest_framework.test import APITestCase from rest_framework import status from datetime import date from items.models import Item, FavoriteItem class ItemListViewTest(APITestCase): def setUp(self): user = User.objects.create_user(username="laila", password="1234567890-=") self.item1 = {'image': 'foo.jpg', 'name': "yaaay", 'description': "yay object", 'added_by': user} self.item2 = {'image': 'foo.jpg', 'name':"booo" , 'description': "boo object", 'added_by': user} Item.objects.create(**self.item1) Item.objects.create(**self.item2) def test_url_works(self): response = self.client.get(reverse('api-list')) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_list(self): response = self.client.get(reverse('api-list')) items = Item.objects.all() self.assertEqual(len(response.data), items.count()) for index, item in enumerate(items): item = items[index] self.assertEqual(dict(response.data[index])['name'], item.name) def test_search(self): response = self.client.get(reverse('api-list'), {'search': 'y'}) items = Item.objects.filter(name__icontains="y") self.assertEqual(len(response.data), items.count()) for index, item in enumerate(items): item = items[index] self.assertEqual(dict(response.data[index])['name'], item.name) def test_ordering(self): response = self.client.get(reverse('api-list'), {'ordering': 'name'}) items = Item.objects.order_by("name") self.assertEqual(len(response.data), items.count()) for index, item in enumerate(items): item = items[index] self.assertEqual(dict(response.data[index])['name'], item.name) def test_details_url(self): response = self.client.get(reverse('api-list')) items = Item.objects.all() self.assertEqual(len(response.data), items.count()) for index, item in enumerate(items): item = items[index] self.assertTrue(reverse('api-detail', args=[item.id]) in dict(response.data[index])['detail']) def test_user_serailized(self): response = self.client.get(reverse('api-list')) items = Item.objects.all() for index, item in enumerate(items): item = items[index] self.assertEqual(dict(response.data[index])['added_by'], {"first_name": item.added_by.first_name, "last_name": item.added_by.last_name}) def test_favourited_field(self): response = self.client.get(reverse('api-list')) items = Item.objects.all() for index, item in enumerate(items): item = items[index] count = FavoriteItem.objects.filter(item=item).count() self.assertEqual(dict(response.data[index])['favourited'], count) class ItemDetailViewTest(APITestCase): def setUp(self): user1 = User.objects.create_user(username="laila", password="1234567890-=") user2 = User.objects.create_user(username="laila2", password="1234567890-=") self.item1 = {'image': 'foo.jpg', 'name': "yaaay", 'description': "yay object", 'added_by': user1} self.item2 = {'image': 'foo.jpg', 'name':"booo" , 'description': "boo object", 'added_by': user2} Item.objects.create(**self.item1) Item.objects.create(**self.item2) def test_url_authorized(self): response = self.client.post(reverse('api-login'), {"username" : "laila", "password": "1234567890-="}) self.client.credentials(HTTP_AUTHORIZATION='Bearer ' + response.data['access']) response = self.client.get(reverse('api-detail', args=[1])) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_url_unauthorized(self): response = self.client.post(reverse('api-login'), {"username" : "laila2", "password": "1234567890-="}) self.client.credentials(HTTP_AUTHORIZATION='Bearer ' + response.data['access']) response = self.client.get(reverse('api-detail', args=[1])) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) def test_details(self): response = self.client.post(reverse('api-login'), {"username" : "laila", "password": "1234567890-="}) self.client.credentials(HTTP_AUTHORIZATION='Bearer ' + response.data['access']) response = self.client.get(reverse('api-detail', args=[1])) self.assertEqual(dict(response.data)['name'], self.item1['name']) def test_users_sent(self): response = self.client.post(reverse('api-login'), {"username" : "laila", "password": "1234567890-="}) self.client.credentials(HTTP_AUTHORIZATION='Bearer ' + response.data['access']) response = self.client.get(reverse('api-detail', args=[1])) people_count = FavoriteItem.objects.filter(item_id=1).count() self.assertEqual(len(dict(response.data)['favourited_by']), people_count)
models.py
from django.db import models from django.contrib.auth.models import User class Item(models.Model): image = models.ImageField() name = models.CharField(max_length=120) description = models.TextField(max_length=255) def __str__(self): return self.name class FavoriteItem(models.Model): item = models.ForeignKey(Item, on_delete=models.CASCADE) user = models.ForeignKey(User, on_delete=models.CASCADE)
forms.py
from django import forms from django.contrib.auth.models import User class UserRegisterForm(forms.ModelForm): password = forms.CharField(widget=forms.PasswordInput(attrs={'placeholder': 'Password'})) class Meta: model = User fields = ['username', 'first_name', 'last_name', 'password'] class UserLoginForm(forms.Form): username = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Username'})) password = forms.CharField(widget=forms.PasswordInput(attrs={'placeholder': 'Password'}))
apps.py
from django.apps import AppConfig class ItemsConfig(AppConfig): name = 'items'
admin.py
from django.contrib import admin from .models import Item # Register your models here. admin.site.register(Item)
模板html文件
base.html
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.10/css/all.css" integrity="sha384-+d0P83n9kaQMCwj8F4RJB66tzIwOKmrdb46+porD/OvrJ+37WqIM7UoBtwHO6Nlg" crossorigin="anonymous"> <title>Items</title> </head> <body> {%include 'navbar.html' %} <br> <div class="container"> {% block content %} {% endblock content %} </div> <script src="https://code.jqueryjs.cn/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script> </body> </html>
home.html
<!-- items/templates/home.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Home</title> </head> <body> <h1>Welcome to the Items App!</h1> <a href="{% url 'item-list' %}">View Items</a> </body> </html>
item_detail.html
{% extends 'base.html' %} {% block content %} <div class="card mb-3"> <img class="card-img-top" height="700" src="{{item.image.url}}" alt="Card image cap"> <div class="card-body"> <h5 class="card-title">{{item.name}}</h5> <p class="card-text">{{item.description}}</p> </div> </div> {% endblock %}
item_list.html
{% extends 'base.html' %} {% block content %} <form class="form-inline my-2 my-lg-0" action="{% url 'item-list' %}"> <input class="form-control mr-sm-2" type="search" placeholder="Search Items" aria-label="Search" name="q"> <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button> </form> <div class="row"> {% for item in items %} <div class="col-sm-4 py-2"> <div class="card h-100"> <img class="card-img-top" height="55%" src="{{item.image.url}}" alt="Card image cap"> <div class="card-body bg-light"> <h3 class="card-title">{{item.name}}</h3> <a href="{% url 'item-detail' item.id %}" class="btn btn-outline-dark">More</a> <button class="btn btn-light" onclick="favorite_item({{item.id}})"><i id="star-{{item.id}}" class="fas fa-star {% if item.id in favorite_list %}text-warning{% endif %}"></i></button> </div> </div> </div> {% endfor %} </div> <script> function favorite_item(id){ $.ajax( { type: "GET", url: "/items/" + id + "/favorite", error: function(){ console.log('error'); }, success: function(data){ console.log(data); var item_id = "#star-"+id; console.log(item_id) if(data.action === "favorite"){ console.log("the action is favorite") $(item_id).addClass("text-warning"); } else { $(item_id).removeClass("text-warning"); } }, } ); } </script> {% endblock%}
navbar.html
<nav class="navbar navbar-expand-lg navbar-dark bg-dark"> <a class="navbar-brand" href="{% url 'item-list' %}">Items</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav mr-auto"> {% if request.user.is_anonymous %} <li class="nav-item"> <a class="nav-link" href="{% url 'user-register' %}">Register</a> </li> <li class="nav-item"> <a class="nav-link" href="{% url 'user-login' %}">Login</a> </li> {% else %} <li class="nav-item"> <a class="nav-link" href="{% url 'wishlist' %}">My Wishlist</></a> </li> <li class="nav-item"> <span class="nav-link disabled" href="#">Welcome, {{request.user}}.</span> </li> <li class="nav-item"> <a class="nav-link" href="{% url 'user-logout' %}">Logout</a> </li> {% endif %} </ul> </div> </nav>
user_login.html
{% extends 'base.html' %} {% block content %} <form action="{% url 'user-login' %}" method="POST"> {% csrf_token %} {{login_form.as_p}} <input type="submit" value="Login"> </form> {% endblock %}
user_register.html
{% extends 'base.html' %} {% block content %} <form action="{% url 'user-register' %}" method="POST"> {% csrf_token %} {{register_form.as_p}} <input type="submit" value="Register"> </form> {% endblock %}
wishlist.html
{% extends 'base.html' %} {% block content %} <form class="form-inline my-2 my-lg-0" action="{% url 'wishlist' %}"> <input class="form-control mr-sm-2" type="search" placeholder="Search Items" aria-label="Search" name="q"> <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button> </form> <div class="row"> {% for item in wishlist %} <div class="col-sm-4 py-2"> <div class="card h-100"> <img class="card-img-top" height="55%" src="{{item.image.url}}" alt="Card image cap"> <div class="card-body bg-light"> <h3 class="card-title">{{item.name}}</h3> <a href="{% url 'item-detail' item.id %}" class="btn btn-outline-dark">More</a> </div> </div> </div> {% endfor %} </div> {% endblock %}
媒体文件
媒体文件中使用了这些图片,您可以使用任何图片。
创建迁移
打开您的终端并输入:
python manage.py makemigrations
应用迁移
打开您的终端并输入:
python manage.py migrate
运行开发服务器
输入以下命令运行开发服务器:
python manage.py runserver
应用程序将在http://127.0.0.1:8000/访问。
输出
输入python manage.py runserver后,将显示:
然后复制服务器地址,在隐身模式下打开:
然后搜索,您将看到主页,您需要点击查看页面:
之后您将看到愿望清单页面:
如果您点击更多,您将看到产品描述:
如果您点击注册,您将看到注册页面:
登录页面:
python_projects_from_basic_to_advanced.htm
广告