UUBlog

UUBlog

Django已经给我们提供了一个用户模型,但是它的字段不多,在某些场景下无法满足我们的使用需求,所以我们还要重新定义个数据模型,来描述我们用户数据表。

原来的auth_user

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| password | varchar(128) | NO | | NULL | |
| last_login | datetime | YES | | NULL | |
| is_superuser | tinyint(1) | NO | | NULL | |
| username | varchar(30) | NO | UNI | NULL | |
| first_name | varchar(30) | NO | | NULL | |
| last_name | varchar(30) | NO | | NULL | |
| email | varchar(254) | NO | | NULL | |
| is_staff | tinyint(1) | NO | | NULL | |
| is_active | tinyint(1) | NO | | NULL | |
| date_joined | datetime | NO | | NULL | |
+--------------+--------------+------+-----+---------+----------------+

编辑我们的新建的用户app的models.py
先import AbstractUser,然后定义我们的类的时候,继承它就好了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from django.contrib.auth.models import AbstractUser


# Create your models here.
class UserProfile(AbstractUser):
nickname = models.CharField(verbose_name=u"用户名", max_length=50)
birthday = models.DateField(verbose_name=u"生日", null=True, blank=True)
gender = models.CharField(verbose_name=u"性别", choices=(("male", u'男'), ("female", u'女')),
default="female", max_length=5)
address = models.CharField(verbose_name=u"地址", max_length=100, default=u"")
mobile = models.CharField(verbose_name=u"手机", max_length=11, null=True, blank=True)
image = models.ImageField(verbose_name=u"头像", upload_to="images/%Y/%M", default=u"images/default.jpg")

class Meta:
verbose_name = u"用户资料"
verbose_name_plural = verbose_name

def __unicode__(self):
return self.username

完事后在settings.py 注册我们的app,

再加上一条AUTH_USER_MODEL = "users.UserProfile" 指定我们新的用户模型
生成数据表

1
2
makemigrations users
migrate users

增加后新的表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
MySQL [opencourse]> desc users_userprofile;
+--------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| password | varchar(128) | NO | | NULL | |
| last_login | datetime | YES | | NULL | |
| is_superuser | tinyint(1) | NO | | NULL | |
| username | varchar(30) | NO | UNI | NULL | |
| first_name | varchar(30) | NO | | NULL | |
| last_name | varchar(30) | NO | | NULL | |
| email | varchar(254) | NO | | NULL | |
| is_staff | tinyint(1) | NO | | NULL | |
| is_active | tinyint(1) | NO | | NULL | |
| date_joined | datetime | NO | | NULL | |
| nickname | varchar(50) | NO | | NULL | |
| birthday | date | YES | | NULL | |
| gender | varchar(5) | NO | | NULL | |
| address | varchar(100) | NO | | NULL | |
| mobile | varchar(11) | YES | | NULL | |
| image | varchar(100) | NO | | NULL | |
+--------------+--------------+------+-----+---------+----------------+

done.

关注公众号 尹安灿

先导入自己的数据模型
from .models import UserMessage

1
2
3
4
5
6
user_message = UserMessage()
user_message.name = 'bob'
user_message.email = 'test@qq.com'
user_message.address = 'guangzhou'
user_message.message = 'sth.'
user_message.save()

结果:

1
2
3
4
5
6
7
MySQL [opencourse]> select * from message_usermessage;
+----+------+-------------+-----------+---------+
| id | name | email | address | message |
+----+------+-------------+-----------+---------+
| 1 | bob | test@qq.com | guangzhou | sth. |
+----+------+-------------+-----------+---------+

删除的话,调用继承过来的delete()方法即可。
下面删除ID为1的结果

1
2
3
4
5
    user_message = UserMessage.objects.filter(id=1)
# user_message = UserMessage.objects.all()
# user_message.delete()
for message in user_message:
message.delete()

可以直接user_message.delete()所有符合结果的都删除,或者遍历删除,看情况选择使用。

1
2
for message in user_message:
message.delete()

两种方法

1
2
user_message = UserMessage.objects.filter(id=1)
user_message.update(address='shenzhen')

或者

1
2
3
user_message = UserMessage.objects.get(id=1)
user_message.address = 'nanjing'
user_message.save()

