django - middleware issue - django

I want to put a login form everywhere on my website, after following a few SO answers I decide to write my own middleware like this:
class LoginFormMiddleware(object):
'''
Put a login form in everypage of the website
'''
def process_request(self, request):
# if the top login form has been posted
if request.method == 'POST':
if 'logout_submit' in request.POST:
# log the user out
from django.contrib.auth import logout
logout(request)
form = LoginForm()
elif 'login_submit' in request.POST:
# validate the form
form = LoginForm(data=request.POST)
if form.is_valid():
# log the user in
from django.contrib.auth import login
login(request, form.get_user())
else:
form = LoginForm(request)
else:
form = LoginForm(request)
# attach the form to the request so it can be accessed
# within the templates
request.login_form = form
in my settings.py, I have:
import django.conf.global_settings as DEFAULT_SETTINGS
...
MIDDLEWARE_CLASSES = DEFAULT_SETTINGS.MIDDLEWARE_CLASSES + (
'base.mymiddleware.LoginFormMiddleware',
)
TEMPLATE_CONTEXT_PROCESSORS = DEFAULT_SETTINGS.TEMPLATE_CONTEXT_PROCESSORS + (
'django.core.context_processors.request',
)
The form, in base.html to be accesed from everywhere, looks like this:
{% if user.is_authenticated %}
<div class="login_box">
<form action="/myapp/logout/" method="post">{% csrf_token %}
<div class="col2"><a>{{ user.username }}</a></div>
<div class="col3"><input type="submit" value="Logout" name="logout_submit"/></div>
</form>
</div>
{% else %}
<form action="." method="post">
{% csrf_token %}
<div class="login_box">
<div class="error_box">
{% if request.login_form.errors %}
Incorrect User/Password
{% endif %}
</div>
<div class="col00"> <h4>{{ request.login_form.username.label_tag }}</h3></div>
<div class="col11">{{ request.login_form.username }}</div>
<div class="col22"><h4>{{ request.login_form.password.label_tag }}</h3></div>
<div class="col33">{{ request.login_form.password }}</div>
<div class="col44"><input type="submit" value="Login" name="login_submit"/></div>
<input type="hidden" name="next" value="{{ request.get_full_path }}" />
</div>
</form>
{% endif %}
Login works normally but, after doing it, each time I make a GET request user.is_authenticated seems to return false cause what I see is an empty LoginForm instead of the logout form.
I dont know if the problem is in my middleware (when request.method != 'POST' it returns form = LoginForm(request)) or it is something I am missing in my settings, or maybe using middleware for this was not a great idea...

I can't believe you have seen any SO answers that advocate putting this sort of logic in the middleware. (If you have, post the link so that I can downvote them.)
This really, really, really isn't the place to do this sort of thing. Write a specific view and set the action parameter of the login form to that view.
However, I suspect your underlying issue is that you're not using RequestContext to render the other views, so the user object is not passed to the template.

Your implementation doesn't make much sense. A login form with action attribute is "." is wrong and will lead to conflicts.
You should have a login view, not a login middleware. The action attribute of the login form should be the reversed url of your login view.
In your login form, you should specify a next hidden input for example:
<input name="next" type="hidden" value="{{ request.POST.next|default:request.path }}" />
Following that, it can be in your base template or anywhere in the website.
This is also valid for logout.

Related

Django custom admin actions with an intermediate page submit not triggered

