How can i submit data in django? - python

I want to have 3 pages. The one displays certain usernames of a certain directory which is called "static" (you will see it in my views.py). And if the user wants to add a user, he presses on one of the 2 "Add" buttons.. if he does that he is getting to the second page where he can type in username and password and can confirm it with the "Submit" button. Then the data should be saved in the "static" folder. After that he is getting directed to another site where it says "registration successful" and after 3 seconds he is getting back to the index.html to see the results. In the django documentation, I think they do almost the same just in another way xP https://docs.djangoproject.com/en/1.5/intro/tutorial04/ I just don't get how I can assign their example to my project :/
Her are my views:
from django.shortcuts import render
import os
def index(request):
os.chdir("/home/ubuntu/newproject/static")
files = []
for file in os.listdir("."):
files.append(file)
return render(request, 'sslcert/index.html', dict(files = files))
def adduser(request):
return render(request, 'sslcert/adduser.html')
def redirect(request):
return render(request, 'sslcert/redirect.html')
This is the template for the first website:
<head>
{% block title %}
<h3>
Following users exist in the folder 'static' :
</h3>
{% endblock %}
</head>
<body>
<table border = "0" width = "100%" align = "left">
<tr>
<td align = "right">
<form action = "adduser.html" method = "post">{% csrf_token %}
<input type = "submit" name = "form" style = "width:8%" value = "Add">
</td>
</tr>
{% for file in files %}
<tr>
<td align = "left"> {{ file }} </td>
</tr>
{% endfor %}
<tr>
<td align = "right">
<form action = "adduser.html" method = "post">{% csrf_token %}
<input type = "submit" name = "form" style = "width:8%" value = "Add">
</form>
</td>
</tr>
</table>
</body>
And this is the template for my second website:
<head>
{% block title %}
<h2 align = "middle" >
<u>Add a user</u>
</h2>
{% endblock %}
</head>
<body>
<table border = "0" width = "100%">
<tr>
<td>
<p>Username:</p>
<input type = "text" name = "" value = "" />
</td>
</tr>
<tr>
<td>
<p>Password:</p>
<input type = "password" name = "" value = "" />
</td>
</tr>
<tr>
<td>
<form action = {% url 'sslcert:redirect' %} method = "post"> {%csrf_token %}
<input type = "submit" value = "Submit">
</form>
</td>
</tr>
</table>
</body>
And this is the template for the redirect site:
<head>
<meta http-equiv = "refresh" content = "3; URL=http://10.0.3.79:8000/sslcert/">
{% block title %}
<h4>
Registration successful !
</h4>
{% endblock %}
</head>
I read the documentation and I found this code example:
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
from polls.models import Choice, Question
# ...
def vote(request, question_id):
p = get_object_or_404(Question, pk=question_id)
try:
selected_choice = p.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
# Redisplay the question voting form.
return render(request, 'polls/detail.html', {
'question': p,
'error_message': "You didn't select a choice.",
})
else:
selected_choice.votes += 1
selected_choice.save()
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse('polls:results', args=(p.id,)))
I thought that this Line might be helpful:
try:
selected_choice = p.choice_set.get(pk=request.POST['choice'])
but I really don't know how to assign this to my project :/ I already created 2 classes in the models with the names: "Username" and "Password". Please guys help me out :(
Help is much appreciated :)

Well, when the browser first gets the form to fill up, you're sending a GET request. Otherwise, if you send information to the server, you need to send a POST request. Take a look at the documentation.

Okay I found the answer myself ... It is frustrating that I wasted so much time on this but I was kind of blind xP in my adduser.html (the second page) I had my just around the submit button ... the only thing that got submitted was the csrf_token. Now it looks like this and it submits the Username and the Password as well:
<!DOCTYPE html>
<html>
<head>
{% block title %}
<h2 align = "middle" >
<u>Add a user</u>
</h2>
{% endblock %}
</head>
<body>
<form action = "{% url 'sslcert:redirect' %}" method = "post">{% csrf_token %}
<table border = "0" width = "100%">
<tr>
<td>
<p>Username:</p>
<input type = "text" name = "username" value = "" />
</td>
</tr>
<tr>
<td>
<p>Password:</p>
<input type = "password" name = "password" value = "" />
</td>
</tr>
<tr>
<td>
<input type = "submit" value = "Submit">
</td>
</tr>
</table>
</form>
</body>
</html>
And I changed my views.py like this:
from django.shortcuts import render
import os
def index(request):
os.chdir("/home/ubuntu/newproject/static")
files = []
for file in os.listdir("."):
files.append(file)
return render(request, 'sslcert/index.html', dict(files = files))
def adduser(request):
return render(request, 'sslcert/adduser.html')
def redirect(request):
username = request.POST['username']
password = request.POST['password']
print username
print password
return render(request, 'sslcert/redirect.html')

