【问题标题】:Django: post form and post list on the same pageDjango:在同一页面上发布表单和发布列表
【发布时间】:2023-03-03 19:11:01
【问题描述】:

我创建了一个有多个用户的网站,发布带有图片的帖子以及添加/删除朋友的功能。 所以很容易为帖子列表制作两个不同的页面并创建一个新页面。当然,当您可以在同一个地方阅读帖子并制作新帖子时,它看起来会更好。

据我了解(学习 django 不到一个月),我无法将 2 个视图连接到同一个 url,所以我看到的最合乎逻辑的方式是将 2 个视图合二为一,我也尝试过使用模板继承通过包含模板来渲染帖子表单,但实际上它不起作用。

您可以在下面看到我的视图、帖子模型和模板。感谢您的关注。

views.py:

from braces.views import SelectRelatedMixin
from . import models
from django.views import generic
from django.contrib.auth.mixins import LoginRequiredMixin

class PostList(SelectRelatedMixin, generic.ListView):
    model = models.Post
    select_related = ('user',)

class CreatePost(LoginRequiredMixin, SelectRelatedMixin, generic.CreateView):
    fields = ('post_message', 'post_image')
    model = models.Post
    select_related = ('user',)

    def form_valid(self, form):
        self.object = form.save(commit = False)
        self.object.user = self.request.user
        self.object.save()
        return super().form_valid(form)

models.py:

import misaka

class Post(models.Model):
    user = models.ForeignKey(User, on_delete = models.CASCADE, related_name = 'posts')
    posted_at = models.DateTimeField(auto_now = True)
    post_message = models.TextField()
    message_html = models.TextField(editable = False)
    post_image = models.ImageField(upload_to = 'postpics', blank = True)

    def __str__(self):
        return self.post_message

    def save(self, *args, **kwargs):
        self.message_html = misaka.html(self.post_message)
        super().save(*args, **kwargs)

    def get_absolute_url(self):
        return reverse('posts:all')

    class Meta:

        ordering = ['-posted_at']
        unique_together = ['user', 'post_message']

urls.py:

app_name = 'posts'

urlpatterns = [
    path('', views.PostList.as_view(), name = 'all'),
    path('new/', views.CreatePost.as_view(), name = 'create'),
]

post_form.html(模板,允许发布新帖子,将在 post_list.html 中看到):

{% extends 'posts/post_base.html'%}
{% block post_content %}
<div class="post-form">
  <form action="{% url 'posts:create' %}" method="POST" enctype="multipart/form-data">
    {% csrf_token %}
    <p>{{ form.post_message }}</p>
    <p>{{ form.post_image }}</p>
    <input id='post-submit' type="submit" value="Post">
  </form>
</div>
{% endblock %}

post_list.html:

{% extends 'posts/post_base.html'%}
{% block post_content %}
<div class="post-container">
  {% for post in post_list %}
  <div class="current-post-container">
    {% include 'posts/_post.html'%}
  </div>
  {% endfor %}
</div>
{% endblock %}

_post.html(页面,由 Misaka 渲染):

<div class="post-info">
  <h5 id='post-owner' >{{post.user.first_name}} {{post.user.last_name}}</h5>
  <h6>{{ post.posted_at }}</h6>
  <p>{{ post.message_html|safe }}</p>
  <div>
    <img class='post-image'  src="/media/{{ post.post_image }}" alt="">
    <div>
      {% if user.is_authenticated and post.user == user and not hide_delete %}
      <a href="{% url 'posts:delete' pk=post.pk %}" title = 'delete'>Delete</a>
      {% endif %}
    </div>
  </div>
</div>

post_base.html:

{% extends 'base.html' %}
{% block content%}
        {% block prepost %}{% endblock %}
        {% block post_content %}{% endblock %}
        {% block post_post %}{% endblock %}
{% endblock %}

编辑: 任务解决了。我在两个视图中都添加了两个 template_name 字符串,所以现在它们看起来像:

在views.py中创建帖子:

class CreatePost(LoginRequiredMixin, SelectRelatedMixin, generic.CreateView):
    fields = ('post_message', 'post_image')
    model = models.Post
    select_related = ('user',)
    template_name = 'posts/post_list.html'
    template_name = 'posts/post_form.html'


    def form_valid(self, form):
        self.object = form.save(commit = False)
        self.object.user = self.request.user
        self.object.save()
        return super().form_valid(form)

views.py 中的 PostList:

class PostList(SelectRelatedMixin, generic.ListView):
    model = models.Post
    select_related = ('user',)
    template_name = 'posts/post_list.html'
    template_name = 'posts/post_form.html'

【问题讨论】:

标签: python html django


【解决方案1】:

您可以将 post_create_form 与 post_list_view 放在同一页面上,无需为创建帖子创建单独的视图,但您需要创建用于编辑和删除的视图。 您可以为所有这些视图提供具有不同 URL 的相同 HTML 页面。 在 Class_Based_Views 中使用 template_name = 'example/example.html'。 我希望我能理解您的问题,如果不进一步说明为什么您不能将两个视图合二为一。

【讨论】:

  • 我已经尝试了很多方法来将这些 PostList 和 CreatePost 视图合并为一个,但无论如何我都不起作用。无论如何,我只看到创建表单或帖子列表。我想过创建一个新类,它将包含这两个类的所有代码并继承它们,但它也不起作用
【解决方案2】:
def posts(request):
posts = Post.objects.all()

form = PostForm(request.POST or None, request.FILES or None)
if request.method == "POST":
    if form.is_valid():
       ...

context={
    'posts'         : page_obj,
    'create_or_update_post_form' : form,

}
return  render(request, 'post/posts.html',context)

您在基于类的视图中难以做到这一点吗?

【讨论】:

  • 我已经用你之前的答案解决了这个问题,现在我会发布它。
【解决方案3】:

您可以轻松地使用基于 django 类的视图。

  • 将视图创建为
from django.views.generic import ListView
from django.views.generic.edit import CreateView

class ModelCreate(CreateView):
    model = ModelName
    fields = ['field1', 'field2']
    template_name = 'same_page.html'
    success_url = reverse_lazy('list_view')


class ModelList(CreateView, ListView):
    model = ModelName
    fields = ['field1', 'field2']
    paginate_by = 5
    template_name = 'same_page.html'

    def get_context_data(self, *args, **kwargs):
        context = super().get_context_data(*args, **kwargs)
        context['form'] = self.get_form()
        return context

    # If form post redirect to ModelCreate View
    def post(self, request, *args, **kwargs):
        return ModelCreate.as_view()(request)
  • app/urls.py
from django.urls import path
from app import views

path('list', views.ModelList.as_view(), name='list_view'),
path('add', views.ModelCreate.as_view(), name='add_view'),
  • 终于在templates/same_page.html中
<div class="row">
   <div class="col-sm-5">
      <form method="post" enctype="multipart/form-data">
         {% csrf_token %}
         {{form.as_p}}
         <button type="submit" value="submit" class="btn btn-primary btn-sm float-right">Submit</button>                              
       </form>
   </div>
   <div class="col-sm-5">
    {% if object_list %}
       {% for object in object_list %}
         <p>{{object.field1}}</p>
         <p>{{object.field2}}</p>
       {% endfor %}
    {% endif %}
   </div>
</div>

希望,这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-14
    • 2015-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多