结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
第一种方法
MySQL [opencourse]> select * from message_usermessage;
+----+------+-------------+----------+---------+
| id | name | email | address | message |
+----+------+-------------+----------+---------+
| 1 | bob | test@qq.com | shenzhen | sth. |
+----+------+-------------+----------+---------+
1 row in set (0.00 sec)
第二种方法结果
MySQL [opencourse]> select * from message_usermessage;
+----+------+-------------+---------+---------+
| id | name | email | address | message |
+----+------+-------------+---------+---------+
| 1 | bob | test@qq.com | nanjing | sth. |
+----+------+-------------+---------+---------+
1 row in set (0.00 sec)


查询

查询方法还是灵活多变的。filter和get区别
简单来说get的如果多于两条数据,或者没有数据就会报错,它返回对象形式。而filter会返回数组形式。

1
2
3
4
5
UserMessage.objects.all()
UserMessage.objects.all().values('name') # 只取user列
UserMessage.objects.all().values_list('id', 'name') # 取出id和name列
UserMessage.objects.get(id=1)
UserMessage.objects.filter(name='bob')

参考资料

Django-Model操作数据库(增删改查、连表结构)

关注公众号 尹安灿

django是通过ORM访问数据库的,所以,它需要自己定义数据模型。

打开相应app/models.py

1
2
3
4
5
6
7
8
9
class UserMessage(models.Model):
name = models.CharField(verbose_name=u"名字", max_length=50)
email = models.EmailField(verbose_name=u"邮箱地址")
address = models.CharField(verbose_name=u"联系地址", max_length=100)
message = models.CharField(verbose_name=u"留言", max_length=100)

class Meta:
verbose_name = u'用户记录'
verbose_name_plural = verbose_name

定义字段,字段类型,长度,描述名。
除了上诉的字符类型,还有以下的数据类型可以定义

1
2
3
4
5
6
7
8
9
10
__all__ = [str(x) for x in (
'AutoField', 'BLANK_CHOICE_DASH', 'BigIntegerField', 'BinaryField',
'BooleanField', 'CharField', 'CommaSeparatedIntegerField', 'DateField',
'DateTimeField', 'DecimalField', 'DurationField', 'EmailField', 'Empty',
'Field', 'FieldDoesNotExist', 'FilePathField', 'FloatField',
'GenericIPAddressField', 'IPAddressField', 'IntegerField', 'NOT_PROVIDED',
'NullBooleanField', 'PositiveIntegerField', 'PositiveSmallIntegerField',
'SlugField', 'SmallIntegerField', 'TextField', 'TimeField', 'URLField',
'UUIDField',
)]

<path-to-your-project>/settings.py
添加自己的app到INSTALLED_APPS

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',
'message',
]

然后运行命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
manage.py@opencourse > makemigrations message
Migrations for 'message':
0001_initial.py:
- Create model UserMessage
Following files were affected
/g/project/opencourse/apps/message/migrations/0001_initial.py
Process finished with exit code 0
manage.py@opencourse > migrate message
migrate message /g/project/opencourse"
Operations to perform:
Apply all migrations: message
Running migrations:
Rendering model states... DONE
Applying message.0001_initial... OK

Process finished with exit code 0

这个时候就可以看到数据库已经生成了一个新的表:

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
MySQL [opencourse]> show tables;
+----------------------------+
| Tables_in_opencourse |
+----------------------------+
| auth_group |
| auth_group_permissions |
| auth_permission |
| auth_user |
| auth_user_groups |
| auth_user_user_permissions |
| django_admin_log |
| django_content_type |
| django_migrations |
| django_session |
| message_usermessage |
+----------------------------+
11 rows in set (0.00 sec)

MySQL [opencourse]> desc message_usermessage;
+---------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(50) | NO | | NULL | |
| email | varchar(254) | NO | | NULL | |
| address | varchar(100) | NO | | NULL | |
| message | varchar(100) | NO | | NULL | |
+---------+--------------+------+-----+---------+----------------+
5 rows in set (0.00 sec)

MySQL [opencourse]>

除此之外,还可以定义索引,自定义表名等。

##参考资料

Model field reference
Model Meta options

关注公众号 尹安灿

  1. 编写views方法,渲染模板
  2. 设置静态文件路径
  3. 设置URL规则

编写渲染的方法

在相应的app下面找到views.py
<path-to-your-app>/views.py

1
2
def getform(request):
return render(request,'message_form.html')

设置静态文件路径

因为模板引用了一些静态资源,但是你得告诉django它路径在哪里。新增配置STATICFILES_DIRS,指定静态URL。

1
2
3
4
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR,'static'),
]

编辑<path-to-your-project>/urls.py
先导入自己的app的getform方法,配置URL url(r'^form/$',getform)

1
2
3
4
5
6
from <path-to-your-app>.views import getform
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^form/$',getform),
]

