I have a simple form in my template, index.html:
{% if stripped_thumbnail_file_list %}
{% for thumbnail_name in stripped_thumbnail_file_list %}
<div class="">
<div class="">
This is my form
<form class="" action="{% url 'index' %}" method="post">
{% csrf_token %}
<input type="image" value="{{ thumbnail_name }}" src="{{ MEDIA_URL}}thumbnails/{{ thumbnail_name }}.jpg">
</form>
</div>
</div>
{% endfor %}
{% else %}
<p>No videos are available.</p>
{% endif %}
I want the index view to pull the {{ thumbnail_name }} value from this form and use it as a variable when the index view redirects to a different view that will use that name to play a matching video.
I have been unsuccessful in trying to pull that value from the form as I have it. I suspect this may because I'm not creating a Django form object. I tried to create that object, but I can't find any examples of a Django form object as an image like I have in my form.
What should that look like? Or, can someone make a recommendation on how to pull the value from the form as is?
EDIT: adding views.py snippet:
def index(request):
# if this is a POST request we need to process the form data
if request.POST:
# get thumbnail_name from form
# redirect to a new URL (hardcode thumbnail name for now):
return HttpResponseRedirect('2017-02-01_04-29-10/video/')
thumbnail_file_list = get_file_list(target_directory, ".jpg")
stripped_thumbnail_file_list = strip_file_extension(thumbnail_file_list)
template = loader.get_template('dash/index.html')
context = {
'stripped_thumbnail_file_list': stripped_thumbnail_file_list,
}
return HttpResponse(template.render(context, request))
def video(request, file_name):
print("this is the file name passed: " + file_name)
template = loader.get_template('dash/video.html')
context = {
'file_name': file_name,
}
return HttpResponse(template.render(context, request))
First: you need to declare the 'name' attribute on your form imput.
<input name="thumbnail_name" type="image" value="{{ thumbnail_name }}" src="{{ MEDIA_URL}}thumbnails/{{ thumbnail_name }}.jpg">
Second: Why don't you just set the 'action' of the form to your 'video' function (when you perform a redirect, you are losing all your POST data).Then, from there you could retrieve the value: something like that
def video(request):
file_name = request.POST.get('thumbnail_name')
print("this is the file name passed: " + file_name)
template = loader.get_template('dash/video.html')
context = {
'file_name': file_name,
}
return HttpResponse(template.render(context, request))
Hope it helps
Related
My path looks like so:
path('edit/<str:entry_name>/', views.edit, name='edit').
I want to access this path through a form like so:
<form action="{% url 'edit' entry_name=entry_title %}" method="get">
{% csrf_token %}
<input type="hidden" name="title" value="{{ entry_title }}">
<input type="hidden" name="content" value="{{ entry_content }}">
<input type="submit" value="Edit">
</form>
But then I get this error: Reverse for 'edit' with keyword arguments '{'entry_name': ''}' not found. 1 pattern(s) tried: ['edit/(?P<entry_name>[^/]+)/\\Z'].
It seems like entry_name is empty, but I use the entry_name parameter elsewhere on the page and it works fine.
{% block title %}
{{ entry_title }}
{% endblock title %}
is not empty, since I can see the titel on the tab-title.
EDIT:
Here are the views:
To access the entry page where the form is located:
def entry(request, title):
entry = util.get_entry(title)
if entry is None:
return render(request, "encyclopedia/error.html", {
"error_name": "Not Found",
"error_message": f"{title} page Not Found"
})
return render(request, "encyclopedia/entry.html", {
"entry_title": title,
"entry_content": markdown2.markdown(entry)
})
The edit view:
def edit(request, entry_name):
if request.method == "POST":
query_dict = request.POST
new_entry_name = entry_name
content = query_dict.get("content")
util.save_entry(new_entry_name, content)
entry = util.get_entry(new_entry_name)
if entry is not None:
return HttpResponseRedirect(f"/wiki/{new_entry_name}/")
else:
return HttpResponse("Oop something went wrong there")
return render(request, "encyclopedia/entry.html", {
"error": "",
"title": entry_name,
"content": request.GET.get("content")
})
You can try to change your form action bcs i`ve never seen someone doing '=' while giving an id or slug in action
try this:
<form action="{% url 'edit' entry_title %}" method="get">
And btw can you add your models and views.py for better understanding
I have a Django form that receives a text (that I copy from Google Classroom: a bunch of student comments). I use these comments to make student's attendance. What I want to achieve is:
Accessing /insertion/ url via GET user receive the page form as a response, to choose the class (class01, class02, etc) and to past the text
When the user clicks on submit in this form (post method), it is redirect to the same /insertion/ url, but now the form is bound to the data submited, and the page shows a preview page (based on a boolean variable I'm passing through context), showing what students are present and what are absent based on the text informed. At that page, a new submit button will be shown below a text like "if everything's ok, hit the ok button".
After click this ok button, a pdf will be generated and the user will be redirected to /files/ url, to see the generated pdf and previous generated pdf.
views.py
def insertion(request):
context = {}
if request.method == 'GET':
form = AttendanceDataForm()
context.update({"form": form})
if request.method == 'POST':
form = AttendanceDataForm(request.POST)
context.update({"form": form})
if form.is_valid():
lesson = form.cleaned_data['lesson']
raw_text = form.cleaned_data['raw_text']
# Get course students
course_students = md.Student.objects.filter(course_id=lesson.course_id)
# Get present students based on raw text informed
present_students = [s for s in course_students if s.full_name in raw_text]
# Get absent students based on raw text informed
absent_students = [s for s in course_students if s.full_name not in raw_text]
context.update({
"present_students": present_students,
"absent_students": absent_students,
"render_preview": True
})
context.update({"active_freq": True})
return render(request, 'core/insertion.html', context)
def files(request):
context = {}
if request.method == 'POST':
# How can I access all expensive calculation I did in the previous view?
context.update({"active_gen": True})
return render(request, "core/files.html", context)
insertion.html
<div class="row">
<div class="col-12 col-md-6">
<h3>Informar Frequência</h3>
{% crispy form %}
</div>
<div class="col-12 col-md-6">
{% if render_preview %}
<div class="container">
<div class="row p-4 bg-white rounded mt-4">
<div class="col-12 col-sm-6">
<h5>Alunos presentes</h5>
<ul class="previewer-list">
{% for student in present_students %}
<li>{{ student.id }} - {{ student.full_name }}</li>
{% endfor %}
</ul>
</div>
<div class="col-12 col-sm-6">
<h5>Alunos ausentes</h5>
<ul class="previewer-list">
{% for student in absent_students %}
<li>{{ student.id }} - {{ student.full_name }}</li>
{% endfor %}
</ul>
</div>
</div>
<p class="mt-3">If everything's ok, hit the OK button</p>
<form method="post" action="{% url "core:files" %}">
{% csrf_token %}
<button type="submit" class="btn btn-primary">OK</button>
</form>
</div>
{% endif %}
</div>
</div>
I could get to implement 1 and 2, but 3 is a mistery right now. What I couldn't get is how I can access the expensive calculations I did in insertion view in the files view. How can I do that?
Here's a solution using session framework.
We'll save the calculations in the session and access those values in another view later.
For starters, we'll just save the ids (pk) of the students instead of the student instances because they are not JSON serializable [See note below].
def insertion(request):
# do expensive calucations ...
present_ids = [s.pk for s in present_students]
absent_ids = [s.pk for s in absent_students]
request.session['attendance_data'] = {
'present_ids': present_ids,
'absent_ids': absent_ids
}
def files(request):
attendance_data = request.session.get('attendance_data')
if not attendance_data:
# show error or something else ...
pass
present_students = md.Student.objects.filter(
pk__in=attendance_data['present_ids']
)
absent_students = md.Student.objects.filter(
pk__in=attendance_data['absent_ids']
)
# generate the pdf ...
Note: If you wish, you can also save the student instances in the session but you'll have to change the SESSION_SERIALIZER setting to use the PickleSerializer. See notes about session serialization.
You could submit the primary keys as form data in hidden fields. Just choose an appropriate delimiter based on your primary key (for example, don't delimit with a hyphen if you use a GUID primary key).
<form method="post" action="{% url "core:files" %}">
{% csrf_token %}
<input type="hidden"
name="present"
value="{% for s in present_students %}{{ s.pk }},{% endfor %}"
>
<input type="hidden"
name="absent"
value="{% for s in absent_students %}{{ s.pk }},{% endfor %}"
>
<button type="submit" class="btn btn-primary">OK</button>
</form>
Then in the view you can pick up the PKs in the view from the form data then request.
def files(request):
context = {}
if request.method == 'POST':
present_pks = request.POST.pop('present').split(',')[:-1]
absent_pks = request.POST.pop('absent').split(',')[:-1]
# do type conversions if needed
...
# Because we already have the pks separated, we can combine them
# for the query in order to do just 1 query
course_students = md.Student.objects.filter(pk__in=present_pks + absent_pks).all()
absent_students = []
present_students = []
for student in course_students:
if student.pk in absent_pks:
absent_students.append(student)
else:
present_students.append(student)
I've been coding in the framework django for two weeks and now I am learning to delete products.
Here's the html code I've done:
{% extends 'base.html' %}
{% block content %}
<form action = '.' method= 'POST'> {% csrf_token %}
<h1>Do you want to delete the product "{{ object.title }}"?</h1>
<p><input type= 'submit' value = 'Yes' /> <a href='../'>Cancel</a></p>
</form>
{% endblock %}
And the function I've coded to delete the product
def product_delete_view(request, my_id):
obj = get_object_or_404(Product, id = my_id)
if request.method == "POST":
obj.delete()
context = {
'object': obj
}
return render(request,"products/product_delete.html", context)
Here's my url path:
path('products/<int:my_id>/delete', product_delete_view, name= 'product-delete')
However, my product doesn't get deleted.
Try redirecting somewhere after the deletion is complete, as the delete command deletes it from the database but if their as an instance in python live it will stay on until the page is either reloaded or left.
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)
I'm trying to set up a user profile where you can enter skills. Entering the skills and save them in the databse already works. Now I want to give the user the opportunity to delete every single one of them with a button click. I tried posting the ID of each skill on button click in the URL and read it out in my view to get the item and delete it, but that does not work like I thought and I cant find out why...
MY VIEW
def profile_settings(request, id=None):
# get logged in user object from session
user_id = request.user.id
# get related userprofile
userprofile = UserProfile.objects.get(pk=user_id)
# get all skills of the userprofile
user_skills = Skill.objects.filter(user=userprofile)
if request.method == 'POST':
form = SkillForm(request.POST)
if 'delete-skill' in request.POST:
if id:
print(id)
skill = Skill.objects.get(pk=id).delete()
elif 'add-skill' in request.POST:
if form.is_valid():
# get data from form
name = form.cleaned_data['name']
category = form.cleaned_data['category']
rating = form.cleaned_data['rating']
# create new skill object for a user
new_skill = Skill(name=name, category=category, rating=rating, user=userprofile)
# save it in the database
new_skill.save()
else:
form = SkillForm()
return render(request, 'profile-settings.html', {'skillform': form, 'existing_skills': user_skills})
MY URLS
urlpatterns = [
url(r'^landing', views.landing, name='landing'),
url(r'^neuigkeiten', views.news, name='news'),
url(r'^profileinstellungen/', views.profile_settings, name='profileinstellungen'),
url(r'^profileinstellungen/(?P<id>\d+)/$', views.profile_settings, name='profileinstellungen'),
]
MY TEMPLATE
{% extends 'base.html' %}
{% block content %}
<form method="post" style="margin-top: 300px">
{% csrf_token %}
{{ skillform }}
<input type="submit" value="Hinzufügen" name="add-skill "/>
</form>
<form method="post">
{% csrf_token %}
<ul>
{% for skill in existing_skills %}
<li>{{ skill.name }}</li>
<input href="{% url 'profileinstellungen' id=skill.id%}" type="submit" value="Löschen" name="delete-skill"/>
{% endfor %}
</ul>
</form>
{% endblock %}
It does not post the ID of the skill in the URL. Is there an alternative approach?
Try to change this :
<input href="{% url 'profileinstellungen' id=skill.id%}" type="submit" value="Löschen" name="delete-skill"/>
by this :
<input href="{% url 'profileinstellungen' %}{{skill.id}}" type="submit" value="Löschen" name="delete-skill"/>
because the "url" will know automatically that "skill.id" was related to "id"
You have forgotten to include dollar signs at the end of the regexes in your URL patterns. It should be:
urlpatterns = [
url(r'^landing$', views.landing, name='landing'),
url(r'^neuigkeiten$', views.news, name='news'),
url(r'^profileinstellungen/$', views.profile_settings, name='profileinstellungen'),
url(r'^profileinstellungen/(?P<id>\d+)/$', views.profile_settings, name='profileinstellungen'),
]
In particular, the problem is the regex r'^profileinstellungen/. Without the dollar, it matches URLs like /profileinstellungen/4/, so the id is not passed to the view.
Secondly, it doesn't make sense to give the input an href attribute. Each input should be in a separate form, and you can set the form action to the URL you wish to submit the post request to.
<ul>
{% for skill in existing_skills %}
<form method="post" action="{% url 'profileinstellungen' id=skill.id%}">
{% csrf_token %}
<li>
{{ skill.name }}
<input type="submit" value="Löschen" name="delete-skill"/>
</li>
</form>
{% endfor %}
</ul>