在基于类的视图中引用当前用户
我实现了一个表单,要求用户对象中的一些字段必须填写(比如名字、姓氏和邮箱),同时还需要填写一个新的会员对象。我是用函数视图(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})
2 个回答
0
虽然你的问题提到了CBV(类视图),但在代码中你使用的是FBV(函数视图)。
在FBV中,你可以直接访问传入的请求变量。在这种情况下,你可以使用request.user来获取用户信息。
而在CBV中,Django允许你通过self.request来访问请求对象。在CBV的默认实现中,'django.views.generic.base.View'类会首先这样做。
你可以查看代码中as_view方法的第4行 - https://github.com/django/django/blob/master/django/views/generic/base.py
所有对象,包括请求中的用户信息,都可以通过self.request.user来访问。
5
在基于类的视图中,你可以通过 self.request.user 来获取当前用户的信息。如果你想在 FormView 中使用,可以通过重新定义验证方法来实现,像这样:
class YourView(CreateView)
...
def form_valid(self, form):
form.instance.user = self.request.user
return super(YourView, self).form_valid(form)
我在这个例子中用了 CreateView,而不是 FormView,因为在编辑的时候,你还需要检查当前实例的用户,以确保安全。