Writing an admin action so an administrator can select a template they can use to send a message to subscribers by inputting only the subject and text message. Using a filtered list from the admin panel an action called broadcast is triggered on this queryset (the default filter list). The admin action 'broadcast' is a function of a sub-classed UserAdmin class. The intermediate page is displayed that shows a dropdown selector for the emailtype, the queryset items (which will be email addresses, input fields for the subject and message text (message is required field) a button for optional file attachment followed by send or cancel buttons. Problem 1) after hitting the send button the app reverts to the admin change list page. In the broadcast function, the conditional if 'send' in request.POST: is never called.
forms.py
mail_types=(('1','Newsletter Link'),('2','Update Alert'))
class SendEmailForm(forms.Form):
_selected_action = forms.CharField(widget=forms.MultipleHiddenInput)
#Initialized 'accounts' from Account:admin.py Actions: 'send_email' using>> form = SendEmailForm(initial={'accounts': queryset})
my_mail_type=forms.ChoiceField(label='Mail Type',choices=mail_types,required=False)
subject = forms.CharField(widget=forms.TextInput(attrs={'placeholder': ('Subject')}),required=False)
message = forms.CharField(widget=forms.Textarea(attrs={'placeholder': ('Teaser')}),required=True,min_length=5,max_length=1000)
attachment = forms.FileField(widget=forms.ClearableFileInput(),required=False)
accounts = forms.ModelChoiceField(label="To:",
queryset=Account.objects.all(),
widget=forms.SelectMultiple(attrs={'placeholder': ('user_email#somewhere.com')}),
empty_label='user_email#somewhere.com',
required=False,
admin.py
from .forms import SendEmailForm
from django.http import HttpResponseRedirect,HttpResponse
from django.shortcuts import render, redirect
from django.template.response import TemplateResponse
def broadcast(self, request, queryset):
form=None
if 'send' in request.POST:
print('DEBUGGING: send found in post request')
form = SendEmailForm(request.POST, request.FILES,initial={'accounts': queryset,})
if form.is_valid():
#do email sending stuff here
print('DEBUGGING form.valid ====>>> BROADCASTING TO:',queryset)
#num_sent=send_mail('test subject2', 'test message2','From Team',['dummy#hotmail.com'],fail_silently=False, html_message='email_simple_nb_template.html',)
self.message_user(request, "Broadcasting of %s messages has been started" % len(queryset))
print('DEBUGGING: returning to success page')
return HttpResponseRedirect(request, 'success.html', {})
if not form:
# intermediate page right here
print('DEBUGGING: broadcast ELSE called')
form = SendEmailForm(request.POST, request.FILES, initial={'accounts': queryset,})
return TemplateResponse(request, "send_email.html",context={'accounts': queryset, 'form': form},)
send_email.html
{% extends "admin/base_site.html" %}
{% load i18n admin_urls static %}
{% load crispy_forms_tags %}
{% block content %}
<form method="POST" enctype="multipart/form-data" action="" >
{% csrf_token %}
<div>
<div>
<p>{{ form.my_mail_type.label_tag }}</p>
<p>{{ form.my_mail_type }}</p>
</div>
<div>
<p>{{ form.accounts.label_tag }}</p>
<p>
{% for account in form.accounts.queryset %}
{{ account.email }}{% if not forloop.last %}, {% endif %}
{% endfor %}
</p>
<p><select name="accounts" multiple style="display: form.accounts.email">
{% for account in form.accounts.initial %}
<option value="{{ account.email }}" selected>{{ account }}</option>
{% endfor %}
</p></select>
</div>
<div>
<p>{{ form.subject.label_tag }}</p>
<p>{{ form.subject }}</p>
</div>
<div>
<p>{{ form.message.label_tag }}</p>
<p>{{ form.message }}</p>
</div>
<div>
<p>{{ form.attachment.label_tag }}</p>
<p>{{ form.attachment.errors }}</p>
<p>{{ form.attachment }}</p>
</div>
<input type="hidden" name="action" value="send_email" />
<input type="submit" name="send" id="send" value="{% trans 'Send messages' %}"/>
{% trans "Cancel this Message" %}
</div>
</form>
{% endblock %}
Inspecting the browser at the POST call seems to show all the data was bound. Another poster here suggested the admin action buttons divert requests to an internal 'view' and you should redirect to a new view to handle the POST request. I can't get that to work because I can't get a redirect to 'forward' the queryset. The form used in the suggested fix was simpler and did not use the queryset the same way. I have tried writing some FBVs in Forms.py and Views.py and also tried CBVs in views.py but had issues having a required field (message) causing non-field errors and resulting in an invalid form. I tried overriding these by writing def \_clean_form(self): that would ignore this error, which did what it was told to do but resulted in the form essentially being bound and validated without any inputs so the intermediate page didn't appear. Which means the rabbit hole returned to the same place. The send button gets ignored in either case of FBVs or CBVs, which comes back to the admin action buttons Post requests revert to the admin channels!
Any ideas on how to work around this? Key requirements: From the admin changelist action buttons:
the Form on an intermediate page must appear with the queryset passed from the admin changelist filter.
The message input field on the form is a required field.
the send button on the HTML form view needs to trigger further action.
NOTES: My custom Admin User is a subclass of AbstractBaseUser called Account, where I chose not to have a username and am using USERNAME_FIELD='email'. Also, I do not need a Model.py for the SendEmailForm as I don't need to save the data or update the user models, just send the input message using the chosen template and queryset. Help is much appreciated!
It will never work in your case:
You call the action.
You receive the Action Confirmation template render.
After pressing "SEND" in your "confirmation" step, you send a POST request to ModelAdmin, not in your FB-Action.
ModelAdmin gets a POST request without special parameters and shows you a list_view by default.
In your case, you should add a send_email.html template:
{% load l10n %}
{# any your staff here #}
{% block content %}
<form method="POST" enctype="multipart/form-data">
{# any your staff here #}
<div>
<p>{{ form.attachment.label_tag }}</p>
<p>{{ form.attachment.errors }}</p>
<p>{{ form.attachment }}</p>
</div>
{% for obj in accounts %}
<input type="hidden" name="_selected_action" value="{{ obj.pk|unlocalize }}" />
{% endfor %}
<input type="hidden" name="action" value="broadcast" />
{# any your staff here #}
</form>
{% endblock %}
You should change your action view, some things are not working in your code:
def broadcast(self, request, queryset):
form = SendEmailForm(data=request.POST, files=request.FILES, initial={'accounts': queryset})
if 'send' in request.POST:
... # your staff here
if form.is_valid():
... # your staff here
# return HttpResponseRedirect(request, 'success.html', {} ) this is NEVER WORK
return TemplateResponse(request, 'success.html', {})
... # your staff here
return TemplateResponse(request, "send_email.html",context={'accounts': queryset, 'form': form},)
I am giving you a solution that I have TESTED on my project. I am sure, it works.
We were told on DjangoCon Europe 2022 that django-GCBV is like a ModelAdminAction and I've added a link below for the talk.
https://youtu.be/HJfPkbzcCJQ?t=1739
I can't get that to work because I can't get a redirect to 'forward' the queryset
I have a similar use case and save the primary keys of the filtered query set in the session (in your case you may be able to save emails and avoid another query)
def broadcast(self, request, queryset):
request.session["emails"] = list(queryset.values_list("emails", flat=True))
return HttpResponseRedirect("url_to_new_view")
I can then use primary keys to filter query set in the new view. You also handle the form in this new view.
User.objects.filter(email__in=self.request.session["emails"])

Django Return redirect working for one view but not for the other

I cannot understand why it is working in one instance but not the other. I am working with django and output in django template. The only difference between the views/functions are in the second one (the one that is not working) I update the field with time. Time updates, saves in the model and displays updated time correctly. It is just the redirect that is not working.
The working redirect code-
Template, this code takes me to the edit page. Name of the url is "update" -
<td><button>Edit</button></td>
The form on the dit page-
{% block content %}
<div class="wrapper">
<h1 class="ok">Entry Form</h1>
<form action="" method="POST">
{% csrf_token %}
{{form}}
<input type="submit" value="submit">
</form>
</div>
<br>
{% endblock content %}
url-
path('update_entry/<str:pk>/', views.update, name = "update"),
And views.py-
def update(request, pk):
order=Bank1.objects.get(id=pk)
form = Bank1Form(instance=order)
if request.method == 'POST':
form = Bank1Form(request.POST, instance=order)
if form.is_valid():
form.save()
return redirect('/bank1')
context = {'form':form}
return render(request, 'myapp/entry.html', context)
Now here is the non working code. Template, the line that takes me to the update page. Name of the url is "update_enter_workout.-
<td><button>Start Time</button></td>
Form on the Edit page. Didn't add the entire form since I only need to update the time from this page. Just the submit button.-
{% block content %}
<Button>Close this page and go to Home</Button>
<div class="wrapper">
<h1 class="ok">Start/End the set now?</h1>
<form action="" method="post">
{% csrf_token %}
<input type="submit" value="YES!">
</form>
</div>
{% endblock content %}
url-
path('update_enter_workout/<str:pk>/', views.update_workout, name='update_enter_workout'),
Views.py-
def update_workout(request, pk):
order=WorkOut.objects.get(id=pk)
form=WorkOutForm(instance=order)
if request.method=='POST':
form=WorkOutForm(request.POST, instance=order)
time=datetime.now().strftime('%H:%M:%S')
WorkOut.objects.filter(id=pk).update(start=time)
if form.is_valid():
form.save()
return redirect('/bank1')
context={'form':form}
return render(request, 'myapp/enter_workout.html', context)
As you can see they are written the same way, but in the second instance redirect is not working. Any idea what can be changed. It is so simple, couldn't even find a typo or simple mistake like that.
Any advise?
Are you accepting str for id fields? Primary Keys are integers, not strings. You need to cast to an int path converter:
Instead of:
path('update_enter_workout/<str:pk>/', views.update_workout, name='update_enter_workout'),
Use:
path('update_enter_workout/<int:pk>/', views.update_workout, name='update_enter_workout'),

django call function in all views (login)

I would like to call a function which is in /inscription/views.py since all views (because it's for the login). And I need to pass the username and the password in parameters to log the user.
def login_user(request):
if request.method =='POST':
auth_form=AuthenticationForm(data=request.POST)
if auth_form.is_valid():
username = request.POST.get('username')
password = request.POST.get('password')
uti = authenticate(username = username,password = password)
if uti:
if uti.is_active:
login(request, uti)
return HttpResponseRedirect('/accueil')
else:
return HttpResponse("Your account is disabled.")
else:
return HttpResponse("Invalid login details supplied.")
else:
auth_form=AuthenticationForm()
return render_to_response('authentication.html',
{'auth_form': auth_form}, RequestContext(request))
def logout_user(request):
logout(request)
And In my base.html I would like to add something like :
<label class="form_login">pseudo : </label>
<input type="text" name="username" id="id_username" class="login_input">
<label class="form_login">mot de passe : </label>
<input type="text" name="password" id="id_password" class="login_input">
<input value="login" type="submit"/>
<button>logout</button>
If I understand your question correctly, what you need is to force the user to login if he is not already logged in before he can access your views. To do this, all you need to do is to decorate your views with login_required decorator
from django.contrib.auth.decorators import login_required
#login_required
def my_view(request):
...
From the docs:
login_required() does the following:
- If the user isn’t logged in, redirect to settings.LOGIN_URL, passing
the current absolute path in the query string. Example:
/accounts/login/?next=/polls/3/.
- If the user is logged in, execute the view normally. The view code is
free to assume the user is logged in.
Update:
From your comment, now I understand that you need to make a form in all pages for the user to login, or a logout link if he is already logged in. First you need to define your URLs for these views:
url(r'^login/$', 'inscription.views.login', name='auth_login'),
url(r'^logout/$', 'inscription.views.logout', name='auth_logout'),
And in your base.html:
{% if user.is_authenticated %}
Logout
{% else %}
<form method="post" action="{% url 'auth_login' %}">
{% csrf_token %}
<input type="text" name="username" id="id_username">
<input type="text" name="password" id="id_password">
<input type="submit" value="Log in" />
</form>
{% endif %}
As a side note, I highly recommend you to use one of these reusable apps for auth and registration. unless you have strange requirements.
http://django-registration-redux.readthedocs.org/en/latest/
http://django-allauth.readthedocs.org/en/latest/
The problem which you are facing is , that u want the login and logout to work from other pages also, So, for this you need not to go for any extra function. All you need to do is, u just extend your base.html to all other html pages. Then you will surely be able to login and logout from all the pages.
Suppose you have login/logout in base.html
<label class="form_login">pseudo :</label>
<input type="text" name="username" id="id_username" class="login_input">
<label class="form_login">mot de passe : </label>
<input type="text" name="password" id="id_password" class="login_input">
<input value="login" type="submit"/>
<button>logout</button>
Now make some other html say test.html
There at the beginning you write
{% extends 'base.html' %}
followed by your HTML markup.
Don't forget to use
{% block content %} {% endblock %} **template tags**
In base as well as other HTML pages.
In other pages u try to write the complete code in template tags.
For query https://docs.djangoproject.com/en/1.7/topics/templates/
Also try using the concept of decorator.

Proper way to handle multiple Django forms in one page with two views?

I've struggled with this problem for the last two days and could use some help. The home page for my Django 1.6 application will include two forms, one that a user can use to sign in to the site and one they can use to sign up (create a login) for the site:
# templates/home/home_page.html
<div class="sign-in-form">
<form action="{% url 'apps.home.views.sign_in' %}" method="post">
{% csrf_token %}
{{ sign_in_form.as_p }}
{% if next %}
<input type="hidden" name="next" value="{{ next }}">
{% else %}
<input type="hidden" name="next" value="{% url 'view-members' %}">
{% endif %}
<input type="submit" value="Sign in">
</form>
</div>
<div class="sign-up-form">
<fieldset>
<legend>Sign up</legend>
<form action="{% url 'apps.home.views.sign_up' %}" method="post">
{% csrf_token %}
{{ sign_up_form.as_p}}
<p><input type="submit" value="Sign up" /></p>
</form>
</fieldset>
</div>
If the user submits, the sign_in form, they'll be taken to a page where they can view other site members. If they submit the sign_up form, they'll be taken to a second signup page where they'll create a user profile, etc.
Originally, I was going to use the technique shown in this question and use one view to handle the homepage. However, I decided to try to use two views because I'm using the Django's actual login view (django.contrib.auth.views.login) so that I can add code to it to detect the user's device (phone, tablet, or computer), and merging that view with my sign_up view would create a very long and complicated view to maintain. I'd prefer to keep the views for both forms separate.
Here's the home page and sign_in views:
# apps/home/views:
def home_page(request, template):
sign_in_form = SignInAuthenticationForm()
sign_up_form = CreateAccountForm()
return render(request, template, {"sign_in_form": sign_in_form,
"sign_up_form": sign_up_form})
#sensitive_post_parameters()
#csrf_protect
#never_cache
def sign_in(request,
template='home_page.html',
redirect_field_name=REDIRECT_FIELD_NAME,
# authentication_form=AuthenticationForm,
authentication_form=SignInAuthenticationForm,
current_app=None, extra_context=None):
# Do device detection here...
# django.contrib.auth.views code goes here...
return response
The signup view will just be your typical, function-based view for processing a form as described in the Django documentation.
What I'm struggling with is my URLconf files. Here's my main and "home" URLconf files:
# conf/urls.py
urlpatterns = patterns('',
url(r'^$', include('apps.home.urls')),
# Other url patterns...
)
# apps/home/urls.py
urlpatterns = patterns('apps.home.views',
url(r'^$',
'home_page',
{'template': 'home/home_page.html'},
name='home-page'),
url(r'^sign_in/$',
'sign_in',
{'template': 'home/home_page.html'},
name='sign-in'),
url(r'^sign_up/$',
'sign_up',
{'template': 'home/home_page.html'},
name='sign-up'),
)
The problem is that I get this error during template rendering:
NoReverseMatch at /
Reverse for 'apps.home.views.sign_in' with arguments '()' and keyword arguments '{}' not found. 1 pattern(s) tried: ['$sign_in/$']
Request Method: GET
Request URL: http://localhost:8000/
Django Version: 1.6.2
Exception Type: NoReverseMatch
Exception Value:
Reverse for 'apps.home.views.sign_in' with arguments '()' and keyword arguments '{}' not found. 1 pattern(s) tried: ['$sign_in/$']
Exception Location: /Users/smith/venv/swing/lib/python2.7/site-packages/django/core/urlresolvers.py in _reverse_with_prefix, line 429
Python Executable: /Users/smith/venv/swing/bin/python
Python Version: 2.7.5
Python Path:
['/Users/smith/Dropbox/www/swing',
'/Users/smith/venv/swing/lib/python2.7/site-packages/wurfl_cloud-1.0.1-py2.7.egg',
'/Users/smith/venv/swing/lib/python27.zip',
'/Users/smith/venv/swing/lib/python2.7',
'/Users/smith/venv/swing/lib/python2.7/plat-darwin',
'/Users/smith/venv/swing/lib/python2.7/plat-mac',
'/Users/smith/venv/swing/lib/python2.7/plat-mac/lib-scriptpackages',
'/Users/smith/venv/swing/Extras/lib/python',
'/Users/smith/venv/swing/lib/python2.7/lib-tk',
'/Users/smith/venv/swing/lib/python2.7/lib-old',
'/Users/smith/venv/swing/lib/python2.7/lib-dynload',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-darwin',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac',
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages',
'/Users/smith/venv/swing/lib/python2.7/site-packages']
At first I started to think that maybe it's telling me that it can's find the correct URL pattern in my home/urls.py file because the URL signature in my form is incorrect. Maybe I needed to do this to match the arguments in the sign_in view:
<form action="{% url 'apps.home.views.sign_in' 'home/home_page.html' %}" method="post">
But I'm already showing the template name in the home URLconf. And I don't think I need to pass the other view arguments in the form action (e.g. redirect_field_name) because their optional. In any case, adding this argument to the form action didn't fix it.
One of the things that confuses me is how to set the first url argument. I've set them to r'^sign_in/$' and r'^sign_up/$' because if I set them both to r'^$', the page will render properly but when I submit either form, it justs posts back to the home page. You can see this will happen by doing a "view source" on the page. It shows each form's action will be "/". On the other hand, the way I have it now seems incorrect to me because the site won't actually have a "/sign_in/" and "/sign_up/" URL since both forms are on the home page. Also, is there going to be a problem in which if the user submits one for or the other improperly, errors for both forms will be rendered on the page?
The Django documentation, to the best of my knowledge, doesn't really describe a standard approach for doing what I'm trying to do. It describes how to render multiple versions of the same form. Can anyone tell me what I'm doing wrong?
Thanks.
Your form names are 'sign_in_form' and 'sign_up_form', but in your html you wrote them 'form.as_p' instead of 'sign_in_form.as_p' and 'sign_up_form.as_p' this is the first bug a saw in your code.
The real problem is in your urls configuration. In your main urls.py you have
url(r'^$', include('apps.home.urls')),
Other ...
Though you will not be able to get to localhost:8000/sign_in/ because initially it does not satisfy to ^$ .
Try to change it by
url(r'', include('apps.home.urls')),
and put it to the end of urls.py.
i test this see if this what you want:
view.py
def loginUser(request,**Kargs):
LoginFormSet = formset_factory(LoginForm)
SignFormSet = formset_factory(SignForm)
if request.method == 'POST':
login_formset = LoginFormSet(request.POST, prefix='login')
sign_formset = SignFormSet(request.POST ,prefix='sign')
if login_formset.is_valid():
#do somthing
elif sign_formset.is_valid():
#do somthing
return render(request, 'reservetion/login.html',{'login_formset': login_formset,'sign_formset':sign_formset})
else:
login_formset = LoginFormSet(prefix='login')
sign_formset = SignFormSet(prefix='sign')
return render(request, 'reservetion/login.html',{'login_formset': login_formset,'sign_formset':sign_formset})
page.html:
<form action="{% url 'loginUser' %}" method="post">
{% csrf_token %}
{{ login_formset.management_form }}
{% for form in login_formset %}
{{ form }}
{% endfor %}
{{ sign_formset.management_form }}
{% for form in sign_formset %}
{{ form }}
{% endfor %}

Django Forms to values of html <input> field

I am trying to access the values of a Bootstrap btn-group from Django and from the documentation I have found, it seems that you should use Forms in Django for such tasks.
This is what the html looks like, right now:
<div class="col-md-6">
{% for metric in metrics %}
<input name="{{ metric.name }}" type="hidden" value="0"/>
{% endfor %}
<div class="btn-group" data-toggle="buttons">
{% for metric in metrics %}
<button type="button" class="btn btn-default" data-checkbox-name="{{ metric.name }}">{{ metric.name }}</button>
{% endfor %}
</div>
</div>
How can I use forms to get the values of the input fields?
Here it is a basic example about using a form in django
views.py:
#login_required
def your_view(request): # Add this code into your view
if request.method == 'POST':
# So here you can do a loop over POST fields like this
data_list = [] # We will insert all the inputs in this array
for key in request.POST:
data_list.append(request.POST[key])
# Here you can manage the the data_list and do whatever you need
# The content of the data_list depend on your inputs
# It could be string, integer....
# YOUR VIEW CODE
template (form example):
<form action="." method="post" id="add_user_form">
{% csrf_token %}
{% for metric in metrics %}
<input type="text" name="{{ metric.name }}" placeholder="whatever you want">
{% endfor %}
<input type="submit" value="submit" class="default"/> # Submit button
</form>
{% csrf_token %} : You need to put this in every form you use
action="." : This make the post to the actual page
But anyway I strongly recommend you to check this Django Forms Documentation to unterstand better the logic, and also check the ModelForms because can save you a lot of time when you need to make a form for a model that exists in your Django Models
You are'n forced to use django forms, this is just a way to get a sort of organization.
in you views toy can get the values sent to the server by using request.GET or request.POST, depending of the method of the form.
to get a list of values you have received just do a
print request.POST
request.POST is a dictionary, so you can get any value fron them by its key:
print request.POST['<key>']