使用DRF ModelViewSet时如何从Django模型中获取主机地址生成二维码
DRF 环境下生成用户主页二维码的实现方案
核心逻辑说明
Django的Model层本身无请求上下文,无法直接获取访问主机地址,所以沿用你之前原生Django的思路,从视图层拿到请求信息后传入Model的save方法即可。
步骤1:调整Model层代码
保留自定义save方法,补充二维码存储逻辑(假设你已在UserInfo模型中定义了qr_code为ImageField类型,用于存储生成的二维码图片):
import uuid from django.utils.text import slugify import qrcode from io import BytesIO from django.core.files import File class UserInfo(models.Model): # 原有字段定义省略,包括slug、qr_code、name等必填字段 def save(self, full_url=None, *args, **kwargs): if not self.slug: self.slug = f'{slugify(self.name)}-{str(uuid.uuid4())[:8]}' # 仅当传入完整访问地址、且二维码不存在/需要更新时生成 if full_url and not self.qr_code: qrcode_img = qrcode.make(full_url) # 把二维码图片写入内存再存到ImageField buffer = BytesIO() qrcode_img.save(buffer, format='PNG') buffer.seek(0) self.qr_code.save(f'qr_{self.slug}.png', File(buffer), save=False) super(UserInfo, self).save(*args, **kwargs)
步骤2:重写DRF ViewSet的保存方法
在你的UserInfoViewSet中重写perform_create方法,利用当前请求对象自动生成用户主页的完整访问地址,传入save方法:
from django.urls import reverse class UserInfoViewSet(viewsets.ModelViewSet): serializer_class = serializers.UserBaseSerializer queryset = models.UserInfo.objects.all() def perform_create(self, serializer): # 先生成用户详情页的相对路径,注意替换成你实际配置的用户详情路由名 relative_path = reverse('user-detail', args=[serializer.validated_data['slug']]) # 自动生成完整的访问URL,自动适配当前请求的域名、协议、端口 full_user_url = self.request.build_absolute_uri(relative_path) # 保存实例时传入完整地址 serializer.save(full_url=full_user_url) # 如果更新用户信息时需要重新生成二维码,可重写perform_update方法 def perform_update(self, serializer): instance = serializer.save() # 检测slug是否变化,变化则重新生成二维码 if 'slug' in serializer.validated_data: relative_path = reverse('user-detail', args=[instance.slug]) full_user_url = self.request.build_absolute_uri(relative_path) instance.save(full_url=full_user_url)
生产环境适配
如果你的服务部署时前端有Nginx等反向代理,需要在settings.py中添加以下配置,确保能正确拿到用户实际访问的域名和协议:
USE_X_FORWARDED_HOST = True SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
内容的提问来源于stack exchange,提问作者Fahad Md Kamal
相关产品推荐
相关产品推荐