Related

why am I receiving this error == Reverse for 'download_done' not found. 'download_done' is not a valid view function or pattern name

I'm trying to create a youtube downloader but when I'm trying to download it gives this error
Reverse for 'download_done' not found. 'download_done' is not a valid view function or pattern name.
I have compared the app name and its corresponding, I have also checked the HTML file it looks okay
views.py
from django.shortcuts import render
from pytube import YouTube
import os
# Create your views here.
def youtubedownloader(request):
return render(request, 'youtube_downloader.html')
def download(request):
global url
url = request.GET.get('url')
yt = YouTube(url)
video = []
video = yt.streams.filter(progressive=True).all()
embed_link = url.replace("watch?v=", "embed/")
Title = yt.title
context = {'video': video, 'embed': embed_link, 'title': Title}
return render(request, 'download.html', context)
def download_done(request, resolution):
global url
homedir = os.path.expanduser("~")
dirs = homedir + '/Downloads'
if request.method == "POST":
YouTube(url).streams.get_by_resolution(resolution).download(dirs)
return render(request, 'download_done.html')
else:
return render(request, 'errorrrr.html')
urls.py
from django.contrib import admin
from django.urls import path
from .views import youtubedownloader, download, download_done
app_name = 'yt_downloader'
urlpatterns = [
path('youtube_downloader/', youtubedownloader, name='youtube downloader'),
path('youtube_downloader/download/', download, name='download video'),
path('download/<resolution>/', download_done, name='download done')
]
download.html
{% extends 'base.html' %}
{% block content %}
<div class="container">
<h1> Title : {{title}} </h1>
<div class=" mt-5 embed-responsive embed-responsive-16by9">
<iframe class="embed-responsive-item" src={{embed}} allowfullscreen></iframe>
</div>
<table class="table">
<thead class="thead-light">
<tr>
<th scope="col">Size</th>
<th scope="col">Type</th>
<th scope="col">Quality</th>
<th scope="col">Download</th>
</tr>
</thead>
{% for j in video %}
<tbody>
<tr>
<th> {{j.filesize}}</th>
<td>{{j.type}}</td>
<td>{{j.resolution}}</td>
<td><form action="{% url 'yt_downloader:download_done' j.resolution %}" method="post">
{% csrf_token %}
<input type="submit" class="btn btn-success" value="Download">
</form>
</tr>
</tbody>
{% endfor %}
</table>
</div>
{% endblock content %}
You have to change the url path name to download_done, like the following:
urlpatterns = [
path('youtube_downloader/', youtubedownloader, name='youtube_downloader'),
path('youtube_downloader/download/', download, name='download_video'),
path('download/<resolution>/', download_done, name='download_done')
]

.getlist() is not returning anything in django / html form checkbox input

I have a 2 forms within my list view for a model. The first one is a search bar which works fine with GET and the next is to select items displayed and collect them to edit. I haven't gotten to the editing because I cannot get a list of the selected objects.
View.py
#login_required
def ex_list(request):
context = {}
if request.GET:
#code for search bar
if request.POST:
selected_values = request.POST.getlist('exlist[]')
print(selected_values)
return render(
request,
'ex/list.html',
context
)
List.html
<form method="POST" action="">
{% csrf_token %}
<table id="exs" class="table table-hover table-striped">
<tbody>
{% for ex in exs %}
<tr>
<td>
<center><input type="checkbox" name="exlist[]" value="{{ex.esid}}"/></center>
</td>
{% endfor %}
<input type="submit" class="btn btn-primary" value="Edit Selected Items" name="edit">
</form>
Although I have print(selected_values), all that is being returned is empty brackets {}. I at least know that we are getting inside of the if statement.
Firstly, in your list.html you haven't specified action and just left it blank
change it to
<form method = "post" action = "{% url 'ex_list' %}">
...
</form>
Also, you are passing empty context to the rendering template that's why you are getting {}
change it to
context = {
"selected_values" = selected_values,
}
return render(request, "...", context)

