【问题标题】:Django model to automatically update username and date/time when Article modifiedDjango模型在文章修改时自动更新用户名和日期/时间
【发布时间】:2020-12-26 23:35:42
【问题描述】:

我有一个名为 Post 的模型,我正在尝试自动保存上次修改文章的登录用户的用户名以及时间戳。到目前为止 DateTime 时间戳正在更新值,但我无法使用用户名获得相同的结果。

models.py

class Post(models.Model):
    article = models.TextField(max_length=2000)
    username = models.ForeignKey(User, on_delete=models.CASCADE, related_name='usernames')
    updated_at = models.DateTimeField(auto_now=True)

forms.py

class PostForm(ModelForm):

    def __init__(self, *args, **kwargs):    

        super(PostForm, self).__init__(*args, **kwargs)
        
    class Meta:
        model = Post
        fields = '__all__'

views.py

class PostUpdate(UpdateView):
    model = Post
    form_class = PostForm
    
    def save_model(self, request, obj, form, change):
        obj.username = request.user
        obj.save()

【问题讨论】:

  • 你能在你想要更新的地方添加视图吗?
  • 你不能自动实现这一点,因为模型通常是模型不感知的。有一些中间件可以做到这一点,但这仍然可能不是一个好主意。您可以制作一个简单的 mixin,并在您创建/更新 Post 对象的 UpdateViews 和 CreateViews 中使用该 mixin。

标签: django django-models django-views django-forms django-templates


【解决方案1】:

首先,如果您希望您的用户名仅由 request.user 设置,然后将 editable=False 添加到 Post 模型中的用户名字段。

username = models.ForeignKey(User, on_delete=models.CASCADE, related_name='usernames', editable=False)

然后在您的 admin.py 中:

from . import models
from django.contrib import admin

class PostAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        obj.username = request.user
        obj.save()

admin.site.register(models.Post, PostAdmin)

编辑从这里开始

models.py

from django.db import models
from django import forms

class Post(models.Model):
    article = models.TextField(max_length=2000)
    username = models.ForeignKey(User, on_delete=models.CASCADE, related_name='usernames') # we don't need editable=False anymore
    updated_at = models.DateTimeField(auto_now=True)


class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = '__all__'

views.py

from . import models
from django.shortcuts import render, get_object_or_404
from django.contrib import messages

def post(request, id):
    post = get_object_or_404(models.Post, id=id) # get a specific post with id
    if request.method == 'POST':
        form = models.PostForm(request.POST, instance=post) # create a post form instance
        if form.is_valid():
            data = models.Post() # create a post model instance
            data.article = form.cleaned_data['article']
            data.username = request.user
            # updated_at field updating automatically
            data.save() # dont't forget to save these data
            messages.success(request, 'Article updated successfully') # this line is optional
        else:
            messages.success(request, form.errors) # this line is optional
    else:
       form = models.PostForm(instance=post)
    return render(request, 'post.html', {'form': form})

        

urls.py

from django.urls import path
from . import views

app_name = 'post'
urlpatterns = [
    path('post/<int:id>', views.post, name='article'),
]

html(模板) 没有小部件调整(简单形式)

<form method="POST">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Send</button>
</form> 

html(模板) 带有小部件调整和引导类(可选)

{% load widget_tweaks %}

<form method="POST">
    {% csrf_token %}
    {% for field in form %}
    <div class="form-group">
        <div class="form-control-border"></div>
        {{ field.label }}
        {% render_field field class="form-control" %}
    </div>
    {% endfor %}
    <button type="submit" class="btn btn-outline-primary-2">Send</button>
</form> 

如果有错误请告诉我

【讨论】:

  • 它不起作用,也没有给我任何错误。
  • 管理员工作正常。让我们在模板中执行此操作。先告诉我你用的是什么表格,或者你想用什么表格? django 表单还是 html 表单?并将您的views.py和html代码添加到问题中
  • 添加视图和表单的附加代码
  • Willem Van Onsem 对 CBV 的回答很好。实际上我对 CBV 了解不多,但我可以用 FBV 做到这一点。告诉我你是否想要FBV
  • 是的,请告诉我如何使用 FBV 来实现这一点。
【解决方案2】:

CreateViewUpdateView 没有 save_model 方法。为此,您使用 form_valid 方法:

class PostUpdate(UpdateView):
    model = Post
    form_class = PostForm
    
    def form_valid(self, form):
        form.instance.username = self.request.user
        return super().form_valid(form)

你可以在一个mixin中定义逻辑,然后在多个视图中使用这个mixin,例如:

from django.contrib.auth.mixins import LoginRequiredMixin

class PostAutorMixin(LoginRequiredMixin):
    def form_valid(self, form):
        form.instance.username = self.request.user
        return super().form_valid(form)

然后将其用于:

class PostCreate(PostAuthorMixin, CreateView):
    # …

class PostUpdate(PostAuthorMixin, UpdateView):
    # …

PostCreatePostUpdate 视图中,您不会覆盖form_valid 方法。


注意ForeignKey 确实存储 列中引用的对象,它存储它的记录的主键 在带有_id 后缀的列中引用ForeignKey 字段。所以 ForeignKeys 通常_name 后缀结尾。你可能想要 考虑将 username 字段重命名为 author


注意:您可以将视图限制为基于类的视图,以便通过身份验证的用户使用 LoginRequiredMixin mixin [Django-doc].

【讨论】:

    【解决方案3】:

    你可以使用request.user

    # Editing Article View
    post_to_be_modified.username = request.user
    post_to_be_modified.save()
    

    虽然该字段应称为userauthor,因为它不仅存储用户名,还存储用户。

    您不能自动执行此操作,因为用户不是全局 Python 对象,这意味着它必须通过视图参数进行修改。

    【讨论】:

      猜你喜欢
      • 2011-09-20
      • 1970-01-01
      • 2015-05-17
      • 2016-07-26
      • 2013-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-05
      相关资源
      最近更新 更多