Django中re_path路由下页面图片仅显示链接不加载的问题
Django媒体图片加载失败问题(re_path路由导致)
我开发了dashboard.html页面,用于展示近30天新注册用户的姓名、注册日期和头像。目前姓名和注册日期显示正常,但头像仅能看到链接(如<img src="/media/user_images/dream_TradingCard_1.jpg">),无法加载图片。经测试,使用path定义URL路由时图片显示正常,改用re_path后出现该问题。
相关代码与配置
1. 用户模型(podcast_user/models.py)
class PodcastUser(AbstractUser): user_id = models.AutoField(primary_key=True) first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) username = models.CharField(max_length=30,unique=True) phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$',message="Phone number must be in the format: '+999999999'. Up to 15 digits allowed.") phone_number = models.CharField(validators=[phone_regex], max_length=17, blank=True, null=True, unique=True, default='+') date_of_birth = models.DateField(blank=True, null=True) date_of_join = models.DateField(blank=True, null=True,default=date.today) address = models.CharField(max_length=100,blank=True, null=True) country = models.ForeignKey(Country, on_delete=models.CASCADE,blank=True, null=True) image = models.ImageField(upload_to='user_images/', blank=True, null=True) city_name = models.CharField(max_length=30, blank=True, null=True) postal_code = models.CharField(max_length=10,blank=True, null=True) is_superuser = models.BooleanField(default=False) is_active = models.BooleanField(default=True) is_staff = models.BooleanField(default=False) email = models.EmailField(max_length=30, validators=[RegexValidator(regex="^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$", message='please enter the correct format')],unique=True) USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['first_name', 'last_name','username'] def create_superuser(self, email, password, **extra_fields): if self.filter(is_superuser=True).exists(): raise ValueError('Superuser already exists') extra_fields.setdefault('is_staff', True) extra_fields.setdefault('is_superuser', True) return self._create_user(email=email, password=password, **extra_fields) def __str__(self): return f"{self.username} ({self.user_id})"
2. 视图函数(podcast_user/views.py)
def PodcastDashboard(request): thirty_days_ago = datetime.now() - timedelta(days=30) new_users = PodcastUser.objects.filter(date_of_join__gte=thirty_days_ago) return render(request, 'pages/podcast_dashboard.html', {'new_users': new_users})
3. 应用路由(podcast_user/urls.py)
from django.urls import re_path,path from .views import login_and_register,PodcastDashboard,logout_view,confirm_user_request urlpatterns = [ re_path(r'^login_and_register/', login_and_register, name='login_and_register'), re_path(r'^podcast_dashboard/', PodcastDashboard, name='podcast_dashboard'), re_path(r'^logout/', logout_view, name='logout'), path('confirm_user_request/<int:user_id>/', confirm_user_request, name='confirm_user_request'), ]
4. 项目根路由(podcast/urls.py)
from django.contrib import admin from django.urls import include, re_path,path from django.views.generic import TemplateView from django.conf.urls.static import static from podcast.settings.base import MEDIA_URL, MEDIA_ROOT urlpatterns = [ re_path(r'^admin', admin.site.urls), re_path(r"^user/", include('podcast_user.urls')), re_path(r"^", TemplateView.as_view(template_name="pages/home.html"), name="home"), ]+ static(MEDIA_URL, document_root=MEDIA_ROOT)
5. 前端模板(podcast_dashboard.html)
{% load static %} {% if user.is_authenticated %} {% block content %} <div class="card-body p-0"> <h1>新注册用户</h1> <ul class="users-list clearfix"> {% for user in new_users %} <li> {% if user.image %} <img src="{{ user.image.url }}" > {% endif %} <a class="users-list-name" href="#">{{ user.first_name }} {{ user.last_name }}</a> <span class="users-list-date"> {{ user.date_of_join|date:"M d, Y" }}</span> </li> {% empty %} <li>暂无新注册用户。</li> {% endfor %} </ul> </div> {% endblock %} {% endif %}
项目结构
podcast | ├── podcast_user | └── templates_static_media ├── media | └── user_images | ├── default.jpg | ├── dream_TradingCard.jpg | ├── dream_TradingCard_1.jpg | ├── Podcast-ddddd.png | ├── static └── templates └── pages ├── podcast_dashboard.html └── test.htm
配置文件(settings.py)
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) APPS_DIR = os.path.join(ROOT_DIR, "templates_static_media/") BASE_DIR = Path(__file__).resolve().parent.parent STATIC_URL = "static/" STATICFILES_FINDERS = ( "django.contrib.staticfiles.finders.FileSystemFinder", "django.contrib.staticfiles.finders.AppDirectoriesFinder", ) STATICFILES_DIRS = (os.path.join(APPS_DIR, "static/"),) DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage' MEDIA_ROOT = os.path.join(APPS_DIR, "/media/") MEDIA_URL = "/media/"
问题原因与解决方案
核心问题
- 路由匹配优先级错误:根路由
re_path(r"^", ...)没有添加结束符$,导致所有包含/media/的请求会被该根路由先行匹配,媒体文件的静态路由无法生效。 - MEDIA_ROOT路径错误:
os.path.join(APPS_DIR, "/media/")中第二个参数以/开头,导致MEDIA_ROOT直接变成/media/,而非项目下的templates_static_media/media/,Django无法找到存储的图片文件。
解决步骤
- 修正根路由匹配规则
修改podcast/urls.py中的根路由,添加$以精确匹配根路径:
re_path(r"^$", TemplateView.as_view(template_name="pages/home.html"), name="home"),
同时建议给admin路由补全后缀,避免不必要的匹配:
re_path(r'^admin/', admin.site.urls),
- 修正MEDIA_ROOT路径
修改settings.py中的MEDIA_ROOT配置:
MEDIA_ROOT = os.path.join(APPS_DIR, "media/")
- 验证DEBUG模式
确保开发环境下DEBUG=True,因为static()函数仅在DEBUG模式下提供媒体文件的服务。
完成以上修改后,重启Django服务,头像即可正常加载。
内容的提问来源于stack exchange,提问作者Davor_Python
相关产品推荐
相关产品推荐