combine django-filter DateTimeFromToRangeFilter and DateTimeInput(datepicker)

Using django_filter and datetimeinput as a datepicker, I am trying to add a date and time input, a FROM, and TO fields.
I have only been able to use a dateinput with just one field from django forms or from django filter DateTimeFromToRangeFilter without the date picker showing (just manual text entry).
Here is my filter_model.py for the one field with a date picker.
from app.models.api_status import ApiStatus
import django_filters
from django import forms
class DateTimeInput(forms.DateTimeInput):
input_type = 'date'
# working solution for just 1 date field
class ApiStatusFilter(django_filters.FilterSet):
date_time = django_filters.DateFilter(
label=('With start date'),
lookup_expr=('icontains'), # use contains,
widget=DateTimeInput()
)
class Meta:
model = ApiStatus
fields = ['id', 'date_time']
Picture shows a clickable date picker popup.
Here is my filter_model.py for the two fields, FROM and TO without a date picker.
from app.models.api_status import ApiStatus
import django_filters
from django import forms
class DateTimeInput(forms.DateTimeInput):
input_type = 'date'
class ApiStatusFilter(django_filters.FilterSet):
date_time =django_filters.DateTimeFromToRangeFilter()
class Meta:
model = ApiStatus
fields = ['id', 'date_time']
widgets = {
'date_time': forms.DateTimeInput(attrs={'placeholder':'Select a date'})
}
Picture below shows a manual text input without a datepicker popup.
Here is my template file although I didn't alter it much when trying the two approaches above.
status_template.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href="{% static 'css/table_styling.css' %}">
<meta charset="UTF-8">
<title>Test Site</title>
{% comment %}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/resources/demos/style.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
{% endcomment %}
</head>
<body>
<table>
<thead>
<tr>
{% for keys in dictionarys.keys %}
<th>{{ keys }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
<form method="get">
{{ apistatus_filter.form.as_p }}
<button type="submit">Search</button>
{% for user in dataqs.object_list %}
<tr>
<td>{{ user.id }}</td>
<td>{{ user.date_time }}</td>
{% endfor %}
</form>
</tbody>
</table>
{% comment %} <script>
$( function() {
$("#datepicker").datepicker();
} );
</script> {% endcomment %}
</body>
</html>
I did look into a variety of sources on here and elsewhere. I tried using MultiWidget and jQuery but didn't get those working yet. Thoughts? Thanks in advance.
It's possible to use javascript to make the range fields have a datepicker class.
I was struggling to get a jQuery datepicker to work with the DateTimeFromToRangeFilter from Django Filters combined with the RangeWidget. For some reason it seems like the RangeWidget won't accept class: datepicker.
Filters.py:
dtoriginal = django_filters.DateTimeFromToRangeFilter(lookup_expr='icontains',
widget=django_filters.widgets.RangeWidget(
attrs={
'placeholder': 'yyyy-mm-dd',
},
),
label = 'Date Original'
)
I changed my search template html to include the following script:
<form method="get">
{{ filter.form.as_p }}
<script>
$(function () {
$("id_dtoriginal_0").datepicker();
$("id_dtoriginal_1").datepicker();
});
</script>
{% if filter.is_bound %}
<button onclick=...></button
{% endif %}
</form>
Where dtoriginal is the name of the field in the model. _0 and _1 are the "from" and "to" fields created by RangeWidget.
Hopefully this helps, I spent hours trying to figure it out how to do it through django-filters, with no luck.
I was able to solve it using no external dependencies (no jquery), just used datetime-local input and DateTimeFromToRangeFilter with Range widget. Perhaps not the most ideal solution, but it is one way to do this.
My model, filter, view, and template codes are below.
model.py
from app.modules.string_handler import StringHandler
from django.db.models.signals import post_save
import datetime
class ApiStatus(models.Model):
id = models.AutoField(primary_key=True)
date_time = models.DateTimeField("Date_Time", default=datetime.datetime.now(), blank=True)
class Meta:
managed = True
db_table = 'api_status'
verbose_name = 'API STATUS'
def __str__(self):
"A string representation of the model."
return f'{self.id},{self.token},{self.date_time},{self.status},{self.summary},{self.log}'
def __unicode__(self):
return self.created_at
filter.py
from app.models.api_status import ApiStatus
import django_filters
from django import forms
class ApiStatusFilter(django_filters.FilterSet):
date_time = django_filters.DateTimeFromToRangeFilter(
lookup_expr=('icontains'),
widget=django_filters.widgets.RangeWidget(
attrs={'type':'datetime-local'}
)
)
class Meta:
model = ApiStatus
fields = ['id', 'date_time']
view.py
from django.shortcuts import render
from app.models.filters_model import ApiStatusFilter
from app.models.api_status import ApiStatus
import requests
from django import forms
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
import urllib
from datetime import datetime, timedelta
def status(request):
apistatus_list = ApiStatus.objects.all()
request.GET2 = request.GET.copy()
if request.GET2.get('date_time_min'):
request.GET2['date_time_min'] = datetime.strptime(request.GET2['date_time_min'],"%Y-%m-%dT%H:%M").strftime("%Y-%m-%d %H:%M")
if request.GET2.get('date_time_max'):
request.GET2['date_time_max'] = datetime.strptime(request.GET2['date_time_max'],"%Y-%m-%dT%H:%M").strftime("%Y-%m-%d %H:%M")
apistatus_filter = ApiStatusFilter(request.GET2, queryset=apistatus_list)
paginator = Paginator(apistatus_filter.qs, 10)
page = request.GET.get('page')
try:
dataqs = paginator.page(page)
except PageNotAnInteger:
dataqs = paginator.page(1)
except EmptyPage:
dataqs = paginator.page(paginator.num_pages)
return render(request, 'status_page_template.html', {'table_col_DATA':all_entries_ordered, 'dictionarys': dictionarys, 'apistatus_filter': apistatus_filter, 'dataqs': dataqs, 'allobjects': apistatus_list})
template.html
{% load my_templatetags %}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" type="text/css" href="{% static 'css/search_form_table_styling.css' %}">
<meta charset="UTF-8">
<title>TEST Site</title>
</head>
<body>
<form method="get" action="">
<div class="search_form_wrapper">
<div class="id_box">ID:{{ apistatus_filter.form.id }}</div>
<div class="id_box">Date_Time:{{ apistatus_filter.form.date_time }}</div>
</div>
<input type="submit" value="Submit" class="search_form_submit">
</form>
<table>
<tbody>
{% for user in dataqs.object_list %}
<tr>
<td>{{ user.id }}</td>
<td>{{ user.date_time }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pagination">
<span>
{% if dataqs.has_previous %}
« first
previous
{% endif %}
<span class="current">
Page {{ dataqs.number }} of {{ dataqs.paginator.num_pages }}.
</span>
{% if dataqs.has_next %}
next
last »
{% endif %}
</span>
</div>
</body>
</html>

Getting Data From the Request Object using Django webframework for MySQL

Hello experts,
I am new in django and trying to learn how to build django web-framework for MySQL database.I can post my query (search term) and get desired results. But I am trying to modify my project so user can submit query in submission page and see their query parameter in URL when it is executed.
Something like this:
submission page: http://localhost:8000/
and after execution page will be like this:http://localhost:8000/xtrack/?searchid=XXXX
But still now I couldn't figure out how to do it in a right way after spending few days.
forms.py
from django import forms
from models import Query
class SQLForm(forms.ModelForm):
xtrackid=forms.CharField(max_length=100)
def checkxID(self):
xtrackid=self.cleaned_data.get("xtrackid")
return xtrackid
class QueryForm(forms.ModelForm):
class Meta:
model=Query
fields=["xtrackid"]
views.py
from django.shortcuts import render
from django.http import HttpResponse
from forms import SQLForm, QueryForm
import sys
def search_form(request):
return render(request, 'index.html')
def search(request):
form = QueryForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
xtrackid = form.cleaned_data.get("xtrackid")
xtrackid =xtrackid.strip()
conn = MySQLdb.connect (host = "localhost", user = "root", passwd = "XXXX", db = "XXXtracker")
cursor = conn.cursor ()
cursor.execute ("SELECT xInfo.xtideID, xIDunID.AccessionNumber FROM xInfo, xIDunID WHERE xInfo.xtideID = xIDunID.xtideID AND xIDunID.xtideID LIKE '%" + xtrackid +"%'")
row = cursor.fetchone ()
listrow= list(row)
contextres={}
if cursor.rowcount==0:
contexterror = {
'outputerror': xtrackid
}
return render(request, 'errorform.html', contexterror)
else:
if contextres.has_key(str(listrow[0])):
contextres[str(listrow[0])].append(listrow[1])
else:
contextres[str(listrow[0])]= [listrow[1]]
resulstdict = {'contextresultinfo': contextres}
return render(request, 'resultform.html', {'xinfo': resulstdict, 'query': xtrackid})
conn.close()
else:
return HttpResponse('Please submit a valid search term.')
urls.py
from django.conf.urls import include, url
from django.contrib import admin
from myapp import views
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^xtrack/$', views.search_form),
url(r'^resultform/$', views.search),
url(r'^errorform/$', views.search)
]
and my templates are like:
index.html
<html>
<h1> Welcome to xTrack </h1>
<head>
<title>Search</title>
</head>
<body>
<form action="/xtrack/" method="get">
<input type="text" name="xtrackid">
<input type="submit" value="Search">
</form>
</body>
</html>
resultform.html
Results
{% if contextresultinfo %}
<table border="1" style="width:100%">
<tr>
<td>xtide tracker ID<br> </td>
<td>Accession number<br></td>
</tr>
{% for key, values in contextresultinfo.items %}
<tr>
{% for items in values %}
<tr>
<td>{{key}}</td>
{% for data in items %}
<td>{{data}}</td>
{% endfor %}
</tr>
{% endfor %}
</tr>
{% endfor %}
</table>
{% else %}
<p>No xtrack matched your search criteria.</p>
{% endif %}
</body>
Can you please give some idea where do I need to change code in my project.
Thanks
in you view, you're getting the submission data through:
form = QueryForm(request.POST or None)
but in you html file, you define your form method as:
<form action="/peptrack/" method="get">
Thus request.POST would't get any data.

Change existing model data with form

I am trying to implement a view that displays a form to capture data and a table with the captured data of a user. The table has a form with two buttons per row, either submitting "change" or "delete" together with the object id of the object in the given table row, using POST.
My Django view looks like this:
def captureData(request):
form = MyForm(request.POST or None)
if request.method == "POST":
if 'delete' in request.POST:
# User hits "Delete" button in displayed objects table.
try:
del_object = MyObject.objects.filter(user = request.user).get(id = request.POST['delete'])
del_object.delete()
except:
# Do something ...
return redirect('captureData')
elif 'change' in request.POST:
# User hits "Change" button in displayed objects table.
ch_object = MyObject.objects.filter(user = request.user).get(id = request.POST['change'])
form = MyForm(instance = ch_object)
if form.is_valid():
form.save()
return redirect('captureData')
else:
# New data to be added to the database.
if form.is_valid():
new_object = form.save(commit = False)
new_object.user = request.user
new_object.save()
return redirect('captureData')
objects = Object.objects.filter(user = request.user)
context = {'form': form, 'objects': objects}
return render(request, 'myTemplate.html', context)
This is how the myTemplate.html looks like:
{% extends "base.html" %}
{% block content %}
<h3>Data capturing</h3>
<p>
<!-- First form, responsible for capturing data -->
<form method="POST" action=""> {% csrf_token %}
{{form}}
<input type ='submit' value='Save'/>
</form>
</p>
<h3>Captured data</h3>
<table>
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Address</th>
<th>City</th>
<th colspan="2">Actions</th>
</tr>
</thead>
<tbody>
{% for object in objects %}
<tr>
<td>{{forloop.counter}}</td>
<td>{{object.name}}</td>
<td>{{object.address}}</td>
<td>{{object.city}}</td>
<!-- Second form (per row), responsible for submitting a "delete" or "change" -->
<form action="" method="POST">{% csrf_token %}
<td>
<button type="submit" value="{{object.id}}" name="change" id="object{{object.id}}">Change</button>
</td>
<td>
<button type="submit" value="{{object.id}}" name="delete" id="object{{object.id}}">Delete</button>
</td>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
The "delete" part works fine. The problem is the "change" part. It successfully populates the form with the selected objects data, but when I hit the capture from submit button it runs into the else: clause resulting in a new data row or an error, if the data already exists. The reason for this is obvious: The new POST data does not contain the "change" marker anymore.
How can I separate the elif: part from the else: part?

Categories