【问题标题】:Referencing the current user in Class Based Views (CBV)在基于类的视图 (CBV) 中引用当前用户
【发布时间】:2014-06-23 05:53:10
【问题描述】:

我已经实现了一个表单,我需要在其中填充用户对象中的字段(名字、姓氏、电子邮件)以及填写新的成员资格对象。我已经使用基于函数的视图 (FBV) 实现了这一点,但我觉得我应该能够使用基于类的视图 (CBV) 来做到这一点。问题的核心似乎是在表单中引用当前用户而不传入用户对象。在 FBV 中,这很容易做到,但我找不到任何使用 CBV 的示例。我在想我一定是在这里遗漏了什么。

这是我的代码

models.py

class Membership(models.Model):

    """Represents an active membership of a user. Both the start_date and
    end_date parameters are inclusive."""

    DEFAULT_DURATION = 365  # the default number of days a membership is active

    start_date = models.DateField(auto_created=True)
    end_date = models.DateField(null=True)
    membership_type = models.ForeignKey(MembershipType)
    referral = models.ForeignKey(User, related_name='membership_referral', null=True)

    # Contact Info
    phone = PhoneNumberField()

    # Address Fields
    address_1 = models.CharField(max_length=255)
    address_2 = models.CharField(max_length=255, blank=True)

    city = models.CharField(max_length=64)
    state = USStateField()
    zip_code = USPostalCodeField()

    def save(self, force_insert=False, force_update=False, using=None,
         update_fields=None):
    """Overload the save function to set the start and end date."""
    self.start_date = datetime.date.today()
    self.end_date = (self.start_date +
                     datetime.timedelta(days=self.membership_type.period))
    super().save()

    @property
    def is_active(self):
    return self.end_date >= datetime.date.today()

forms.py

class MembershipForm(ModelForm):
    """The Form shown to users when enrolling or renewing for membership."""

    def __init__(self, *args, **kwargs):
    self.user = kwargs.pop("user", None)

    _fields = ('first_name', 'last_name', 'email',)
    _initial = model_to_dict(self.user, _fields) if self.user is not None else {}

    super(MembershipForm, self).__init__(initial=_initial, *args, **kwargs)
    self.fields.update(fields_for_model(User, _fields))
    self.fields['referral'].required = False

    class Meta:
    model = Membership
    fields = ['membership_type', 'referral', 'phone', 'address_1',
              'address_2', 'city', 'state']

    zip_code = USZipCodeField(max_length=5, required=True)

    def save(self, *args, **kwargs):
    self.user.first_name = self.cleaned_data['first_name']
    self.user.last_name = self.cleaned_data['last_name']
    self.user.email = self.cleaned_data['email']
    self.user.save()
    profile = super(MembershipForm, self).save(*args, **kwargs)
    return profile

views.py

@login_required
def enroll(request):
    template_name = 'enroll.html'

    if request.method == 'POST':
    form = MembershipForm(request.POST, user=request.user)

    if form.is_valid():
        form.save()
        return redirect('/')
    else:
    form = MembershipForm(user=request.user)

    return render(request, template_name, {'form': form})

【问题讨论】:

    标签: python django python-3.x django-forms django-views


    【解决方案1】:

    您可以通过 self.request.user 在基于类的视图中访问当前用户。可以通过重新定义 validate 方法在 FormView 中设置,如下所示:

    class YourView(CreateView)
        ...
    
        def form_valid(self, form):
            form.instance.user = self.request.user
            return super(YourView, self).form_valid(form)
    

    我在示例中使用了 CreateView 而不是 FormView,因为出于安全目的,您应该在编辑时额外检查当前实例的用户。

    【讨论】:

      【解决方案2】:

      虽然您的问题提到了 CBV,但在您使用 FBV 的代码中。

      在 FBV 中,您可以访问正在传递的请求变量。在这种情况下,您可以使用 request.user 。

      对于 CBV,Django 允许您以 self.request 的形式访问请求对象。在 CBV 的默认 'django.views.generic.base.View' 类的实现中,他们首先会这样做。

      在此代码中将 def 视图的第 4 行检查为 as_view 的一部分 - https://github.com/django/django/blob/master/django/views/generic/base.py

      所有对象,包括作为请求一部分的用户,都可以作为 self.request.user 访问。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-02-21
        • 2020-02-17
        • 1970-01-01
        • 2016-07-28
        • 2011-10-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多