【问题标题】:Need a PK or ID for success_message in UpdateView (a class based view)UpdateView(基于类的视图)中的 success_message 需要 PK 或 ID
【发布时间】:2019-07-17 18:14:18
【问题描述】:

我想在 UpdateView 中发送一条成功消息,其中包含允许用户改变对更新的想法的链接。这意味着我需要主键。

我无法确定如何在 UpdateView 中检索主键。其他一切都正常,所以你会在我的代码中看到,我暂时将主键硬编码为 434。

我对所有编程都是一个极端的新手,所以我相信这里有一些愚蠢的东西。我试着一次减少一点我愚蠢的东西。因此,我主要想专注于如何检索 PK(或 ID)。谢谢。

网址:

# CLASS BASED VIEWS #
path('event/list', EventListView.as_view(), name='list'),
path('event/detail/<int:pk>', EventDetailView.as_view(), name='detail'),
path('event/create', EventCreateView.as_view(), name='create'),
path('event/update/<int:pk>', EventUpdateView.as_view(), name='update'),

观点:

class EventUpdateView(SuccessMessageMixin,UpdateView):

    template_name = 'update.html'
    form_class = EventForm
    success_url = '../list'
    queryset = Event.objects.all()

    def get_object(self, queryset=None):  # here we override the get_object method in UpdateView, don't need queryset
        #obj = Event.objects.get(id=self.kwargs['pk'])
        pk_=self.kwargs.get("pk")
        print("The pk is", pk_)
        return get_object_or_404(Event,pk=pk_)

    def form_valid(self, form):
        return super().form_valid(form)

    message_part_1 = "Record has been updated <a href='unupdate?recordtobeunupdated="
    message_part_2 =  '434'
    message_part_3 = "'>Undo</a>"
    undo_message = message_part_1  + message_part_2 + message_part_3
    success_message = (mark_safe(undo_message))

模特:

from django.db import models
from django.urls import reverse

class Event(models.Model):  # This is our database table
    company = models.CharField(default='UL',   max_length=20)
    engine = models.CharField(blank=True, max_length=15)
    date = models.DateTimeField(default=datetime.now, blank=True, null=True)  # default the date to today
    category = models.CharField(max_length=20, choices=CATEGORY_CHOICES, default='Weights')
    description = models.TextField(blank=True, null=True)
    reason = models.TextField(blank=True, null=True)
    assess_date = models.DateTimeField(null=True, blank=True)
    outcome = models.CharField(blank=True, max_length=200)
    # the default is True, it can't be blank
    visible = models.BooleanField(default=True, blank=False)


    def get_absolute_url(self):
        return reverse("SiteEventsAPP: SiteEventsAPP-detail", kwargs={"pk": self.pk})

    # See below __str__(self) is a special method
    # It does a cool thing
    # Whenever Python asks for a string representation of my Event object, this method returns a human-readable version
    # If there is no string method, then Python returns the object type
    # This class method is really only needed for the admin page

    def __str__(self):
        return self.engine  # I have to have a field here. Whatever field I pick will be the field shown in admin

这是用户看到的结果:

【问题讨论】:

  • 你打算用这个success_message做什么?它不是任何基于类的内置视图的标准属性。
  • 丹尼尔,我在上面加了一个sn-p给你看。 “撤消”是需要PK的。但如果你有更好的主意,我很感兴趣。
  • 是的,但是您打算如何将该消息从班级获取到模板?
  • (另外,它不会影响您的问题,但请注意您的 get_object 方法是不必要的 - 它只是执行默认实现已经执行的操作。仅当您需要覆盖 get_object想做一些不寻常的事情。你应该删除你的版本。)
  • 好的就行。这是一次检索 PK 的尝试,但失败了。

标签: python django django-class-based-views


【解决方案1】:

如果你检查 SuccessMessageMixin 的代码,你会看到:

    class SuccessMessageMixin:
    """
    Add a success message on successful form submission.
    """
    success_message = ''

    def form_valid(self, form):
        response = super().form_valid(form)
        success_message = self.get_success_message(form.cleaned_data)
        if success_message:
            messages.success(self.request, success_message)
        return response

    def get_success_message(self, cleaned_data):
        return self.success_message % cleaned_data

