我们将建立一个用户注册和身份验证系统,让用户能够注册账户,进而登录和注销。我们将创建一个新的应用程序,其中包含与处理用户账户相关的所有功能。我们还将对模型Topic 稍做修改,让每个主题都归属于特定用户。

1、应用程序users

我们首先使用命令startapp 来创建一个名为users 的应用程序:

  1. (ll_env)learning_log$ python manage.py startapp users
  2. (ll_env)learning_log$ ls
  3. db.sqlite3 learning_log learning_logs ll_env manage.py users
  4. (ll_env)learning_log$ ls users
  5. admin.py __init__.py migrations models.py tests.py views.py

这个命令新建一个名为users的目录,其结构与应用程序learning_logs 相同。

1.1 将应用程序users 添加到settings.py中

在settings.py中,我们需要将这个新的应用程序添加到INSTALLED_APPS 中,如下所示:

  1. INSTALLED_APPS = [
  2. 'django.contrib.admin',
  3. 'django.contrib.auth',
  4. 'django.contrib.contenttypes',
  5. 'django.contrib.sessions',
  6. 'django.contrib.messages',
  7. 'django.contrib.staticfiles',
  8.  
  9. # 我的应用程序
  10. 'learning_logs',
  11. 'users',
  12. ]

1.2 包含应用程序users 的URL

接下来,我们需要修改项目根目录中的urls.py,使其包含我们将为应用程序users 定义的URL:

  1. from django.contrib import admin
  2. from django.conf.urls import url, include
  3.  
  4. urlpatterns = [
  5. url(r'^admin/', admin.site.urls),
  6. url(r'', include('learning_logs.urls',namespace='learning_logs')),
  7. url(r'^users/', include('users.urls', namespace='users')),
  8. ]

