feldo badix
feldo badix

Reputation: 125

how to get user object and pass it to form field in django

is there a better way to get the user object from the code below in forms.py?

models

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    ...

forms.py

class FooForm(forms.Form):

    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop("user")
        super(ExperienceStart, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_method = 'post'
        self.helper.layout = Layout(InlineRadios('topics'),)

    hardcoded_username = "johndoe" # i want to find a way not to hardcode this

    current_user = User.objects.filter(username=hardcoded_username).first()

    profile = Profile.objects.filter(user=current_user).first()

    ...

    profile_values = list(zip(profile, profile))

    profile = forms.TypedChoiceField(
        label="Select a Profile",
        choices=profile_values,
        coerce=str,
        widget=forms.RadioSelect,
        initial=profile[0],
        required=True)

views.py

def foo(request):
    form = fooForm(request.POST, user=request.user)

    print(form.request) # i have already tried this but i want to get it in form not views

    if request.method == "POST":
        if form.is_valid():
            # do something
    else:
        form = fooForm(user=request.user)

    context = {"form": form}

I am trying to find a way not to hardcode the username in forms.py and get the current logged in user.

Upvotes: 2

Views: 1830

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477704

Don't include it in the form. Forms are typically request unaware, and furthermore are used to process input from the HTML form.

You can make use of the initial=… parameter of the form to specify the initial item.

In your form you can use a ModelChoiceField [Django-doc] to select a Profile item:

class FooForm(forms.Form):

    profile = forms.ModelChoiceField(
        label='Select a Profile',
        queryset=Profile.objects.all(),
        widget=forms.RadioSelect,
        required=True
    )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_method = 'post'
        self.helper.layout = Layout(InlineRadios('topics'))

then in the view, you can pass the profile of the user as initial value:

from django.shortcuts import redirect, render
from django.contrib.auth.decorators import login_required

@login_required
def foo(request):
    if request.method == 'POST':
        form = fooForm(request.POST, initial={'profile': request.user.profile})
        if form.is_valid():
            # do something
            return redirect('name-of-some-view')
    else:
        form = fooForm(initial={'profile': request.user.profile})
    context = {'form': form}
    return render(request, 'some_template.html', context)

Note: You can limit views to a view to authenticated users with the @login_required decorator [Django-doc].


Note: In case of a successful POST request, you should make a redirect [Django-doc] to implement the Post/Redirect/Get pattern [wiki]. This avoids that you make the same POST request when the user refreshes the browser.

Upvotes: 1

Related Questions