Summary:
- requirement analysis
- Table structure design
- Registration function implementation
1. Demand analysis:
- Project Requirements (Product Manager, Architect, Development Team Leader talk to customer about project related requirements)
- Project Design (Architect needs to think about: framework selection, database selection, main function modules, quotation: including duration, developer salary...)
- Task Distribution (Development Team Leaders meet, project tasks are split, and distributed to groups)
- Testing (self/local testing, tester testing, white-box testing - developers, black-box testing - testers)
- Delivery Online (Operations & Maintenance with Online)
2. Project Analysis:
Table design:
-
User table (UserInfo)
First, we use the Django Web framework, so the user table inherits the structure of Django's auth_user table. We customize the creation of the UserInfo table, based on the auth_user table that was automatically created by the original DjangoAdd some additional fields:
User phone BigIntegerField Type
User Avatar FileField type (specify upload_to=', default avatar file default='avatar/xxx.jpg')
User creation time DateField type (set time to auto_now_add=True when new records are added)
One-to-one blog field (blog)OneToOneField(to='Blog', null=True)
What you need to know: user users will be a little complimentary (UpAndDown), Comment, and Blog) -
Personal Site Table (Blog)
Site name (blog_name) CharField type, recommended length 32
Site Title (blog_title) CharField type, recommended length 64
Site Style Theme (blog_theme) CharField type, store css file path, recommended length 64
You need to know that there are tags, categories, and articles on your site blog -
Article Tag Table
Label name CharField type, recommended length 32
One-to-many relationships: Blog (one)>>Tag (many):
blog foreign key field ForeignKey(to='Blog',null=True) -
Category of Articles
Classification name CharField type, recommended length 32
One-to-many relationships: Blog (1)>>Category (many):
blog foreign key field ForeignKey(to='Blog',null=True) -
Article Table
Article Title CharField type recommended length 64
Article Summary (desc) CharField type Recommended length 255
Article content TextField Type
Article Publishing Time (create_time) DateField type (set time to auto_now_add=True when new records are added)
# Optimize the fields created by the query:
Number of comments (comment_num) IntegerField type
Point Ratio (up_num) IntegerField type
Step count (down_num) IntegerField type
The # Article table is associated with personal site blogs, Tag Tags, categorized Categories:
One-to-many relationships:
Blog (1)>>Article (many): Blog foreign key field ForeignKey(to='Blog',null=True)
Category (1)>>Article (many): Catgory foreign key field ForeignKey(to='Category',null=True)
Many-to-many relationships: (Here we manually create the third many-to-many Association table, Article2Tag)
Tag >>> Article: tag many-to-many foreign key fields: ManyToManyField (to='Tag', through='Article2Tag', through_fields=('article','tag')) -
UpAndDown
is_up BooleanField type, 0 for step-on, 1 for favor
Dot-and-dot stepping is associated with user table UserInfo and Article table Articles:
One-to-many relationships:
UserInfo (1)>>UpAndDown (many): User foreign key field ForeignKey(to='UserInfo') A user can click on more than one favorite step, one may be just one user point
Article (1) > > UpAndDown (many): An article can be clicked with multiple approvals by using the ForeignKey(to='Article') foreign key field of user. One step or approval may correspond to one article. -
Comment
Comment content CharField Type Recommended length 255
Create_time DateField type (set time to auto_now_add=True when adding new records)
The comment table is associated with the user table UserInfo, the article table Article:
One-to-many relationships:
UserInfo (1)>>Comment: user foreign key field ForeignKey(to='UserInfo') One user can post multiple comments, one comment may only be published by one user
Article (1)>>Comment: user foreign key field ForeignKey(to='Article') An article can have multiple comments, one comment may only correspond to one article
parent ForeignKey Type ForeignKey(to='self') This is a special one that relates to itselfSummary: Direct relationship diagram of BBS table:
Registration function implementation:
-
Configuration environment:
setting.py file1,Set Static File 2,tell Django,Customize Create User Table 3,Use MySQL Database, configure database parameters STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static'), os.path.join(BASE_DIR, 'app01/static') ] AUTH_USER_MODEL = 'app01.UserInfo' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'bbs01', 'HOST': '127.0.0.1', 'PORT': 3306, 'USER': 'root', 'PASSWORD': '123' } }
# Note that in the init file:
import pymysql
pymysql.install_as_MySQLdb() -
Configure Django's form-related data:
Create a new folder myform under the app01 folder, and then create a new myform.py file under this file, which is:from django import forms from app01 import models # Establish Django Of form form class MyForm(forms.Form): username = forms.CharField( max_length=8, min_length=3, label='User name:', error_messages={ 'required': 'User name cannot be empty', 'max_length': 'Maximum username size is 8 bits', 'min_length': 'Minimum 3-digit user name', }, widget=forms.widgets.TextInput(attrs={'class': 'form-control'}) ) password = forms.CharField( max_length=8, min_length=3, label='Password:', error_messages={ 'required': 'Password cannot be empty', 'max_length': 'Maximum password 8 bits', 'min_length': 'Minimum password 3 bits', }, widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'}) ) confirm_password = forms.CharField( max_length=8, min_length=3, label='Confirm Password:', error_messages={ 'required': 'Confirmation password cannot be empty', 'max_length': 'Confirm password up to 8 bits', 'min_length': 'Confirm password minimum 3 bits', }, widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'}) ) email = forms.EmailField( label='mailbox:', error_messages={ 'required': 'Mailbox cannot be empty', 'invalid': 'Mailbox format error' }, widget=forms.widgets.EmailInput(attrs={'class': 'form-control'}) ) # User names and passwords are checked twice using local and global hooks: # Global hook checks if password input is consistent: def clean(self): password = self.cleaned_data.get('password') confirm_password = self.cleaned_data.get('confirm_password') if password != confirm_password: self.add_error('confirm_password', 'Passwords do not match when entered twice') return self.cleaned_data # Remember to return # Local hook checks if the user name exists: def clean_username(self): username = self.cleaned_data.get('username') user_obj = models.UserInfo.objects.filter(username=username).first() if user_obj: self.add_error('username', 'User name already exists') return username # Remember to return
-
Create orm mapping table relational model data for Django in model.py file of project app01:
models.py, create tables (if you need to create a database first (bbs01))from django.db import models from django.contrib.auth.models import AbstractUser # Create your models here. class UserInfo(AbstractUser): phone = models.BigIntegerField(null=True) create_time = models.DateField(auto_now_add=True) blog = models.OneToOneField(to='Blog', null=True) avatar = models.FileField(upload_to='avatar/', default='avatar/default_avatar.jpg') class Blog(models.Model): blog_name = models.CharField(max_length=32) blog_title = models.CharField(max_length=64) blog_theme = models.CharField(max_length=64) class Article(models.Model): title = models.CharField(max_length=64) content = models.TextField() desc = models.CharField(max_length=255) create_time = models.DateField(auto_now_add=True) blog = models.ForeignKey(to='Blog', null=True) category = models.ForeignKey(to='Category', null=True) tag = models.ManyToManyField(to='Tag', through='Article2Tag', through_fields=('article', 'tag')) # Optimize Query comment_num = models.IntegerField() up_num = models.IntegerField() down_num = models.IntegerField() class Category(models.Model): name = models.CharField(max_length=32) blog = models.ForeignKey(to='Blog', null=True) class Article2Tag(models.Model): article = models.ForeignKey(to='Article') tag = models.ForeignKey(to='Tag') class Tag(models.Model): name = models.CharField(max_length=32) blog = models.ForeignKey(to='Blog', null=True) class UpAndDown(models.Model): is_up = models.BooleanField() user = models.ForeignKey(to='UserInfo') article = models.ForeignKey(to='Article') class Comment(models.Model): content = models.CharField(max_length=255) create_time = models.DateField(auto_now_add=True) user = models.ForeignKey(to='UserInfo') article = models.ForeignKey(to='Article') parent = models.ForeignKey(to='self', null=True)
4. Configure routes, view functions, front-end register.html creation
In ## urls.py:from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^register/', views.register) ]
## register.html file creation:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> {# <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>#} <script src="/static/jQuery-3.4.1.js"></script> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css"> <link rel="stylesheet" href="/static/reg.css"> <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-6 col-md-offset-3"> <h2 class="text-center">Registration Page</h2> <hr> {# Note: Use here form The purpose of the form is that we need to pass form Batch processing of data objects entered in a form#} <form id="myform"> {% csrf_token %} {% for form in form_obj %} {# By input Box jackets div,Set up div Of class Contain form-group,#} {# Can pass bootstrap Style to adjust input Spacing between boxes#} <div class="form-group"> <label for="{{ form.auto_id }}">{{ form.label }}</label> {{ form }} <span class="has-error pull-right"></span> </div> {% endfor %} </form> <div class="form-group"> <label for="id_myfile"> <img id="id_avatar" src="/static/avatar/default_avatar.jpg" width="70" class="img-thumbnail"> </label> //Click on the picture to upload the Avatar <input type="file" id="id_myfile" name="myfile" class="hide"> </div> <button class="btn btn-primary pull-right" id="id_submit">Submit registration</button> </div> </div> </div> <script> // Render user-uploaded picture files to the page display instantly $('#id_myfile').on('change',function () { // Get Upload File Object let file_obj = this.files[0]; // Generate a built-in object let fileReader = new FileReader(); // Pass file objects to built-in objects fileReader.readAsDataURL(file_obj); // Replace the read file object with img Label // Because rendering pictures is much faster than reading files with a file reader // So, you need to use onload Method Wait for the file reader to finish reading before rendering the picture fileReader.onload = function () { $('#id_avatar').attr('src', fileReader.result) } }) // adopt ajax Send Request,Submit data $('#id_submit').on('click',function () { // ajax Can't transfer file by itself, need help from built-in object FormData Transfer Files // Declare a formData Object, formData Objects can transfer both files and normal keys through append Way to add let formData = new FormData(); // jQuery Object Method each Method: // Will pass $('#The json-formatted array of objects obtained by the myform').serializeArray() method traverses each of its key-value pairs // Each key-value pair traversed is treated as a function. function()In index Is a traversed index of key-value pairs, // obj Is the traversed key-value pair(Here it is form Inside Form input Box name And filled in value) $.each( // adopt serializeArray() Method serialization form Form value to create object array(Name and Value),This method returns a json object // Returned JSON An object is an array of objects, where each object contains a key-value pair name and value $('#myform').serializeArray(), function (index, obj) {formData.append(obj.name,obj.value);} // 1 {name: "username", value: "sgt"} Corresponding index and obj ); // function The function that will be traversed json Data Pass Point name And Point value Get the corresponding key value to add in formData in // Normal key value(input Key values filled in by boxes)Once added, add file data to formData in formData.append('myfile', $('#id_myfile')[0].files[0]); $.ajax({ url: '', // Do not write default current page route submission type: 'post', // post Submission Method data: formData, // To transfer data and files, you have to use built-in objects formData Send Request processData: false, // Tell the browser not to do anything with the data contentType: false, // No encoding, formData data object Django Backend is recognizable // Next success:function (data) { // Registration successful, jump to the specified page from the back end if (data.code==100) {location.replace(data.url)} // Registration failed, rendering the front end with hints from the back end that the check was unsuccessful // One thing to note here is: Django Of form When the form is rendered on the front end, each input Box id Name follows law // Define names, like this: id_username,id_password else { $.each( data.msg, function (index, obj) { // Be careful: index obj Namely: username ["Minimum 3-digit user name"] // Unlike the above method, this is to use a dictionary each Method, which uses the array above each Method let targetId = '#id_'+index; // Stitch out input Box id name // Each field name traversed, matched by the stitching above input Box corresponding id Name, through this // id The name will find it, underneath it (via next()Method) is what we need to do span Label // Add it html text(Is the error message, note obj Is a list),Continue chain operation at the same time // Make a mistake input Red box, warning prompt, pass parent()Method finds parent label div,Put it in // class Join one has-error That's it. $(targetId).next().html(obj[0]).parent().addClass('has-error') } ) } } }) }); // Pass above ajax Send out post The request for registration is almost complete, and finally the rendering of error information is implemented, which needs to be improved // If a user registers with an error prompt and continues to register, he or she will need to clear the error prompt again, so: $('input').on('focus',function () { $(this).next().html('').parent().removeClass('has-error') // The method is similar to adding an error message above and finds input Below the box span Label, put her html Empty, go and remove the red tips // Continue to find its parent tag at the same time div Remove class Inside has-error,Red box prompts cancel }) </script> </body> </html>
## views.py view function
from django.shortcuts import render,HttpResponse,redirect from app01.myform.myform import MyForm from app01 import models from django.http import JsonResponse # Create your views here. def register(request): form_obj = MyForm() # Define a response dictionary first, then register the request to use when returning back_dic = {'code': 100, 'msg': ''} if request.method == 'POST': # take register Common data for page submissions is retrieved and discarded to MyForm(),item base form_obj form_obj = MyForm(request.POST) # adopt form_obj obtain Django Automatically verify submission form processing results if form_obj.is_valid(): # Verification Passed,Get all key value data dictionaries passed data = form_obj.cleaned_data # Note here that there is one in the dictionary confirm_password The key value, which is not required after the check passes # So it needs to be removed: data.pop('confirm_password') # Get the user's uploaded avatar file object file_obj = request.FILES.get('myfile') # You need to add a layer of judgment here to see if the user has uploaded a avatar file on the front end or is using the default Avatar # Add when passed data,Add data directly without passing if file_obj: # User uploaded avatar file,to data Add key value of avatar file to data['avatar'] = file_obj # Be careful to use create_user Can create user data normally # data Is a dictionary key-value pair that directly scatters incoming data. perfect! models.UserInfo.objects.create_user(**data) back_dic['msg'] = 'login was successful' # Add page routes that jump after successful registration to the corresponding data dictionary back_dic['urs'] = '/login/' # Verification failed, registration unsuccessful else: back_dic['code'] = 101 # Failed to register on behalf of 101 # Pass in a dictionary of information that failed validation, wait for front-end rendering to prompt user registration failure back_dic['msg'] = form_obj.errors return JsonResponse(back_dic) return render(request, 'register.html', locals())