Django 3已发布,具有完全异步支持!在本教程中,我们将通过示例逐步演示如何创建CRUD应用程序。我们将看到如何配置MySQL数据库,启用管理界面以及创建django视图。
我们将使用Bootstrap 4进行样式设置。
您将学习如何:
实施CRUD操作,
配置和访问MySQL数据库,
创建Django视图,模板和网址,
使用Bootstrap 4设置UI样式
Django 3功能
Django 3具有许多新功能,例如:
MariaDB支持:Django现在正式支持MariaDB 10.1+。您可以通过MySQL后端使用MariaDB,
ASGI支持异步编程,
Django 3.0提供了对作为ASGI应用程序运行的支持,从而使Django完全具有异步功能
PostgreSQL上的排除约束:Django 3.0添加了一个新的ExclusionConstraint类,该类在PostgreSQL等上添加了排除约束。
先决条件
让我们从本教程的先决条件开始。为了逐步按照本教程进行操作,您需要满足一些要求,例如:
基本的Python知识,
Django的工作知识(django-admin.py和manage.py),
您的系统上安装了Python 3的最新版本(最新版本是3.7),
系统上已安装MySQL数据库。
我们将使用pip和venv,它们在Python的最新版本中作为模块捆绑在一起,因此除非您使用的是旧版本,否则实际上不需要安装它们。
如果你准备好了,让我们开始吧。
Django 3教程,第1步-创建MySQL数据库
在这一步中,我们将创建一个mysql数据库来存储我们的应用程序数据。
打开一个新的命令行界面,并运行mysql客户端,如下所示:
1 |
$ mysql -u root -p |
系统将提示您输入MySQL密码,输入密码,然后按Enter。
接下来,使用以下SQL语句创建数据库:
1 |
mysql> create database mydb; |
Django 3教程,第2步-初始化新的虚拟环境
在这一步中,我们将初始化一个新的虚拟环境,以分离系统范围的软件包来安装我们的项目软件包。
回到您的命令行界面并运行以下命令:
1 |
$ python3 -m venv .env |
下一步激活你的虚拟环境,命令如下:
1 |
$ source .env/bin/activate |
在本教程的这一点上,我们有一个用于保存数据的mysql数据库,并创建了一个用于安装项目包的虚拟环境。
Django 3教程,第3步-安装Django和MySQL客户端
在此步骤中,我们将在激活的虚拟环境中使用pip从PyPI安装django和mysql客户端。
回到您的命令行界面并运行以下命令来安装django软件包:
1 |
$ pip install django |
然后等待一会,django-3.0.2就会被安装上。
因为用的mysql,你也需要安装mysql client, pip命令:
1 |
$ pip install mysqlclient |
Django 3教程,第4步-初始化新项目
在这一步中,我们将使用django-admin初始化一个新的django项目。
回到您的命令行界面并运行以下命令:
1 |
$ django-admin startproject djangoCrudExample |
下一步,打开settings.py文件,db配置修改如下:
1 2 3 4 5 6 7 8 9 10 |
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'mydb', 'USER': 'root', 'PASSWORD': '<YOUR_DB_PASSWORD>', 'HOST': 'localhost', 'PORT': '3306', } } |
下一步,迁移数据,命令:
1 2 |
$ cd djangoCrudExample $ python3 manage.py migrate |
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Operations to perform: Apply all migrations: admin, auth, contenttypes, sessions Running migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying admin.0003_logentry_add_action_flag_choices... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying auth.0009_alter_user_last_name_max_length... OK Applying auth.0010_alter_group_name_max_length... OK Applying auth.0011_update_proxy_permissions... OK Applying sessions.0001_initial... OK |
Django 3教程,第5步-安装django-widget-tweaks
在此步骤中,我们将在我们的虚拟环境中安装django-widget-tweaks。 回到您的命令行界面并运行以下命令:
1 |
$ pip insll django-widget-tweaks |
然后,再次打开settings.py文件,安装app,配置如下:
1 2 3 4 5 6 7 8 9 |
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'widget_tweaks' ] |
Django 3教程,第6步-创建管理员用户
在此步骤中,我们将创建一个管理员用户,该用户将允许我们使用以下命令访问应用程序的管理界面:
1 |
$ python manage.py createsuperuser |
输入用户名,和密码,邮箱:
1 2 3 4 5 |
Username (leave blank to use 'ahmed'): Email address: ahmed@gmail.com Password: Password (again): Superuser created successfully. |
Django 3教程,第7步-创建Django应用程序
在这一步中,我们将创建一个django应用程序。
回到您的命令行界面,并运行以下命令:
1 |
$ python manage.py startapp crudapp |
打开settings.py文件,加到配置文件中:
1 2 3 4 5 6 7 8 9 10 |
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'widget_tweaks', 'crudapp' ] |
Django 3教程,第8步-创建模型
在这一步。 我们将创建用于存储联系人的数据库模型。
打开crudapp / models.py文件并添加以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
from django.db import models class Contact(models.Model): firstName = models.CharField("First name", max_length=255, blank = True, null = True) lastName = models.CharField("Last name", max_length=255, blank = True, null = True) email = models.EmailField() phone = models.CharField(max_length=20, blank = True, null = True) address = models.TextField(blank=True, null=True) description = models.TextField(blank=True, null=True) createdAt = models.DateTimeField("Created At", auto_now_add=True) def __str__(self): return self.firstName |
之后,我们创建迁移的sql:
1 |
$ python manage.py makemigrations |
输出:
1 2 |
crudapp/migrations/0001_initial.py - Create model Contact |
再执行迁移命令和输出:
1 2 |
$ python manage.py migrate Applying crudapp.0001_initial... OK |
Django 3教程,第9步-创建表单
在此步骤中,我们将创建一个用于创建联系人的表单。
在crudapp文件夹中,创建一个forms.py文件并添加以下代码:
1 2 3 4 5 6 7 |
from django import forms from .models import Contact class ContactForm(forms.ModelForm): class Meta: model = Contact fields = "__all__" |
我们从models.py文件导入Contact模型。 我们创建了一个名为ContactForm的类,该类从django.forms包中继承了Django的ModelForms,并指定了我们要使用的模型。 我们还指定将使用Contact模型中的所有字段。 这将使我们能够在模板中显示这些字段。
Django 3教程,第10步-创建视图
在此步骤中,我们将创建用于执行CRUD操作的视图。
打开crudapp / views.py文件并添加:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
from django.shortcuts import render, redirect, get_object_or_404 from .models import Contact from .forms import ContactForm from django.views.generic import ListView, DetailView class IndexView(ListView): template_name = 'crudapp/index.html' context_object_name = 'contact_list' def get_queryset(self): return Contact.objects.all() class ContactDetailView(DetailView): model = Contact template_name = 'crudapp/contact-detail.html' def create(request): if request.method == 'POST': form = ContactForm(request.POST) if form.is_valid(): form.save() return redirect('index') form = ContactForm() return render(request,'crudapp/create.html',{'form': form}) def edit(request, pk, template_name='crudapp/edit.html'): contact = get_object_or_404(Contact, pk=pk) form = ContactForm(request.POST or None, instance=post) if form.is_valid(): form.save() return redirect('index') return render(request, template_name, {'form':form}) def delete(request, pk, template_name='crudapp/confirm_delete.html'): contact = get_object_or_404(Contact, pk=pk) if request.method=='POST': contact.delete() return redirect('index') return render(request, template_name, {'object':contact}) |
Django 3教程,第11步-创建模板
打开settings.py文件,并将os.path.join(BASE_DIR,’templates’)添加到TEMPLATES数组中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
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在模板文件夹中查找模板。
接下来,在crudapp文件夹中创建一个模板文件夹:
1 |
$ mkdir templates |
接下来,在模板文件夹中,创建以下文件:
base.html
Confirm_delete.html
edit.html
index.html
create.html
contact-detail.html
通过从项目的根目录运行以下命令:
1 2 3 4 5 6 7 8 9 |
$ mkdir templates $ cd templates $ mkdir crudapp $ touch crudapp/base.html $ touch crudapp/confirm_delete.html $ touch crudapp/edit.html $ touch crudapp/index.html $ touch crudapp/create.html $ touch crudapp/contact-detail.html |
打开crudapp/templates/base.html文件,然后加入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<!DOCTYPE html> <html> <head> <title>Django 3 CRUD Example</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css"> </head> <body> {% block content %} {% endblock %} <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script> </body> </html> |
下一步,打开crudapp/templates/index.html文件,加入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
{% extends 'crudapp/base.html' %} {% block content %} <div class="container-fluid"> <div class="row"> <div class="col-md-1 col-xs-1 col-sm-1"></div> <div class="col-md-10 col-xs-10 col-sm-10"> <h3 class="round3" style="text-align:center;">Contacts</h3> </div> <div class="col-md-1 col-xs-1 col-sm-1"></div> </div> <div class="row"> <div class="col-md-10 col-xs-10 col-sm-10"></div> <div class="col-md-2 col-xs-1 col-sm-1"> <br /> <a href="{% url 'create' %}"> <button type="button" class="btn btn-success"> <span class="glyphicon glyphicon-plus"></span> </button> </a> </div> </div> <br /> {% for contact in contact_list %} <div class="row"> <div class="col-md-1 col-xs-1 col-sm-1"></div> <div class="col-md-7 col-xs-7 col-sm-7"> <ul class="list-group"> <li class="list-group-item "> <a href="{% url 'detail' contact.pk %}"> {{ contact.firstName }} {{contact.lastName}} </a> <span class="badge"></span> </li> </ul> <br> </div> <div class="col-md-1 col-xs-1 col-sm-1"> <a href="{% url 'detail' contact.pk %}"> <button type="button" class="btn btn-info"> <span class="glyphicon glyphicon-open"></span> </button> </a> </div> <div class="col-md-1"> <a href="{% url 'edit' contact.pk %}"> <button type="button" class="btn btn-info"> <span class="glyphicon glyphicon-pencil"></span> </button> </a> </div> <div class="col-md-1"> <a href="{% url 'delete' contact.pk %}"> <button type="button" class="btn btn-danger"> <span class="glyphicon glyphicon-trash"></span> </button> </a> </div> <div class="col-md-1 col-xs-1 col-sm-1"></div> </div> {% endfor %} </div> {% endblock %} |
然后,打开crudapp/templates/create.html文件,加入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
{% load widget_tweaks %} <!DOCTYPE html> <html> <head> <title>Posts</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous"> <style type="text/css"> <style> </style> </style> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-1 col-xs-1 col-sm-1"></div> <div class="col-md-10 col-xs-10 col-sm-10 "> <br /> <h6 style="text-align:center;"> <font color="red"> All fields are required</font> </h6> </div> <div class="col-md-1 col-xs-1 col-sm-1"> </div> </div> <div class="row"> <div class="col-md-1 col-xs-1 col-sm-1"></div> <div class="col-md-10 col-xs-10 col-sm-10"> <form method="post" novalidate> {% csrf_token %} {% for hidden_field in form.hidden_fields %} {{ hidden_field }} {% endfor %} {% for field in form.visible_fields %} <div class="form-group"> {{ field.label_tag }} {% render_field field class="form-control" %} {% if field.help_text %} <small class="form-text text-muted">{{ field.help_text }}</small> {% endif %} </div> {% endfor %} <button type="submit" class="btn btn-primary">post</button> </form> <br> </div> <div class="col-md-1 col-xs-1 col-sm-1"></div> </div> </div> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script> </body> </html> |
打开crudapp/templates/edit.html文件,加入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
{% load widget_tweaks %} <!DOCTYPE html> <html> <head> <title>Edit Contact</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous"> <style type="text/css"> <style> </style> </style> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-1 col-xs-1 col-sm-1"></div> <div class="col-md-10 col-xs-10 col-sm-10 "> <br /> <h6 style="text-align:center;"> <font color="red"> All fields are required</font> </h6> </div> <div class="col-md-1 col-xs-1 col-sm-1"> </div> </div> <div class="row"> <div class="col-md-1 col-xs-1 col-sm-1"></div> <div class="col-md-10 col-xs-10 col-sm-10"> <form method="post" novalidate> {% csrf_token %} {% for hidden_field in form.hidden_fields %} {{ hidden_field }} {% endfor %} {% for field in form.visible_fields %} <div class="form-group"> {{ field.label_tag }} {% render_field field class="form-control" %} {% if field.help_text %} <small class="form-text text-muted">{{ field.help_text }}</small> {% endif %} </div> {% endfor %} <button type="submit" class="btn btn-primary">submit</button> </form> <br> </div> <div class="col-md-1 col-xs-1 col-sm-1"></div> </div> </div> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script> </body> </html> |
打开crudapp/templates/confirm_delete.html文件加入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
{% extends 'crudapp/base.html' %} {% block content %} <div class="container"> <div class="row"></div> <br /> <div class="row"> <div class="col-md-2 col-xs-2 col-sm-2"></div> <div class="col-md-10 col-xs-10 col-sm-10"> <form method="post"> {% csrf_token %} <div class="form-row"> <div class="alert alert-warning"> Are you sure you want to delete {{ object }}? </div> </div> <button type="submit" class="btn btn-danger"> <span class="glyphicon glyphicon-trash"></span> </button> </form> </div> </div> </div> {% endblock %} |
Django 3教程,第12步-创建URL
在这一步中,我们将创建URL来访问我们的CRUD视图。
转到urls.py文件,并按如下所示进行更新:
1 2 3 4 5 6 7 8 9 10 11 12 |
from django.contrib import admin from django.urls import path from crudapp import views urlpatterns = [ path('admin/', admin.site.urls), path('contacts/', views.IndexView.as_view(), name='index'), path('contacts/<int:pk>/', views.ContactDetailView.as_view(), name='detail'), path('contacts/edit/<int:pk>/', views.edit, name='edit'), path('contacts/create/', views.create, name='create'), path('contacts/delete/<int:pk>/', views.delete, name='delete'), ] |
Django 3教程,第11步-运行本地开发服务器
在此步骤中,我们将运行本地开发服务器来玩我们的应用程序,而无需将其部署到网络上。
回到您的命令行界面并运行以下命令:
1 |
$ python manage.py runserver |
最后,打开http://localhost:8000/地址,访问
结论
在django 3教程中,我们初始化了一个新的django项目,创建并迁移了MySQL数据库,并构建了一个简单的CRUD接口。
原文:https://www.techiediaries.com/django-3-tutorial-and-crud-example-with-mysql-and-bootstrap/