done.

关注公众号 尹安灿

##更改配置

<project_name>/settings.py 一开始是使用sqlite3的,改成MySQL的就好

1
2
3
4
5
6
7
8
9
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'opencourse',
'USER': 'opencourse',
'PASSWORD': 'opencourse',
'HOST': '172.25.254.10'
}
}

安装驱动

*如果没有安装MySQL驱动的,就pip install MySQL-python 安装一个.如果出现错误,提示没有找到mysql_config的。
Ubuntu类的安装apt install libmysqlclient-dev,Redhat类yum install -y mysql-devel

在确保安装了libmysqlclient-dev或者mysql-devel的同学,如果使用pycharm的话,直接File->Settins->Project Interpreter点加号+ 搜索mysql,然后点击Install Package即可。

生成数据库表

python manage.py makemigrations,或者pycharm中,Tools->Run manage.py Task 直接输入makemigrations,然后migrate。

如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
manage.py@opencourse > makemigrations
No changes detected
manage.py@opencourse > migrate
Operations to perform:
Apply all migrations: admin, contenttypes, auth, sessions
Running migrations:
Rendering model states... DONE
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... 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 sessions.0001_initial... OK

关注公众号 尹安灿

第一个print是100内的质数列表。
第二个是列表的数字求和
第三个是列表数字换成它的平方数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env python

def is_prime(x):
if x<=1:
return False
for i in range(2,x):
if x % i == 0:
return False
return True

if __name__ == '__main__':
n = [x for x in range(1,101)] # 生成1-199的列表
print(filter(is_prime,n)) # 筛选出100内的质数
print(reduce(lambda x,y:x+y,n)) # 用reduce特性求和
print(map(lambda x:x*x,n)) # 用map求平方

Output:

1
2
3
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
5050
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200]

参考资料:
PEP 8 – Style Guide for Python Code

关注公众号 尹安灿

今天给测试环境配置https的时候遇到了问题。

先后排除了证书错误,防火墙,nginx -V确定相关模块存在,但是依然不行。

查看 nginx error日志

发现如下结果:

1
2
2017/11/22 12:18:11 [error] 18365#18365: *10 no "ssl_certificate" is defined in server listening on SSL port while SSL handshaking, client: 120.197.49.xxx, server: 0.0.0.0:443

寻找资料,提到是监听了443端口,但是没有指定证书之类的东西。

于是我cat /etc/nginx/conf.d/* | grep 443
发现一条

1
2
3
4
5
6
7
server {
listen *:443 default;
server_name _;
return 444;
access_log off;
}

之前为了屏蔽空主机名瞎访问,我添加了一条80端口的,又想当然地配置了一个443的。

现在把这个注释掉,重启nginx。一切正常。

参考资料

参考资料

关注公众号 尹安灿

错误提示:

xxx :Read-only file system

尝试了用 ntfs-3g挂载,fstab也写明是rw权限,但是就是不行。

最后还是用

sudo ntfsfix /dev/sdbxxx 指定NTFS格式的磁盘。

然后remount一下就好了。

—更新
主要原因还是windows开启了快速启动。

1
2
3
4
5
  The disk contains an unclean file system (0, 0).
Metadata kept in Windows cache, refused to mount.
Falling back to read-only mount because the NTFS partition is in an
unsafe state. Please resume and shutdown Windows fully (no hibernation
or fast restarting.)

metadata存在cache,Linux挂载的时候,不敢清除这些cache,所以只能以只读方式打开。

在BIOS关闭快速启动后,如果还不行,进去windows,电源-更改当前不可用设置-快速启动去掉。

关注公众号 尹安灿

今天开发说有一台服务器crontab任务执行异常。

同样的账户上去手动运行命令就能正确执行该命令。当时就感觉遇到灵异事件了。

吃完饭再仔细看看。

先把crontab要执行的命令重定向错误输出到文件。

1
*/ * * * * xxxx xxxx > ~/errors 2>&1

发现是如下错误:

/usr/bin/env: php: No such file or directory

说找不到PHP。基本可以判定是环境变量问题。可能当初php安装的时候没有加入到一个常用的路径中。

which php 得到php路径。

新建了一个脚本专门执行这条之前的命令,前面指定。

1
2
3
#!/bin/bash
export PATH=$PATH:/usr/local/bin
xxxx xxxx

或者直接导入环境变量再执行。

1
*/ * * * * source ~/.bashrc && xxxx xxxx > ~/errors 2>&1

关注公众号 尹安灿

0%