【问题标题】:How do I pass the current user id as a hidden field in a Django form?如何将当前用户 ID 作为 Django 表单中的隐藏字段传递?
【发布时间】:2023-04-09 00:17:01
【问题描述】:

我遇到的问题是我正在尝试创建一个表单,该表单通过将当前登录的用户 ID 嵌入到 ModelForm 的隐藏字段中来传递它。

我的模特:

class Portfolios(models.Model):
    id = models.AutoField(primary_key=True)
    port_name = models.CharField(max_length=135, blank=True)
    port_type = models.ForeignKey(PortType, null=True, db_column='port_type', blank=True)
    user = models.ForeignKey(User)

    def __unicode__(self):
        return self.port_name;

class Meta:
    db_table = u'tbl_portfolios'

我的表格:

class PortfoliosCreateForm(ModelForm):
    class Meta:
        model = Portfolios;

我的模板:

<form action="" method="post">
    {% csrf_token %}
    {% for field in form %}
        <div class="create_form_field">
            {{ field.errors }}
            {{ field.label_tag }}: {{ field }}
        </div>
    {% endfor %}
    <input type="submit" value="Create" /></p>
</form>

我使用通用创建视图调用模板:

url(
    r'^portfolios/create/$',
    'django.views.generic.create_update.create_object',
    dict(
        form_class=PortfoliosCreateForm,
        post_save_redirect='/',
        template_name='portfolios/create.html'
    )

),

如何最好地将用户 ID 嵌入该表单中,以便传递隐藏字段?还是我应该简单地传入一个虚拟字段并在自定义保存函数中填写值?

编辑:用户模型是内置的 Django 用户模型。

谢谢

【问题讨论】:

  • 您使用的是内置的用户模型吗?当您对我说“当前用户 ID”时,这表明您的应用已经以某种方式了解用户,如果是这种情况,在表单上传递它应该是不必要的?
  • 我使用的是内置的用户模型,是的。提交表单时,用户必须登录到系统,因此从这个意义上说,应用程序已经知道用户。我不知道在哪里可以检索用户 ID,因此可能会将其保存为记录的一部分。

标签: django forms hidden


【解决方案1】:

在表单提交后从请求中获取当前用户要安全得多。您可以将通用视图重写为如下内容:

from django.shortcuts import redirect, render

def create_portfolio(request):
    if request.method == 'POST':
        form = PortfoliosCreateForm(request.POST)
        if form.is_valid():
            portfolio = form.save(commit=False)
            portfolio.user = request.user  # The logged-in user
            portfolio.save()
            return redirect('/')
    else:
        form = PortfoliosCreateForm()
    return render(request, 'portfolios/create.html', {'form': form})


url(r'^portfolios/create/$', create_portfolio)


class PortfoliosCreateForm(ModelForm):
    class Meta:
        model = Portfolios;
        exclude = ['user']   # Will be taken from the request

【讨论】:

  • @JakubRoztočil 请在下面查看我的回答。
【解决方案2】:

在通用视图中设置 all 不是一个好习惯,因为:

  1. 它会强制您更改 form 类中的逻辑,这可能会添加约束漏洞,因此如果您尝试在外部某处创建对象,则可以将 bad 数据保存到数据库中通用视图,以及
  2. 它为通用视图增加了额外的无用复杂性。视图就像一个控制器,它应该知道 WHO 负责验证/保存数据并将其委托给该方。它不应该知道对象是如何关联和验证的,并且
  3. 它迫使您到处分发代码。

在我看来,更好的方法可能是:

型号

class Book(models.Model):
    # ...
    author = models.ForeignKey(Author, related_name='books')

    # ...

表格

class BookForm(forms.ModelForm):

class Meta:
    model = Book
    # ...

    widgets = {
        'author': forms.HiddenInput(),
        # ...
    }

    # ...

查看

def create(request, author_id):
    author = get_object_or_404(Author, pk=author_id)
    form = BookForm(request.POST or None, initial={'author': author.id})
    if request.method == "POST":
        if form.is_valid():
            form.save()
            return redirect('/')

因此,这将允许您使用 Django 表单验证并为 IDs 设置数据库约束,以确保您将有效数据放入数据库。

【讨论】:

  • 这个问题是关于“[创建]一个传递当前登录用户的表单”。您的代码没有解决这个问题,也没有阻止用户通过更改隐藏字段值来伪装成另一个用户。因此,您的答案既不正确也不安全。
猜你喜欢
  • 1970-01-01
  • 2017-02-25
  • 2018-08-29
  • 2020-11-16
  • 1970-01-01
  • 2021-02-26
  • 1970-01-01
  • 2011-10-15
  • 1970-01-01
相关资源
最近更新 更多