我们添加了一行代码,以包含应用程序users 中的文件urls.py。这行代码与任何以单词users打头的URL(如http://localhost:8000/users/login/)都匹配。我们还创建了命名空 间'users' ,以便将应用程序learning_logs 的URL同应用程序users 的URL区分开来。

2、登陆页面

我们首先来实现登录页面的功能。为此,我们将使用Django提供的默认登录视图,因此URL模式会稍有不同。在目录learning_log/users/中,新建一个名为urls.py的文件,并在其中添加如下代码:

  1. from django.conf.urls import url
  2. from django.contrib.auth.views import LoginView
  3.  
  4. from . import views
  5. app_name='users'
  6.  
  7. urlpatterns = [
  8. # 登录页面
  9. url(r'^login/$', LoginView.as_view(template_name='users/login.html'),
  10. name='login'),
  11.  
  12. ]

我们首先导入了默认视图login 。登录页面的URL模式与URL http://localhost:8000/users/login/匹配。这个URL中的单词users让Django在users/urls.py中查找,而单词 login让它将请求发送给Django默认视图login (请注意,视图实参为login ,而不是views.login )。鉴于我们没有编写自己的视图函数,我们传递了一个字典,告诉Django 去哪里查找我们将编写的模板。这个模板包含在应用程序users 而不是learning_logs 中。

(1)模板login.html

用户请求登录页面时,Django将使用其默认视图login ,但我们依然需要为这个页面提供模板。为此,在目录learning_log/users/中,创建一个名为templates的目录,并在其中创建一个名为users的目录。以下是模板login.html,你应将其存储到目录learning_log/users/templates/users/中:

  1. {% extends "learning_logs/base.html" %}
  2.  
  3. {% block content %}
  4.  
  5. {% if form.errors %}
  6. <p>Your username and password didn't match. Please try again.</p>
  7. {% endif %}
  8.  
  9. <form method="post" action="{% url 'users:login' %}">
  10. {% csrf_token %}
  11. {{ form.as_p }}
  12.  
  13. <button name="submit">log in</button>
  14. <input type="hidden" name="next" value="{% url 'learning_logs:index' %}" />
  15. </form>
  16.  
  17. {% endblock content %}
  • 这个模板继承了base.html,旨在确保登录页面的外观与网站的其他页面相同。请注意,一个应用程序中的模板可继承另一个应用程序中的模板。
  • 如果表单的errors 属性被设置,我们就显示一条错误消息,指出输入的用户名—密码对与数据库中存储的任何用户名—密码对都不匹配。

我们要让登录视图处理表单,因此将实参action 设置为登录页面的URL。登录视图将一个表单发送给模板,在模板中,我们显示这个表单并添加一个提交按 钮。我们包含了一个隐藏的表单元素——'next' ,其中的实参value 告诉Django在用户成功登录后将其重定向到什么地方——在这里是主页。

(2)链接到登陆页面

下面在learning_logs/templates/learning_logs/base.html中添加到登录页面的链接,让所有页面都包含它。用户已登录时,我们不想显示这个链接,因此将它嵌套在一个{% if %}标签中:

  1. <p>
  2. <a href="{% url 'learning_logs:index' %}">Learning Log</a>
  3. <a href="{% url 'learning_logs:topics' %}">Topics</a>
  4. {% if user.is_authenticated %}
  5. Hello, {{ user.username }}.
  6. {% else %}
  7. <a href="{% url 'users:login' %}">log in</a>
  8. {% endif %}
  9. </p>
  10.  
  11. {% block content %}{% endblock content %}

在Django身份验证系统中,每个模板都可使用变量user ,这个变量有一个is_authenticated 属性:如果用户已登录,该属性将为True ,否则为False 。这让你能够向已 通过身份验证的用户显示一条消息,而向未通过身份验证的用户显示另一条消息。
在这里,我们向已登录的用户显示一条问候语。对于已通过身份验证的用户,还设置了属性username ,我们使用这个属性来个性化问候语,让用户知道他已登录。对于还未通过身份验证的用户,我们再显示一个到登录页面的链接。
(3)使用登陆页面

前面建立了一个用户账户,下面来登录一下,看看登录页面是否管用。请访问http://localhost:8000/admin/,如果你依然是以管理员的身份登录的,请在页眉上找到注销链接并单击
它。
注销后,访问http://localhost:8000/users/login/,你将看到类似于图19-4所示的登录页面。输入你在前面设置的用户名和密码,将进入页面index。。在这个主页的页眉中,显示了一条 个性化问候语,其中包含你的用户名。

3、注销

现在需要提供一个让用户注销的途径。我们不创建用于注销的页面,而让用户只需单击一个链接就能注销并返回到主页。为此,我们将为注销链接定义一个URL模式,编写一个 视图函数,并在base.html中添加一个注销链接。

(1)注销url

下面的代码为注销定义了URL模式,该模式与URL http://locallwst:8000/users/logout/匹配。修改后的users/urls.py如下:

  1. from django.conf.urls import url
  2. from django.contrib.auth.views import LoginView
  3.  
  4. from . import views
  5. app_name='users'
  6.  
  7. urlpatterns = [
  8. # 登录页面
  9. url(r'^login/$', LoginView.as_view(template_name='users/login.html'),
  10. name='login'),
  11.  
  12. # 注销
  13. url(r'^logout/$', views.logout_view, name='logout'),
  14. ]

这个URL模式将请求发送给函数logout_view() 。这样给这个函数命名,旨在将其与我们将在其中调用的函数logout() 区分开来。

2. 视图函数logout_view()

函数logout_view() 很简单:只是导入Django函数logout() ,并调用它,再重定向到主页。请打开users/views.py,并输入下面的代码:

  1. from django.shortcuts import render
  2. from django.http import HttpResponseRedirect
  3. from django.urls import reverse
  4. from django.contrib.auth import logout
  5.  
  6. def logout_view(request):
  7. """注销用户"""
  8. logout(request)
  9. return HttpResponseRedirect(reverse('learning_logs:index'))

我们从django.contrib.auth中导入了函数logout()。我们调用了函数logout() ,它要求将request 对象作为实参。然后,我们重定向到主页。

(3)链接到注销页面

现在我们需要添加一个注销链接。我们在learning_logs/templates/learning_logs/base.html 中添加这种链接,让每个页面都包含它;我们将它放在标签{% if user.is_authenticated %}中,使得仅当用户登录后 才能看到它:

  1. <p>
  2. <a href="{% url 'learning_logs:index' %}">Learning Log</a>
  3. <a href="{% url 'learning_logs:topics' %}">Topics</a>
  4. {% if user.is_authenticated %}
  5. Hello, {{ user.username }}.
  6. <a href="{% url 'users:logout' %}">log out</a>
  7. {% else %}
  8. <a href="{% url 'users:login' %}">log in</a>
  9. {% endif %}
  10. </p>
  11.  
  12. {% block content %}{% endblock content %}

下图显示了用户登录后看到的主页。这里的重点是创建能够正确工作的网站,因此几乎没有设置任何样式。确定所需的功能都能正确运行后,我们将设置这个网站的样式,使 其看起来更专业。

4、注册页面

下面来创建一个让新用户能够注册的页面。我们将使用Django提供的表单UserCreationForm,但编写自己的视图函数和模板。

(1)注册页面的URL模式

下面的代码定义了注册页面的URL模式,它也包含在users/urls.py中:

  1. from django.conf.urls import url
  2. from django.contrib.auth.views import LoginView
  3.  
  4. from . import views
  5. app_name='users'
  6.  
  7. urlpatterns = [
  8. # 登录页面
  9. url(r'^login/$', LoginView.as_view(template_name='users/login.html'),
  10. name='login'),
  11.  
  12. # 注销
  13. url(r'^logout/$', views.logout_view, name='logout'),
  14.  
  15. # 注册页面
  16. url(r'^register/$', views.register, name='register'),
  17. ]

(2). 视图函数register()

在注册页面首次被请求时,视图函数register() 需要显示一个空的注册表单,并在用户提交填写好的注册表单时对其进行处理。如果注册成功,这个函数还需让用户自动登 录。请在users/views.py中添加如下代码:

  1. from django.shortcuts import render
  2. from django.http import HttpResponseRedirect
  3. from django.urls import reverse
  4. from django.contrib.auth import login, logout, authenticate
  5. from django.contrib.auth.forms import UserCreationForm
  6.  
  7. def logout_view(request):
  8. """注销用户"""
  9. logout(request)
  10. return HttpResponseRedirect(reverse('learning_logs:index'))
  11.  
  12. def register(request):
  13. """注册新用户"""
  14. if request.method != 'POST':
  15. # 显示空的注册表单
  16. form = UserCreationForm()
  17. else:
  18. # 处理填写好的表单
  19. form = UserCreationForm(data=request.POST)
  20.  
  21. if form.is_valid():
  22. new_user = form.save()
  23. # 让用户自动登录,再重定向到主页
  24. authenticated_user = authenticate(username=new_user.username,
  25. password=request.POST['password1'])
  26. login(request, authenticated_user)
  27. return HttpResponseRedirect(reverse('learning_logs:index'))
  28.  
  29. context = {'form': form}
  30. return render(request, 'users/register.html', context)
  • 我们首先导入了函数render() ,然后导入了函数login() 和authenticate() ,以便在用户正确地填写了注册信息时让其自动登录。我们还导入了默认表 单UserCreationForm 。
  • 在函数register() 中,我们检查要响应的是否是POST请求。如果不是,就创建一个UserCreationForm 实例,且不给它提供任何初始数据。如果响应的是POST请求,我们就根据提交的数据创建一个UserCreationForm 实例,并检查这些数据是否有效:就这里而言,是用户名未包含非法字符,输入的两个密码相同,以及用户没有试图做恶意的事情。
  • 如果提交的数据有效,我们就调用表单的方法save() ,将用户名和密码的散列值保存到数据库中。方法save() 返回新创建的用户对象,我们将其存储在new_user 中。
  • 保存用户的信息后,我们让用户自动登录,这包含两个步骤。首先,我们调用authenticate() ,并将实参new_user.username 和密码传递给它。用户注册时, 被要求输入密码两次;由于表单是有效的,我们知道输入的这两个密码是相同的,因此可以使用其中任何一个。在这里,我们从表单的POST数据中获取与键'password1' 相关 联的值。如果用户名和密码无误,方法authenticate() 将返回一个通过了身份验证的用户对象,而我们将其存储在authenticated_user 中。
  • 我们调用函 数login() ,并将对象request 和authenticated_user 传递给它,这将为新用户创建有效的会话。最后,我们将用户重定向到主页,其页眉中显示了 一条个性化的问候语,让用户知道注册成功了。

(3)注册模板

注册页面的模板与登录页面的模板类似,请务必将其保存到login.html所在的目录中:

  1. {% extends "learning_logs/base.html" %}
  2.  
  3. {% block content %}
  4.  
  5. <form method="post" action="{% url 'users:register' %}">
  6. {% csrf_token %}
  7. {{ form.as_p }}
  8.  
  9. <button name="submit">register</button>
  10. <input type="hidden" name="next" value="{% url 'learning_logs:index' %}" />
  11. </form>
  12.  
  13. {% endblock content %}

这里也使用了方法as_p ,让Django在表单中正确地显示所有的字段,包括错误消息——如果用户没有正确地填写表单。

(4)链接到注册页面

我们在learning_logs/templates/learning_logs/base.html添加这样的代码,即在用户没有登录时显示到注册页面的链接:

  1. <p>
  2. <a href="{% url 'learning_logs:index' %}">Learning Log</a>
  3. <a href="{% url 'learning_logs:topics' %}">Topics</a>
  4. {% if user.is_authenticated %}
  5. Hello, {{ user.username }}.
  6. <a href="{% url 'users:logout' %}">log out</a>
  7. {% else %}
  8. <a href="{% url 'users:register' %}">register</a>
  9. <a href="{% url 'users:login' %}">log in</a>
  10. {% endif %}
  11. </p>
  12.  
  13. {% block content %}{% endblock content %}

现在,已登录的用户看到的是个性化的问候语和注销链接,而未登录的用户看到的是注册链接和登录链接。请尝试使用注册页面创建几个用户名各不相同的用户账户。
注意  这里的注册系统允许用户创建任意数量的账户。有些系统要求用户确认其身份:发送一封确认邮件,用户回复后其账户才生效。通过这样做,系统生成的垃圾账户将比这里使用的简单系统少。然而,学习创建应用程序时,完全可以像这里所做的那样,使用简单的用户注册系统。

5、让用户拥有自己的数据

用户应该能够输入其专有的数据,因此我们将创建一个系统,确定各项数据所属的用户,再限制对页面的访问,让用户只能使用自己的数据。
在本节中,我们将修改模型Topic ,让每个主题都归属于特定用户。这也将影响条目,因为每个条目都属于特定的主题。我们先来限制对一些页面的访问。

5.1、使用@login_required 限制访问

Django提供了装饰器@login_required ,让你能够轻松地实现这样的目标:对于某些页面,只允许已登录的用户访问它们。装饰器 (decorator)是放在函数定义前面的指 令,Python在函数运行前,根据它来修改函数代码的行为。下面来看一个示例。
1. 限制对topics 页面的访问
每个主题都归特定用户所有,因此应只允许已登录的用户请求topics 页面。为此,在learning_logs/views.py中添加如下代码: views.py

  1. from django.shortcuts import render
  2. from django.http import HttpResponseRedirect
  3. from django.urls import reverse
  4. from django.contrib.auth.decorators import login_required
  5.  
  6. from .models import Topic, Entry
  7. from .forms import TopicForm,EntryForm
  8.  
  9. def index(request):
  10. """学习笔记的主页"""
  11. return render(request, 'learning_logs/index.html')
  12.  
  13. @login_required
  14. def topics(request):
  15. """显示所有的主题"""
  16. topics = Topic.objects.order_by('date_added')
  17. context = {'topics': topics}
  18. return render(request, 'learning_logs/topics.html', context)
  19.  
  20. def topic(request, topic_id):
  21. """显示特定主题的详细页面"""
  22. topic = Topic.objects.get(id=topic_id)
  23. entries = topic.entry_set.order_by('-date_added')
  24. context = {'topic': topic, 'entries': entries}
  25. return render(request, 'learning_logs/topic.html', context)
  26.  
  27. def new_topic(request):
  28. """添加新主题"""
  29. if request.method != 'POST':
  30. # 未提交数据:创建一个新表单
  31. form = TopicForm()
  32. else:
  33. # POST提交的数据,对数据进行处理
  34. form = TopicForm(request.POST)
  35. if form.is_valid():
  36. form.save()
  37. return HttpResponseRedirect(reverse('learning_logs:topics'))
  38. context = {'form': form}
  39. return render(request, 'learning_logs/new_topic.html', context)
  40.  
  41. def new_entry(request, topic_id):
  42. """在特定的主题中添加新条目"""
  43. topic = Topic.objects.get(id=topic_id)
  44.  
  45. if request.method != 'POST':
  46. # 未提交数据,创建一个空表单
  47. form = EntryForm()
  48. else:
  49. # POST提交的数据,对数据进行处理
  50. form = EntryForm(data=request.POST)
  51. if form.is_valid():
  52. new_entry = form.save(commit=False)
  53. new_entry.topic = topic
  54. new_entry.save()
  55. return HttpResponseRedirect(reverse('learning_logs:topic',
  56. args=[topic_id]))
  57. context = {'topic': topic, 'form': form}
  58. return render(request, 'learning_logs/new_entry.html', context)
  59.  
  60. def edit_entry(request, entry_id):
  61. """编辑既有条目"""
  62. entry = Entry.objects.get(id=entry_id)
  63. topic = entry.topic
  64.  
  65. if request.method != 'POST':
  66. # 初次请求,使用当前条目填充表单
  67. form = EntryForm(instance=entry)
  68. else:
  69. # POST提交的数据,对数据进行处理
  70. form = EntryForm(instance=entry, data=request.POST)
  71. if form.is_valid():
  72. form.save()
  73. return HttpResponseRedirect(reverse('learning_logs:topic',
  74. args=[topic.id]))
  75. context = {'entry': entry, 'topic': topic, 'form': form}
  76. return render(request, 'learning_logs/edit_entry.html', context)

我们首先导入了函数login_required() 。我们将login_required() 作为装饰器用于视图函数topics() ——在它前面加上符号@ 和login_required ,让Python在运 行topics() 的代码前先运行login_required() 的代码。
login_required() 的代码检查用户是否已登录,仅当用户已登录时,Django才运行topics() 的代码。如果用户未登录,就重定向到登录页面。 为实现这种重定向,我们需要修改settings.py,让Django知道到哪里去查找登录页面。请在项目learning_log的Django设置settings.py末尾添加如下代码:

  1. # 我的设置
  2. LOGIN_URL = '/users/login/'

现在,如果未登录的用户请求装饰器@login_required 的保护页面,Django将重定向到settings.py中的LOGIN_URL 指定的URL。
要测试这个设置,可注销并进入主页。然后,单击链接Topics,这将重定向到登录页面。接下来,使用你的账户登录,并再次单击主页中的Topics链接,你将看到topics页面。

2、全面限制对项目“学习笔记”的访问

Django让你能够轻松地限制对页面的访问,但你必须针对要保护哪些页面做出决定。最好先确定项目的哪些页面不需要保护,再限制对其他所有页面的访问。你可以轻松地修改 过于严格的访问限制,其风险比不限制对敏感页面的访问更低。
在项目“学习笔记”中,我们将不限制对主页、注册页面和注销页面的访问,并限制对其他所有页面的访问。 在下面的learning_logs/views.py中,对除index() 外的每个视图都应用了装饰器@login_required :

  1. --snip--
  2. @login_required
  3. def topics(request):
  4. --snip--
  5.  
  6. @login_required
  7. def topic(request, topic_id):
  8. --snip--
  9.  
  10. @login_required
  11. def new_topic(request):
  12. --snip--
  13.  
  14. @login_required
  15. def new_entry(request, topic_id):
  16. --snip--
  17.  
  18. @login_required
  19. def edit_entry(request, entry_id):
  20. --snip--

如果你在未登录的情况下尝试访问这些页面,将被重定向到登录页面。另外,你还不能单击到new_topic 等页面的链接。但如果你输入URL http://localhost:8000/new_topic/,将重 定向到登录页面。对于所有与私有用户数据相关的URL,都应限制对它们的访问。

3、将数据关联到用户

现在,需要将数据关联到提交它们的用户。我们只需将最高层的数据关联到用户,这样更低层的数据将自动关联到用户。例如,在项目“学习笔记”中,应用程序的最高层数据是
主题,而所有条目都与特定主题相关联。只要每个主题都归属于特定用户,我们就能确定数据库中每个条目的所有者。
下面来修改模型Topic ,在其中添加一个关联到用户的外键。这样做后,我们必须对数据库进行迁移。最后,我们必须对有些视图进行修改,使其只显示与当前登录的用户相关 联的数据。

(1)修改模型Topic

对models.py的修改只涉及两行代码:

  1. from django.db import models
  2. from django.contrib.auth.models import User
  3.  
  4. class Topic(models.Model):
  5. """用户要学习的主题"""
  6. text = models.CharField(max_length=200)
  7. date_added = models.DateTimeField(auto_now_add=True)
  8. owner = models.ForeignKey(User)
  9.  
  10. def __str__(self):
  11. """返回模型的字符串表示"""
  12. return self.text
  13.  
  14. class Entry(models.Model): --snip--

我们首先导入了django.contrib.auth 中的模型User ,然后在Topic 中添加了字段owner ,它建立到模型User 的外键关系。

(2) 确定当前有哪些用户

我们迁移数据库时,Django将对数据库进行修改,使其能够存储主题和用户之间的关联。为执行迁移,Django需要知道该将各个既有主题关联到哪个用户。最简单的办法是,将既 有主题都关联到同一个用户,如超级用户。为此,我们需要知道该用户的ID。
下面来查看已创建的所有用户的ID。为此,启动一个Django shell会话,并执行如下命令:

  1. (ll_env) [root@xxjt learning_log]# python3 manage.py shell>>> from django.contrib.auth.models import User
  2. >>> User.objects.all()
  3. <QuerySet [<User: happy>, <User: test1234>]>
  4. >>>
  5. >>> for user in User.objects.all():
  6. ... print(user.username, user.id)
  7. ...
  8. happy 1
  9. test1234 2

我们在shell会话中导入了模型User 。然后,我们查看到目前为止都创建了哪些用户。 我们遍历用户列表,并打印每位用户的用户名和ID。Django询问要将既有主题关联到哪个用户时,我们将指定其中的一个ID值。

3. 迁移数据库

知道用户ID后,就可以迁移数据库了。

参考资料:

1、python编程,从入门到实践

Django web编程3 -- 创建用户账户的更多相关文章

  1. Django web编程1 -- 创建项目和应用

    python:3.7.2 Django:2.1.7 1.创建虚拟环境 虚拟环境是系统的一个位置,可以在其中安装包,并将其与其他python包隔离. 创建目录,命名为learning_log,并切换到这 ...

  2. Django web编程2 -- 编辑页面内容

    你将创建一些表单,让用户能够添加主题和条目,以及编辑既有的条目.你还将学习Django如何防范对基于表单的网页发起的常见攻击,这让你无需花太多时间考虑确保应用程序安全的问题. 然后,我们将实现一个用户 ...

  3. Django学习路13_创建用户登录,判断数据库中账号名密码是否正确

    在 models.py 中设置数据库表的信息 from django.db import models # Create your models here. class User(models.Mod ...

  4. 用户账户——《Python编程从入门到实践》

    Web应用程序的核心是让任何用户都能够注册账户并能够使用它,不管用户身处何方 1.让用户能够输入数据 建立用于创建用户的身份验证系统之前,我们先来添加几个页面,让用户能够输入数据.当前,只有超级用户能 ...

  5. 教程:Visual Studio 中的 Django Web 框架入门

    教程:Visual Studio 中的 Django Web 框架入门 Django 是高级 Python 框架,用于快速.安全及可扩展的 Web 开发. 本教程将在 Visual Studio 提供 ...

  6. Linux字符界面下用户账户的设置

    在Linux系统字符界面下创建.修改以及删除用户账户主要使用useradd,usermod和userdel这3个命令. 一.创建用户账户 创建用户账户就是在系统中创建一个新账户,然后为新账户分配用户U ...

  7. MongoDB学习(配置用户账户和访问控制)

    理解admin数据库 安装MongoDB时,会自动创建admin数据库,这是一个特殊的库.有些用户账户角色赋予用户操作多个数据库的权限,而这些用户只能在admin数据库中创建.要创建有权操作所有数据库 ...

  8. Django Web开发【3】创建网络收藏夹

    这一节我们将继续一个创建网络收藏夹应用,并学习视图.模型以及模板的处理过程. Django是一个MVC开发框架,但是它的控制器对应的为view,而视图对应为模板(template),模型对应model ...

  9. Django 小实例S1 简易学生选课管理系统 3 创建用户模型(model)

    Django 小实例S1 简易学生选课管理系统 第3节--创建用户模型(model) 点击查看教程总目录 作者自我介绍:b站小UP主,时常直播编程+红警三,python1对1辅导老师. 本文涉及到的新 ...

随机推荐

  1. Android ble蓝牙使用注意

    以下均为自己在Android ble开发项目中遇到的问题 1.尽量不要在BluetoothGattCallback里面的回调函数中执行读写通知操作,最多一个,因为例如在onServicesDiscov ...

  2. Socket 通讯原理

    Socket是什么呢? Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后 ...

  3. Spark 基本函数学习笔记一

      Spark 基本函数学习笔记一¶ spark的函数主要分两类,Transformations和Actions. Transformations为一些数据转换类函数,actions为一些行动类函数: ...

  4. Mac Git 安装和配置

    一.git下载与安装 点击Git,然后选择下载安装包 git --version,终端输入该命令, 如输出版本号,则说明安装成功. git version 2.20.1 二.git基本配置 通过下面这 ...

  5. Win 10 无法打开内核设备“\\.\Global\vmx86”问题

    Win 10操作系统, VMWareWorkstation10 无法打开内核设备"\\.\Global\vmx86": 系统找不到指定的文件.你想要在安装 VMware Works ...

  6. Excel自定义公式,类似VLOOKUP的查询

    Excel在使用VLOOKUP时,当检索值超过255长度的时候就会报错,没法正常检索. 官方提供的办法是通过INDEX和MATCH公式组合使用来解决. 微软官方方案 1,公式 =INDEX($A$5: ...

  7. 使用docker快速搭建nginx+php环境

    在朋友的强烈推荐下,走上了docker之路.经过了繁琐的docker环境安装,看了下镜像/容器的简单使用,开始进行nginx+php环境的搭建,本文记录一下在安装过程中的笔记. 原文地址:代码汇个人博 ...

  8. Mysql原理与优化

    原文:https://mp.weixin.qq.com/s__biz=MzI4NTA1MDEwNg==&mid=2650763421&idx=1&sn=2515421f09c1 ...

  9. 求导程序编写(oo-java编程)

    本单元的任务为求导. 即将一个含自变量x的多项式F求导成为另外一个含自变量x的多项式f.使得 dF/dx = f 为降低我们的难度,这个任务被分解成了三个阶段: (1)对幂函数进行求导(不允许嵌套) ...

  10. php将字符串转为二进制数据串

    /** * 将字符串转换成二进制 * @param type $str * @return type */ function StrToBin($str){ //1.列出每个字符 $arr = pre ...