正如您在此处看到的,返回成功消息的函数是 get_success_message,因此您只需覆盖该函数。

你的代码应该是:

class EventUpdateView(SuccessMessageMixin,UpdateView):

    template_name = 'update.html'
    form_class = EventForm
    success_url = '../list'
    queryset = Event.objects.all()    

    def form_valid(self, form):
        return super().form_valid(form)

    def get_success_message(self, cleaned_data):
        message = "Record has been updated <a href='unupdate?recordtobeunupdated="
        message += str(self.kwargs.get("pk"))
        message += "'>Undo</a>"
        return (mark_safe(message))

让我给你一个建议,永远不要把 python 库/框架当成一个黑盒实体,只要输入它们并探索它们是如何工作的,它会让你的编程生活更轻松。

祝你好运,继续努力!

【讨论】:

  • 谢谢,哈金。这行得通,我理解。正如 Daniel 指出的那样,我删除了不必要的 get_object,并将您的最后一行代码编辑为 message 而不是 undo_message。
  • 很高兴它成功了!我认为您也可以删除 form_valid 方法,您只是在调用 super。
  • 好的,我删除了 form_valid。再次感谢。
【解决方案2】:

您可以使用 django 内置消息:

def form_valid(self, form):
        messages.add_message(
            self.request, 
            messages.SUCCESS, 
            """
            Record has been updated <a href="unupdate?recordtobeunupdated={}">Undo</a>""".format(
                kwargs={'pk': self.kwargs['pk']}
             """"
        )

        return super(UserUpdate, self).form_valid(form)

使用 kwargs={'pk': self.kwargs['pk']} 您将获得 id。

之后,您可以在模板中捕获消息:

{% if messages %}
    {% for msg in messages %}
      <div class="alert
      alert-{% if msg.level_tag == 'debug' %}rose{% endif %}
      {% if msg.level_tag == 'info' %}info{% endif %}
      {% if msg.level_tag == 'success' %}success{% endif %}
      {% if msg.level_tag == 'warning' %}warning{% endif %}
      {% if msg.level_tag == 'error' %}danger{% endif %} alert-with-icon" data-notify="container">
        <i class="material-icons" data-notify="icon">
          {% if msg.level_tag == 'debug' %}code{% endif %}
          {% if msg.level_tag == 'info' %}info{% endif %}
          {% if msg.level_tag == 'success' %}done_all{% endif %}
          {% if msg.level_tag == 'warning' %}warning{% endif %}
          {% if msg.level_tag == 'error' %}error{% endif %}
        </i>
        <button type="button" class="close" data-dismiss="alert" aria-label="Close">
          <i class="material-icons">close</i>
        </button>
        <span data-notify="message">
          {% autoescape off %}
            {{ msg.message }}
          {% endautoescape %}
        </span>
      </div>
    {% endfor %}
  {% endif %}

上面的代码捕获每条消息(假设您使用的是一般布局)并使用引导程序将消息呈现为通知。

更多信息here

【讨论】:

    【解决方案3】:
    class PostCreateView(LoginRequiredMixin , CreateView):
            model =  Post
            template_name = 'blog/post_create.html'
            fields = ['title', 'content' ]
            success_url = '/'
        
            def form_valid(self, form):
                form.instance.author = self.request.user
                return super().form_valid(form )
        
            def my_fun(self, messages,request):
                messages = messages.success(request, f'Your account has been created, Now you able to login.')
                return super().my_fun( messages )
    
    
    
    <div class="container">
        {% if messages %}
                {% for message in messages %}
                  <div class="alert alert-{{ message.tags }}">
                    {{ message }}
                  </div>
                {% endfor %}
              {% endif %}
        {% block content %}{% endblock content %}
      </div>
    

    【讨论】:

    • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-07-02
    • 2011-08-19
    • 1970-01-01
    • 1970-01-01
    • 2021-03-28
    • 2021-02-07
    相关资源
    最近更新 更多