Referencing the current user in Class Based Views (CBV

By : Slick
Source: Stackoverflow.com
Question!

I've implemented a form where I require fields in the User object to be populated (firstname, lastname, email) as well as fill out a new membership object. I've implemented this with a Function Based View (FBV) but I feel like I should be able to do this with a Class Based View (CBV). The heart of the problem seems to be referencing the current user in a form without passing in the user object. In FBV it's easy to do but I can't find any examples using CBV. I'm thinking that I must be missing something here.

Here is my code

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})
By : Slick


Answers

Although your question mentions CBV, yet in the code you are using FBV.

In FBV you have access to request variable being passed. You can use request.user in this case.

In case of CBVs, Django allows you to access request object as self.request. In the implementation of default 'django.views.generic.base.View' class of CBV, they do this as first thing.

Check 4th line of def view as part of as_view in this code - https://github.com/django/django/blob/master/django/views/generic/base.py

All the objects, including user as part of request can be accessed as self.request.user.

By : iankit


This video can help you solving your question :)
By: admin