In our template, we check whether the user is authenticated. If the user is logged in, we display the log-out link and the user\\'s full name. Otherwise, we show the sign-in and sign-up links.
Now let\\'s run all the tests

(.venv)$ python3 manage.py testFound 22 test(s).Creating test database for alias \\'default\\'...System check identified no issues (0 silenced).......................----------------------------------------------------------------------Ran 22 tests in 9.942sOKDestroying test database for alias \\'default\\'...

3. Test if everything is working as it should in our browser

Now that we\\'ve configured the login and logout functionality, it\\'s time to test everything in our web browser. Let\\'s start the development server

(.venv)$ python3 manage.py runserver

Navigate to the registration page and enter valid credentials. After a successful registration, you should be redirected to the login page. Enter the user information in the login form, and once logged in, click the logout button. You should then be logged out and redirected to the homepage. Finally, verify that you\\'re no longer logged in and that the sign-up and sign-in links are displayed again.
Everything works perfectly, but I noticed that when a user is logged in and visits the registration page at http://127.0.0.1:8000/users/sign_up/, they still have access to the registration form. Ideally, once a user is logged in, they shouldn\\'t be able to access the sign-up page.
\\\"Guide
This behaviour can introduce several security vulnerabilities into our project. To address this, we need to update the SignUpView to redirect any logged-in user to the home page.
But first, let\\'s update our LoginTest to add a new test that covers the scenario. So in the users/tests/test_views.py add this code.

# users/tests/test_views.pyclass LoginTests(TestCase):  # -- other test cases  def test_visiting_registration_after_logged_in(self):    \\\"\\\"\\\"    Logged in user should be redirected when visiting the registration page    \\\"\\\"\\\"    response = self.client.post(reverse(\\'users:login\\'), self.valid_credentials, follow=True)    self.assertTrue(response.context[\\'user\\'].is_authenticated)    sign_up_resp = self.client.get(reverse(\\'users:signup\\'))    self.assertRedirects(sign_up_resp, reverse(\\'home\\'))

Now, we can update our SignUpView

# users/views.pyfrom django.conf import settings # new line...class SignUpView(CreateView):  form_class = CustomUserCreationForm  redirect_authenticated_user = True  model = User  success_url = reverse_lazy(\\'users:login\\')  template_name = \\'registration/signup.html\\'  def dispatch(self, request, *args, **kwargs):    # Check if a user is already authenticated    if request.user.is_authenticated:      # Redirect the user to the login redirect url      return redirect(f\\'{settings.LOGIN_REDIRECT_URL}\\')    return super().dispatch(request, *args, **kwargs)

In the code above, we override the dispatch() method of our SignUpView to redirect any user who is already logged in and tries to access the registration page. This redirect will use the LOGIN_REDIRECT_URL set in our settings.py file, which in this case, points to the home page.
Okay! Once again, let\\'s run all our tests to confirm that our updates are working as expected

(.venv)$ python3 manage.py testFound 23 test(s).Creating test database for alias \\'default\\'...System check identified no issues (0 silenced)........................----------------------------------------------------------------------Ran 23 tests in 11.215sOKDestroying test database for alias \\'default\\'...

I know there\\'s much more to accomplish, but let\\'s take a moment to appreciate what we\\'ve accomplished so far. Together, we\\'ve set up our project environment, connected a PostgreSQL database, and implemented a secure user registration and login system for our Django blog application. In the next part, we\\'ll dive into creating a user profile page, enabling users to edit their information, and password reset! Stay tuned for more exciting developments as we continue our Django blog app journey!

Your feedback is always valued. Please share your thoughts, questions, or suggestions in the comments below. Don\\'t forget to like, leave a comment, and subscribe to stay updated on the latest developments!

