Django taggit如何记录添加标签的用户ID

Django taggit how to record id of user that added tag

我有使用 django-taggit 模块的 Django 应用程序。我的工作流程是添加一张照片,然后返回照片以使用 photo_edit 视图、photo_edit 表单和 photo_edit.html 模板分配标签,如下所示。

应用程序使用表单和模板中的 'tags': TagWidget() 成功标记了照片。这工作正常,它可以针对该照片保存新的、修改的或删除的标签。

但是我希望能够在django taggit模型数据库table中记录添加标签的人的用户id。 django taggit 没有这个功能。

首先,我已经成功地向 class TagBase(models.Model): 添加了一个新的 user 字段,使用 settings.AUTH_USER_MODEL 来引用在 user_id 中创建新列的用户对象taggit_tags table 当 makemigrations 是 运行.

现在我需要弄清楚如何在添加或编辑标记对象标签时获取当前用户 ID 以填充新的 user_id 列。

我已经尝试在我的应用程序视图和 django taggit 模型中执行此操作。理想情况下,由于这将是默认功能,因此用户 ID 保存在 django taggit 模型中。

django taggit 模型中,我尝试将 self.user = get_user_model().objects.get(id=request.user.id) 添加到 TagBase def save 函数中。但是它当然不知道 request 是什么。我还尝试在 TagBase 模型 class 中创建新函数,如下所示,并从 def save 函数调用它,但它 returns 什么都没有。

def get_user(request):
    user = request.user
    print('MODEL request user', request.user)
    return user

作为测试,我将 request.user.id 替换为硬编码 ID,例如 self.user = get_user_model().objects.get(id=1) 实际上确实将 1 写入 taggit_tag table user_id 字段那个标签。

我也尝试在应用程序视图中执行此操作。例如,我在 save_m2m() 之前尝试过 photo.tag.user_id = request.user.id,但没有用。目前尚不清楚什么语法(如果有的话)可用于保存相关模型字段。我相信我必须修改表单 TagWidget() 以包含 user_id 字段,这样 save_2m2() 会保存它,但我想避免修改 django-taggit 太多。

我进行了详尽的搜索,但没有找到任何特定于 Django 和 django-taggit 的东西。也许有人可以从 Python 的角度提供帮助!

照片编辑表单

class PhotoEditForm(ModelForm):
    #filename = forms.ImageField()
    class Meta:
        model = Photo
        fields = (
            'tags',
        )
        widgets = {
            'tags': TagWidget(),
        }

照片编辑视图 - 理想情况下,我可以在 form.save_m2m() 之前保存 request.user,例如 photo.taggit_tag.user_id = user.id。有一些语法可以在这里工作吗?

def photo_edit(request, photo_id):
    photo = Photo.objects.get(id=int(photo_id))
    user = get_user_model().objects.get(id=request.user.id)
    photo_tags = Tag.objects.filter(photo=photo.id).order_by('name')

    if request.method == "POST":
        form = PhotoEditForm(request.POST, instance=photo)

        if form.is_valid():
            photo = form.save(commit=False)
            photo.modified = timezone.now()
            photo = form.save()

            #save tags if any
            form.save_m2m()

            return HttpResponseRedirect(reverse('photo', kwargs={ 'photo_id': photo.id,}))

    else:
        form = PhotoEditForm(instance=photo)

    context = { 
        'photo_form': form,
        'photo': photo, 
        'photo_tags': photo_tags,
        'title': 'Edit Mode',
        }

    return render(
        request,
        'photo_edit.html',
        context,

    )  

照片模特

class Photo(models.Model):
    filename = CloudinaryField('image')
    user = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=True)
    inactive = models.BooleanField(default=False, choices=INACTIVE_CHOICES)
    created = models.DateTimeField(blank=True, null=True)
    modified  = models.DateTimeField(blank=True, null=True)
    tags = TaggableManager()

    class Meta:
        managed = True
        db_table = 'photo'
        verbose_name_plural = 'photos'

    def __str__(self):
        return str(self.filename)

我确实对 django taggit 模型进行了轻微修改以包含 user_id 字段。理想情况下,我可以将此 user_id 设置为 request.user 作为默认值,但还没有看到任何看起来简单或容易的东西。

class TagBase(models.Model):
    name = models.CharField(verbose_name=_("Name"), unique=True, max_length=100)
    slug = models.SlugField(verbose_name=_("Slug"), unique=True, max_length=100)
    # added user to model which created `user_id` column on `taggit_tags` table
    user = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=True)

    def __str__(self):
        return self.name

    def __gt__(self, other):
        return self.name.lower() > other.name.lower()

    def __lt__(self, other):
        return self.name.lower() < other.name.lower()

    class Meta:
        abstract = True

    def save(self, *args, **kwargs):
        self.user = get_user_model().objects.get(id=1)
        if self._state.adding and not self.slug:
            self.slug = self.slugify(self.name)
            using = kwargs.get("using") or router.db_for_write(
                type(self), instance=self
            )

你可能想看看 django-crum:Django-CRUM(当前请求用户中间件)在线程本地存储中捕获当前请求和用户。

我在解决类似问题时使用了它。它允许您访问当前用户而无需直接传递请求对象:

https://django-crum.readthedocs.io/en/stable/