Django CreateView使用双模型仅展示单模型输入字段并保存关联关系求助
模板遍历无输出问题解决
你无法直接遍历{% get_quotes %}的原因是Django的simple_tag返回值不能直接作为循环对象,需要先将标签返回值赋值给模板变量再遍历:
{% load create_tags %} <!-- 先将随机引用赋值给变量 --> {% get_quotes 2 as random_quotes %} <!-- 遍历变量即可正常输出 --> {% for quote in random_quotes %} <p>{{ quote.text }} <em>by {{ quote.author }}</em></p> {% endfor %}
另外你当前的Quote.get_random方法存在明显缺陷:当激活状态的引用数量小于你要取的数量时会报错,且通过索引取值的逻辑不稳定,建议优化为:
@classmethod def get_random(cls, n=2): n = int(n) # 直接用Django内置的随机排序,返回实例对象而非字典,模板调用更方便 return cls.objects.filter(active=True).order_by('?')[:n]
你可以删除原来的to_dict转换逻辑,直接返回Quote实例,模板可以直接访问实例的所有字段。
保存引用与用户评论关联关系
有两种实现方案,推荐优先用第二种更安全的方案:
方案1:隐藏字段传值(简单但易被篡改)
- 在模板的表单内,遍历引用时加入隐藏input存储引用ID:
<form method="post"> {% csrf_token %} {% for quote in random_quotes %} <p>{{ quote.text }} <em>by {{ quote.author }}</em></p> <input type="hidden" name="quote_ids" value="{{ quote.id }}"> {% endfor %} <!-- 你的表单其他字段 --> {{ form.as_p }} <button type="submit">提交</button> </form>
- 重写
UserPostCreateView的form_valid方法,保存多对多关联:
def form_valid(self, form): # 先保存基础实例(多对多字段操作需要实例先有主键) response = super().form_valid(form) # 获取提交的引用ID列表 quote_ids = self.request.POST.getlist('quote_ids') # 关联引用和用户帖子 self.object.quotes.add(*quote_ids) return response
方案2:Session存储(安全,避免用户篡改引用ID)
不需要模板标签,直接在视图层生成随机引用并存到Session,用户无法篡改关联的引用:
- 给
UserPostCreateView新增get_context_data方法,生成随机引用并存到上下文和Session:
def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # 生成随机引用 random_quotes = Quote.get_random(2) # 存引用ID到Session self.request.session['selected_quote_ids'] = [q.id for q in random_quotes] # 传到模板用于展示 context['random_quotes'] = random_quotes return context
- 重写
form_valid方法,从Session取引用ID完成关联:
def form_valid(self, form): response = super().form_valid(form) # 从Session取ID并移除该字段,避免重复使用 quote_ids = self.request.session.pop('selected_quote_ids', []) if quote_ids: self.object.quotes.add(*quote_ids) return response
- 模板直接遍历上下文变量即可,不需要隐藏字段:
<form method="post"> {% csrf_token %} {% for quote in random_quotes %} <p>{{ quote.text }} <em>by {{ quote.author }}</em></p> {% endfor %} {{ form.as_p }} <button type="submit">提交</button> </form>
内容的提问来源于stack exchange,提问作者Niq_Lin
相关产品推荐
相关产品推荐

