在完成了之前的事情之后,接下來就是實(shí)現(xiàn)注冊功能了。
首先進(jìn)行基礎(chǔ)的分析工作
- 判斷用戶名是否為空,是否已注冊
- 判斷郵箱是否為空,是否已注冊
- 判斷密碼是否為空,格式是否正確
一般的注冊操作還會有確認(rèn)密碼
的輸入,所以我們會在前端中增加一列。 - 判斷確認(rèn)密碼與密碼是否相同
請求方法:POST
url定義:/register/
請求參數(shù):url路徑參數(shù)
參數(shù) | 類型 | 前端是否必須傳 | 描述 |
---|---|---|---|
username | 字符串 | 是 | 用戶輸入的用戶名 |
password | 字符串 | 是 | 用戶輸入的密碼 |
password_repeat | 字符串 | 是 | 用戶輸入的重復(fù)密碼 |
字符串 | 是 | 用戶輸入的郵箱地址 |
注:由于是post請求,在向后端發(fā)起請求時,需要附帶csrf token
加入我們需要完成注冊,那就需要把這三個字段username
,password
,email
存入到數(shù)據(jù)庫中
我們首先編寫數(shù)據(jù)庫相關(guān)的代碼
因?yàn)镈jango框架功能齊全自帶數(shù)據(jù)庫操作功能,所以我們可以很方便的完成數(shù)據(jù)庫的設(shè)計。不過還是從最普通的開始了解吧。
正常的情況我們?nèi)绻僮鲾?shù)據(jù)庫需要:
- 創(chuàng)建數(shù)據(jù)庫,設(shè)計表結(jié)構(gòu)和字段
- 使用 MySQLdb 來連接數(shù)據(jù)庫,并編寫數(shù)據(jù)訪問層代碼
- 業(yè)務(wù)邏輯層去調(diào)用數(shù)據(jù)訪問層執(zhí)行數(shù)據(jù)庫操作
Django采用ORM的形式完成數(shù)據(jù)庫的操作
ORM是什么?:(在django中,根據(jù)代碼中的類自動生成數(shù)據(jù)庫的表也叫--code first)
ORM:Object Relational Mapping(關(guān)系對象映射)
類名對應(yīng)------》數(shù)據(jù)庫中的表名
類屬性對應(yīng)---------》數(shù)據(jù)庫里的字段
類實(shí)例對應(yīng)---------》數(shù)據(jù)庫表里的一行數(shù)據(jù)
obj.id obj.name.....類實(shí)例對象的屬性
也就是說django與數(shù)據(jù)庫的交互被寫在了黑盒子里面了,如果我們要用只需要知道輸入,不用管黑盒子是MySQL、Oracle、sqlite還是其他亂七八糟的數(shù)據(jù)庫,它都會按照我們的需求輸出正確的操作。
下面我們打開
apps/login/models.py
開始編寫數(shù)據(jù)庫相關(guān)約束。
id = models.AutoField()
username = models.CharField()
password = models.CharField()
email = models.EmailField()
了解一下常用的類型,接觸過數(shù)據(jù)庫的應(yīng)該都知道
-
IntegerField
: 整型,映射到數(shù)據(jù)庫中的int類型。 -
CharField
: 字符類型,映射到數(shù)據(jù)庫中的varchar類型,通過max_length指定最大長度。 -
TextField
: 文本類型,映射到數(shù)據(jù)庫中的text類型。 -
BooleanField
: 布爾類型,映射到數(shù)據(jù)庫中的tinyint類型,在使用的時候,傳遞True/False進(jìn)去。如果要可以為空,則用NullBooleanField。 -
DateField
: 日期類型,沒有時間。映射到數(shù)據(jù)庫中是date類型,
在使用的時候,可以設(shè)置DateField.auto_now每次保存對象時,自動設(shè)置該字段為當(dāng)前時間。設(shè)置DateField.auto_now_add當(dāng)對象第一次被創(chuàng)建時自動設(shè)置當(dāng)前時間。 -
DateTimeField
: 日期時間類型。映射到數(shù)據(jù)庫中的是datetime類型,
在使用的時候,傳遞datetime.datetime()進(jìn)去。
但是寫了這些還不夠的,因?yàn)橛脩裘艽a,郵箱等都需要進(jìn)行一定的約束,id一半是作為主鍵
知道了這個之后,就需要想辦法解決了,但是受限于我的編碼經(jīng)驗(yàn),所以我選擇借鑒django大佬的代碼。直接查看Django為admin編寫的用戶類
from django.contrib.auth.models import AbstractUser
按住ctrl+AbstractUser跳進(jìn)去。
以下是django中的源碼:
class AbstractUser(AbstractBaseUser, PermissionsMixin):
"""
An abstract base class implementing a fully featured User model with
admin-compliant permissions.
Username and password are required. Other fields are optional.
"""
username_validator = UnicodeUsernameValidator()
username = models.CharField(
_('username'),
max_length=150,
unique=True,
help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
validators=[username_validator],
error_messages={
'unique': _("A user with that username already exists."),
},
)
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=150, blank=True)
email = models.EmailField(_('email address'), blank=True)
is_staff = models.BooleanField(
_('staff status'),
default=False,
help_text=_('Designates whether the user can log into this admin site.'),
)
is_active = models.BooleanField(
_('active'),
default=True,
help_text=_(
'Designates whether this user should be treated as active. '
'Unselect this instead of deleting accounts.'
),
)
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
objects = UserManager()
EMAIL_FIELD = 'email'
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
abstract = True
def clean(self):
super().clean()
self.email = self.__class__.objects.normalize_email(self.email)
def get_full_name(self):
"""
Return the first_name plus the last_name, with a space in between.
"""
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
"""Return the short name for the user."""
return self.first_name
def email_user(self, subject, message, from_email=None, **kwargs):
"""Send an email to this user."""
send_mail(subject, message, from_email, [self.email], **kwargs)
在變成我們自己的代碼之前先了解以下里面的東西吧:
- primary_key: 指定是否為主鍵。
- unique: 指定是否唯一。
- null: 指定是否為空,默認(rèn)為False。
- blank: 等于True時form表單驗(yàn)證時可以為空,默認(rèn)為False。
- default: 設(shè)置默認(rèn)值。
- DateField.auto_now: 每次修改都會將當(dāng)前時間更新進(jìn)去,只有調(diào)用,QuerySet.update方法將不會調(diào)用。這個參數(shù)只是Date和DateTime以及TimModel.save()方法才會調(diào)用e類才有的。
- DateField.auto_now_add: 第一次添加進(jìn)去,都會將當(dāng)前時間設(shè)置進(jìn)去。以后修改,不會修改這個值
我們復(fù)制其中的username和email再稍加整改
突然先到我們好像缺少了創(chuàng)建時間
,更新時間
。而且這兩個內(nèi)容在全部表中都可以被應(yīng)用到。所以我們封裝一個基類好了。
from django.db import models
class ModelBase(models.Model):
create_time = models.DateTimeField(auto_now_add=True, verbose_name='創(chuàng)建時間')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新時間')
is_delete = models.BooleanField(default=False, verbose_name='邏輯刪除')
class Meta:
# 為抽象模型類,用于其他模型來繼承,數(shù)據(jù)庫遷移時不會創(chuàng)建ModelBase表
abstract = True
所以我們的用戶表的model文件就是:
from django.db import models
from utils.models import ModelBase
class User(ModelBase):
id = models.AutoField(primary_key=True)
username = models.CharField(
max_length=30,
unique=True,
)
password = models.CharField(
max_length=30,
)
email = models.EmailField()
class Meta:
db_table = "tb_user" # 指明數(shù)據(jù)庫表名
def __str__(self): # 這個__str__方法的作用將在查詢時看到
return f'User<id={self.id},username={self.username},email={self.email}'
表名為tb_user
數(shù)據(jù)庫遷移
找到Tools中的
Run manage.py Task...
首先輸入
makemigrations login
再輸入
migrate login
可以打開數(shù)據(jù)庫可視化工具查看
以上就完成了用戶表的創(chuàng)建,不過里面的一些約束條件什么的感覺還是有點(diǎn)問題,但是應(yīng)該不影響正常的使用(無法應(yīng)對破壞性的測試)。之后修改
models
之后在使用makemigrations [app name]
和migrate [app name]
就可以修改表結(jié)構(gòu)了。以后出問題了再改好了,問題驅(qū)動開發(fā)是比較合理的模式,畢竟在一開始就面面俱到難度不是一般的大。