","image":"http://www.luping.net/uploads/20241023/17296751096718bf6570e45.png","datePublished":"2024-11-06T19:55:38+08:00","dateModified":"2024-11-06T19:55:38+08:00","author":{"@type":"Person","name":"luping.net","url":"https://www.luping.net/articlelist/0_1.html"}}
”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 使用 TDD 方法论和 PostgreSQL 使用 Django 构建完整博客应用程序的指南(部分安全用户身份验证)

使用 TDD 方法论和 PostgreSQL 使用 Django 构建完整博客应用程序的指南(部分安全用户身份验证)

发布于2024-11-06
浏览:412

Welcome back, everyone! In the previous part, we established a secure user registration process for our Django blog application. However, after successful registration, we were redirected to the homepage. This behaviour will be modified once we implement user authentication. User authentication ensures that only authorized users can access certain functionalities and protects sensitive information.
Guide to Building a Complete Blog App with Django using TDD Methodology and PostgreSQL (Part  Secure User Authentication
In this series, we are building a complete blog application, guided by the following Entity-Relationship Diagram (ERD). For this time, our focus will be on setting up a secure user authentication process. If you find this content helpful, please like, comment, and subscribe to stay updated when the next part is released.
Guide to Building a Complete Blog App with Django using TDD Methodology and PostgreSQL (Part  Secure User Authentication
This is a preview of how our login page will look after we’ve implemented the login functionality. If you haven’t read the previous parts of the series, I recommend doing so, as this tutorial is a continuation of the previous steps.

Okay, let’s get started !!

Django comes with a built-in app called contrib.auth, which simplifies handling user authentication for us. You can check the blog_env/settings.py file, under the INSTALLED_APPS, you’ll see that auth is already listed.

# django_project/settings.py
INSTALLED_APPS = [
    # "django.contrib.admin",
    "django.contrib.auth",  # 



The auth app provides us with multiple authentication views for handling login, logout, password change, password reset, etc. This means that the essential authentication functionality, such as user login, registration, and permissions, is ready to use without needing to build everything from scratch.

In this tutorial, we’ll focus solely on the login and logout views, and cover the rest of the views in later parts of the series.

1. Create a login form

Following our TDD approach, let’s begin by creating tests for the login form. Since we haven’t created a login form yet, navigate to the users/forms.py file and create a new class inheriting from AuthenticationForm.

# users/forms.py
from django.contrib.auth import AuthenticationForm

class LoginForm(AuthenticationForm):


Once the form is defined, we can add test cases in users/tests/test_forms.py to verify its functionality.

# users/tests/test_forms.py

#   --- other code

class LoginFormTest(TestCase):
  def setUp(self):
    self.user = User.objects.create_user(
      full_name= 'Tester User',
      email= '[email protected]',
      bio= 'new bio for tester',
      password= 'password12345'
    )

  def test_valid_credentials(self):
    """
    With valid credentials, the form should be valid
    """
    credentials = {
      'email': '[email protected]',
      'password': 'password12345',
      'remember_me': False
    }

    form = LoginForm(data = credentials)
    self.assertTrue(form.is_valid())

  def test_wrong_credentials(self):
    """
    With wrong credentials, the form should raise Invalid email or password error
    """
    credentials = {
      'email': '[email protected]',
      'password': 'wrongpassword',
      'remember_me': False
    }
    form = LoginForm(data = credentials)
    self.assertIn('Invalid email or password', str(form.errors['__all__']))

  def test_credentials_with_empty_email(self):
    """
    Should raise an error when the email field is empty
    """
    credentials = {
      'email': '',
      'password': 'password12345',
      'remember_me': False
    }
    form = LoginForm(data = credentials)
    self.assertFalse(form.is_valid())
    self.assertIn('This field is required', str(form.errors['email']))

  def test_credentials_with_empty_password(self):
    """
    Should raise error when the password field is empty
    """
    credentials = {
      'email': '[email protected]',
      'password': '',
      'remember_me': False
    }
    form = LoginForm(data = credentials)
    self.assertFalse(form.is_valid())
    self.assertIn('This field is required', str(form.errors['password']))

These tests cover scenarios like successful login with valid credentials, failed login with invalid credentials, and handling error messages appropriately.

The AuthenticationForm class provides some basic validation by default. However, with our LoginForm, we can tailor its behaviour and add any necessary validation rules to meet our specific requirements.

# users/forms.py

# -- other code
from django.contrib.auth.forms import UserCreationForm, UserChangeForm, AuthenticationForm # new line
from django.contrib.auth import get_user_model, authenticate # new line


# --- other code

class LoginForm(AuthenticationForm):
  email = forms.EmailField(
    required=True,
    widget=forms.EmailInput(attrs={'placeholder': 'Email','class': 'form-control',})
  )
  password = forms.CharField(
    required=True,
    widget=forms.PasswordInput(attrs={
                                'placeholder': 'Password',
                                'class': 'form-control',
                                'data-toggle': 'password',
                                'id': 'password',
                                'name': 'password',
                                })
  )
  remember_me = forms.BooleanField(required=False)

  def __init__(self, *args, **kwargs):
    super(LoginForm, self).__init__(*args, **kwargs)
    # Remove username field

    if 'username' in self.fields:
      del self.fields['username']

  def clean(self):
    email = self.cleaned_data.get('email')
    password = self.cleaned_data.get('password')

    # Authenticate using email and password
    if email and password:
      self.user_cache = authenticate(self.request, email=email, password=password)
      if self.user_cache is None:
        raise forms.ValidationError("Invalid email or password")
      else:
        self.confirm_login_allowed(self.user_cache)
    return self.cleaned_data

  class Meta:
    model = User
    fields = ('email', 'password', 'remember_me')

We’ve created a custom login form that includes the following fields: email, password, and remember_me. The remember_me checkbox allows users to maintain their login session across browser sessions.

Since our form extends the AuthenticationForm, we've overridden some default behaviour:

  • ** __init__ method**: We've removed the default username field from the form to align with our email-based authentication.
  • clean() method: This method validates the email and password fields. If the credentials are valid, we authenticate the user using Django's built-in authentication mechanism.
  • confirm_login_allowed() method: This built-in method provides an opportunity for additional verification before login. You can override this method to implement custom checks if needed. Now our tests should pass:
(.venv)$ python3 manage.py test users.tests.test_forms
Found 9 test(s).
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.........
----------------------------------------------------------------------
Ran 9 tests in 3.334s
OK
Destroying test database for alias 'default'...

2. Create our login view

2.1 Create tests for the login view

Since we do not have the view for the login yet, let's navigate to the users/views.py file and create a new class inheriting from the auth app’s LoginView

# -- other code 
from .forms import CustomUserCreationForm, LoginForm
from django.contrib.auth import get_user_model, views
# -- other code

class CustomLoginView(views.LoginForm):


At the bottom of the users/tests/test_views.py file add these test cases

# users/tests/test_views.py

# -- other code

class LoginTests(TestCase):
  def setUp(self):
    User.objects.create_user(
      full_name= 'Tester User',
      email= '[email protected]',
      bio= 'new bio for tester',
      password= 'password12345'
    )
    self.valid_credentials = {
      'email': '[email protected]',
      'password': 'password12345',
      'remember_me': False
    }

  def test_login_url(self):
    """User can navigate to the login page"""
    response = self.client.get(reverse('users:login'))
    self.assertEqual(response.status_code, 200)

  def test_login_template(self):
    """Login page render the correct template"""
    response = self.client.get(reverse('users:login'))
    self.assertTemplateUsed(response, template_name='registration/login.html')
    self.assertContains(response, 'Sign Up')

  def test_login_with_valid_credentials(self):
    """User should be log in when enter valid credentials"""
    response = self.client.post(reverse('users:login'), self.valid_credentials, follow=True)
    self.assertEqual(response.status_code, 200)
    self.assertRedirects(response, reverse('home'))
    self.assertTrue(response.context['user'].is_authenticated)
    self.assertContains(response, '')

  def test_login_with_wrong_credentials(self):
    """Get error message when enter wrong credentials"""
    credentials = {
      'email': '[email protected]',
      'password': 'wrongpassword',
      'remember_me': False
    }

    response = self.client.post(reverse('users:login'), credentials, follow=True)
    self.assertEqual(response.status_code, 200)
    self.assertContains(response, 'Invalid email or password')
    self.assertFalse(response.context['user'].is_authenticated)

We need to ensure that these tests are failing at this stage.

2.2 Create a login view

In the users/views.py file at the bottom of the file add the code below:

# -- other code 
from .forms import CustomUserCreationForm, LoginForm
from django.contrib.auth import get_user_model, views
# -- other code

class CustomLoginView(views.LoginView):
  form_class = LoginForm
  redirect_authenticated_user = True
  authentication_form = LoginForm
  template_name = 'registration/login.html'

  def form_valid(self, form):
    remember_me = form.cleaned_data.get('remember_me')

    if not remember_me:
      # set session expiry to 0 seconds. So it will automatically close the session after the browser is closed.
      self.request.session.set_expiry(0)
      # Set session as modified to force data updates/cookie to be saved.
      self.request.session.modified = True
    return super(CustomLoginView, self).form_valid(form)

In the code above, we accomplish the following:

  • Set the form_class Attribute: We specify our custom LoginForm as the form_class attribute since we are no longer using the default AuthenticationForm.
  • Override the form_valid Method: We override the form_valid method, which is called when valid form data has been posted. This allows us to implement custom behaviour after the user has successfully logged in.
  • Handle Session Expiration: If the user does not check the remember_me box, the session will expire automatically when the browser is closed. However, if the remember_me box is checked, the session will last for the duration defined in settings.py. The default session length is two weeks, but we can modify this using the SESSION_COOKIE_AGE variable in settings.py. For example, to set the cookie age to 7 days, we can add the following line to our settings:
# blog_app/settings.py
SESSION_COOKIE_AGE = 60 * 60 * 24 * 7

To connect your custom login functionality and allow users to access the login page, we’ll define URL patterns in the users/urls.py file. This file will map specific URLs (/log_in/ in this case) to the corresponding views (CustomLoginView). Additionally, we'll include a path for the logout functionality using Django's built-in LogoutView.

# users/urls.py

# -- other code
from django.contrib.auth import views as auth_views
from . import views

app_name = 'users'
urlpatterns = [
  path('log_in/', views.CustomLoginView.as_view(), name='login' ), # new line
  path('sign_up/', views.SignUpView.as_view(), name='signup'),
  path('log_out/', auth_views.LogoutView.as_view(), name='logout'),# new line
]

Everything seems to be in order, but we should specify where to redirect users upon successful login and logout. To do this, we will use the LOGIN_REDIRECT_URL and LOGOUT_REDIRECT_URL settings. At the bottom of your blog_app/settings.py file, add the following lines to redirect users to the homepage:

# django_project/settings.py
LOGIN_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL = '/'

Now that we have the login URL let’s update our SignUpView in the users/views.py file to redirect to the login page when sign-up is successful.

# users/views.py
class SignUpView(CreateView):
  form_class = CustomUserCreationForm
  model = User
  success_url = reverse_lazy('users:login') # Updated line
  template_name = 'registration/signup.html'

We will also update our SignUpTexts, specifically the test_signup_correct_data(self), to reflect the new behaviour and ensure that our changes are properly tested.

# users/tests/test_views.py
  def test_signup_correct_data(self):
    """User should be saved when a correct data is provided"""
    response = self.client.post(reverse('users:signup'), data={
      'full_name': self.full_name,
      'email': self.email,
      'bio': self.bio,
      'password1': self.password,
      'password2': self.password
    })

    self.assertRedirects(response, reverse('users:login')) # Updated line
    users = User.objects.all()
    self.assertEqual(users.count(), 1)
    self.assertNotEqual(users[0].password, self.password)

2.3 Create a template for Login

Then create a users/templates/registration/login.html file with your text editor and include the following code:

{% extends 'layout.html' %}
{% block page %}
  Login
{% endblock %}
{% block content %}

Sign In

{% if form.errors %} {% for field, message in form.errors.items %} {% endfor %} {% endif %}
{{form.email}}
{{form.password}}
{{form.remember_me}}
{% endblock %}

We will add the Forgot Password functionality later in this series but now it’s just a dead link.
Guide to Building a Complete Blog App with Django using TDD Methodology and PostgreSQL (Part  Secure User Authentication
Now, let us update our layout.html template to include the login, sign-up and logout links.



  {% block page %}{% endblock %} | Blog App
  {% block content %}
  {% endblock %}
  

In our template, we check whether the user is authenticated. If the user is logged in, we display the log-out link and the user's full name. Otherwise, we show the sign-in and sign-up links.
Now let's run all the tests

(.venv)$ python3 manage.py test
Found 22 test(s).
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
......................
----------------------------------------------------------------------
Ran 22 tests in 9.942s
OK
Destroying test database for alias 'default'...

3. Test if everything is working as it should in our browser

Now that we've configured the login and logout functionality, it's time to test everything in our web browser. Let's start the development server

(.venv)$ python3 manage.py runserver

Navigate to the registration page and enter valid credentials. After a successful registration, you should be redirected to the login page. Enter the user information in the login form, and once logged in, click the logout button. You should then be logged out and redirected to the homepage. Finally, verify that you're no longer logged in and that the sign-up and sign-in links are displayed again.
Everything works perfectly, but I noticed that when a user is logged in and visits the registration page at http://127.0.0.1:8000/users/sign_up/, they still have access to the registration form. Ideally, once a user is logged in, they shouldn't be able to access the sign-up page.
Guide to Building a Complete Blog App with Django using TDD Methodology and PostgreSQL (Part  Secure User Authentication
This behaviour can introduce several security vulnerabilities into our project. To address this, we need to update the SignUpView to redirect any logged-in user to the home page.
But first, let's update our LoginTest to add a new test that covers the scenario. So in the users/tests/test_views.py add this code.

# users/tests/test_views.py
class LoginTests(TestCase):
  # -- other test cases

  def test_visiting_registration_after_logged_in(self):
    """
    Logged in user should be redirected when visiting the registration page
    """
    response = self.client.post(reverse('users:login'), self.valid_credentials, follow=True)
    self.assertTrue(response.context['user'].is_authenticated)

    sign_up_resp = self.client.get(reverse('users:signup'))
    self.assertRedirects(sign_up_resp, reverse('home'))

Now, we can update our SignUpView

# users/views.py
from django.conf import settings # new line
...

class SignUpView(CreateView):
  form_class = CustomUserCreationForm
  redirect_authenticated_user = True
  model = User
  success_url = reverse_lazy('users:login')
  template_name = 'registration/signup.html'

  def dispatch(self, request, *args, **kwargs):
    # Check if a user is already authenticated
    if request.user.is_authenticated:
      # Redirect the user to the login redirect url
      return redirect(f'{settings.LOGIN_REDIRECT_URL}')
    return super().dispatch(request, *args, **kwargs)

In the code above, we override the dispatch() method of our SignUpView to redirect any user who is already logged in and tries to access the registration page. This redirect will use the LOGIN_REDIRECT_URL set in our settings.py file, which in this case, points to the home page.
Okay! Once again, let's run all our tests to confirm that our updates are working as expected

(.venv)$ python3 manage.py test
Found 23 test(s).
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.......................
----------------------------------------------------------------------
Ran 23 tests in 11.215s

OK
Destroying test database for alias 'default'...

I know there's much more to accomplish, but let's take a moment to appreciate what we've accomplished so far. Together, we've set up our project environment, connected a PostgreSQL database, and implemented a secure user registration and login system for our Django blog application. In the next part, we'll dive into creating a user profile page, enabling users to edit their information, and password reset! Stay tuned for more exciting developments as we continue our Django blog app journey!

Your feedback is always valued. Please share your thoughts, questions, or suggestions in the comments below. Don't forget to like, leave a comment, and subscribe to stay updated on the latest developments!

版本声明 本文转载于:https://dev.to/lionrouge1/guide-to-building-a-complete-blog-app-with-django-using-tdd-methodology-and-postgresql-part-3-secure-user-authentication-nkc?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 在 React 中构建无限滚动组件
    在 React 中构建无限滚动组件
    介绍 我们在应用程序和网页中看到无限滚动,尤其是希望我们滚动的社交媒体。虽然无意识地滚动不好,但构建自己的无限滚动是很棒的。作为开发人员,我们应该尝试重新创建我们在网上冲浪时看到的组件。它可以挑战您在实现某些组件时了解更多信息并跳出框框进行思考。 此外,如果您希望在应用程序中实现无...
    编程 发布于2024-11-06
  • 在 React 中构建响应式会议图块的动态网格系统
    在 React 中构建响应式会议图块的动态网格系统
    In the era of remote work and virtual meetings, creating a responsive and dynamic grid system for displaying participant video tiles is crucial. Inspi...
    编程 发布于2024-11-06
  • 使用 Spring Boot 和 Spring Cloud 开发微服务
    使用 Spring Boot 和 Spring Cloud 开发微服务
    微服务架构已成为构建可扩展和模块化系统的流行解决方案。通过微服务,您可以将单一应用程序分解为更小的、独立的和专业的服务,这使得系统的维护和发展变得更加容易。在这篇文章中,我们将探讨如何使用 Spring Boot 和 Spring Cloud 创建健壮且高效的微服务。 微服务简介 微服务背后的主要思...
    编程 发布于2024-11-06
  • 克服 PHP DOM XML 解析中的挑战:问题和解决方案
    克服 PHP DOM XML 解析中的挑战:问题和解决方案
    简化 PHP DOM XML 解析:揭开要点当您浏览 PHP DOM 函数的复杂性时,可能会出现某些障碍。为了解决这些挑战,让我们开始了解 DOM 的复杂性,并找出常见问题的解决方案。问题 1:使用 xml:id 驯服 ID当使用 ID 来防止树中出现重复页面时,PHP 的 DOM 遇到了一个难题:...
    编程 发布于2024-11-06
  • 密码重置功能:使用 OTP 重置密码
    密码重置功能:使用 OTP 重置密码
    后端 2. 重置密码 转向下一个 API。 PUT 上 /api/reset-password, req -> otp, email, 新密码, res -> nocontent // controllers/passwordReset.go func ResetP...
    编程 发布于2024-11-06
  • 如何从全局站点包继承 Virtualenv 中的特定包?
    如何从全局站点包继承 Virtualenv 中的特定包?
    从全局站点包继承 Virtualenv 中的特定包为了增强虚拟环境 (virtualenv) 的功能,您可能希望从全局站点继承特定包站点包目录。这种方法允许您有选择地将重要的库合并到您的 virtualenv 中,而无需直接安装它们。继承方法要实现这种继承,请使用以下命令创建一个新的 virtual...
    编程 发布于2024-11-06
  • 如何解决 EF6 中的“找不到 'MySql.Data.MySqlClient\'\”错误?
    如何解决 EF6 中的“找不到 'MySql.Data.MySqlClient\'\”错误?
    MySQL 实体框架的提供程序注册使用 MySQL 和实体框架时,您可能会遇到错误“找不到 Entity Framework 提供程序” 'MySql.Data.MySqlClient' ADO.NET 提供程序。”尽管安装了最新的 MySQL 连接器,您可能仍然会遇到此问题。出现此...
    编程 发布于2024-11-06
  • 如何利用PHP防止邮件传输中的恶意输入?
    如何利用PHP防止邮件传输中的恶意输入?
    保护电子邮件传输的用户输入在 PHP 中,必须在发送电子邮件之前清理用户输入,以防止恶意或有害内容泄露你的系统。考虑下面的简单 PHP 邮件脚本的代码片段:<?php $to = "[email protected]"; $name = $_POST['name']; $m...
    编程 发布于2024-11-06
  • 应用页面开发
    应用页面开发
    Если посмотреть на исходный проект, то можно увидеть, что нам необходимо создать одну главную страницу. Результаты поиска авиабилетов, отелей и туров ...
    编程 发布于2024-11-06
  • Java 应用程序中的“No X11 DISPLAY Variable”错误:如何为 GUI 功能设置 DISPLAY 变量?
    Java 应用程序中的“No X11 DISPLAY Variable”错误:如何为 GUI 功能设置 DISPLAY 变量?
    Java 应用程序中的“No X11 DISPLAY Variable”错误Java 应用程序依赖于 X Window 系统 (X11) 来实现图形用户界面 ( GUI)功能。 “未设置 X11 DISPLAY 变量”错误表示应用程序无法访问 X11 显示环境。要解决此问题,请设置 X11 DISP...
    编程 发布于2024-11-06
  • 破解 HashMap 的基础知识:Java 开发人员的关键概念
    破解 HashMap 的基础知识:Java 开发人员的关键概念
    介绍 了解 HashMap 类对于开发人员来说至关重要,无论是在实际应用程序还是面试中。在这篇文章中,我们将探讨如何在 HashMap 中插入、更新和管理键值对。这些知识也将为我们的下一篇文章奠定基础,我们将深入研究 HashSet 并了解这两个集合之间的关系。 什...
    编程 发布于2024-11-06
  • 如何在 .htaccess 中启用 PHP 错误显示和日志记录?
    如何在 .htaccess 中启用 PHP 错误显示和日志记录?
    通过 .htaccess 解决 PHP 错误显示问题测试网站并遇到问题时,错误显示至关重要。但是,此显示有时可能会被禁用。对于仅有权访问 .htaccess 文件并希望启用错误显示的用户,此问题提供了全面的解决方案。该问题解决了 .htaccess 文件是唯一可访问资源的情况。它建议添加三个 PHP...
    编程 发布于2024-11-06
  • 精选的最佳 React 管理仪表板模板
    精选的最佳 React 管理仪表板模板
    Hi there ?. I'm Syakir, a Front-end engineer. In this page, i curated premium react admin templates from various vendors with top features and design ...
    编程 发布于2024-11-06
  • Gosync.Pool 及其背后的机制
    Gosync.Pool 及其背后的机制
    这是帖子的摘录;完整的帖子可以在这里找到:https://victoriametrics.com/blog/go-sync-pool/ 这篇文章是关于 Go 中处理并发的系列文章的一部分: Gosync.Mutex:正常和饥饿模式 Gosync.WaitGroup 和对齐问题 Gosync.Poo...
    编程 发布于2024-11-06
  • 如何在 PHP 中包含 CSS:详细指南
    如何在 PHP 中包含 CSS:详细指南
    在 PHP 中包含 CSS 文件:综合指南在进行 Web 开发时,将 CSS 样式合并到 PHP 代码中对于管理至关重要您的页面的呈现。然而,众所周知,使用 HTML 代码包含 CSS 文件是标准方法。在本文中,我们将深入研究基于 PHP 的解决方案,帮助您了解如何将 CSS 文件直接导入 PHP ...
    编程 发布于2024-11-06

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3