I have made this HTML code:
<h3>your major is {{user.userprofile.major}}</h3>
This will correctly show the major on the webpage, but I want to use this string to get something from another table in view.
How would I pass this string to view?
edit:
Here is my view.py
def dashboardView(request):
obj = BooksFile.objects.all()
query = BooksFile.objects.filter(book_major='cs)
return render(request, 'dashboard.html', {'books': obj, 'major': query})
def registerView(request):
if request.method == "POST":
form = UserCreationForm(request.POST)
profile_form = UserProfileForm(request.POST)
if form.is_valid() and profile_form.is_valid():
user = form.save()
profile = profile_form.save(commit=False)
profile.user = user
profile.save()
return redirect('login_url')
else:
form = UserCreationForm()
profile_form = UserProfileForm()
context = {'form': form, 'profile_form': profile_form}
return render(request, 'registration/register.html', context)
here is my template:
{% extends 'index.html' %}
{% block content %}
<h1>Welcome, {{user.username}}</h1>
<h2>Your major is {{user.userprofile.major}}</h2>
{% for book in books %}
<h3>Your book name is {{book.book_name}}</h3>
{% endfor %}
{% endblock %}
I am trying to show the book names from the booksfile table by corresponding major that user has. Right its showing the books that has "cs" attribute because I manually put "cs" in the get function in view. I am trying to send the major string from template to view, so that I can put what ever the user's major is in the get function. Or is there any other way to do it.
You need to use a form in your template and submit it to call your view. i.e.
<form action="your_view_url" method="POST">
<input type="text" name="major" value="{{user.userprofile.major}}"/>
<input type="submit"/>
</form>
an then in your view you access that with:
if request.POST:
major = request.POST.get('major')
As per documentation: https://docs.djangoproject.com/en/2.2/topics/forms/
First of all you have to get the value of model with help of queryset, and put it in the dictionary and then pass it with the template.
In views:
def get(self, request):
queryset = Model_name.objects.all()
ctx = {
'queryset': queryset,
}
return render(request, 'page_name(or template_name).html', ctx)
in template:
<form action="{%url'(your_view_name without brackets)'%}" method="POST">
{% for data in queryset%}
<span class="username">{{data.name(field of your model)}} .
</span>
<span class="email">{{data.email(field of your model)}} .
</span>
{% endfor%}
</form>
Related
After struggling with this issue for a while, I am hoping someone here can point me in a more productive direction.
I am trying to take an indeterminate number of variables in a database (obtained through a different template) and render them on a webpage, each variable with a simple data entry form, to be saved back to the database. Basically, it's a tracker for analysis. Say I want to track my daily sleep, running time, and calorie intake (the variables). I have those saved in a database as variables and want to call upon those variables and show them on a webpage with a daily entry form. I am using a "for" loop right now and it renders the way I want it to, with the variable name and the form, but it is only saving the last item in the variable list. How do I amend the code below such that when I hit the save button for each form rendeded, it saves the information for that variable (not just the last one rendered).
Below is the code. Any and all help would be infinitely appreciated.
Models...
class Variable(models.Model):
date_added = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(get_user_model(), default='', on_delete=models.CASCADE) # id the active user
ENTRY_TYPE_CHOICES = [
('numeric', 'enter a daily number'),
('scale', 'rate daily on a scale of 1-10'),
('binary', "enter daily, 'yes' or 'no' "),
]
variable = models.CharField(max_length=50, default='')
entry_type = models.CharField(max_length=50, choices=ENTRY_TYPE_CHOICES, default="numeric")
def __str__(self):
return self.variable
class DailyEntry(models.Model):
date = models.DateField(default=datetime.date.today)
# date_added = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(get_user_model(), default='', on_delete=models.CASCADE) # id the active user
variable_name = models.CharField(max_length=50, default='')
variable_id = models.SmallIntegerField(default=0000)
entry = models.FloatField(default=9999)
class Meta:
verbose_name_plural = 'Daily Entries'
def __str__(self):
return self.variable
Form...
class VariablesForm(forms.ModelForm):
class Meta:
model = Variable
fields = ['variable', 'entry_type' ]
labels = {'variable':'Dependent variable to track', 'entry_type': 'Type of measure'}
class DailyEntryForm(forms.ModelForm):
class Meta:
model = DailyEntry
fields = ['variable_name', 'variable_id', 'entry', 'date']
labels = {'entry': 'Daily entry', 'date': 'Date'}
widgets = {'variable_name': forms.HiddenInput(), 'variable_id': forms.HiddenInput()}
Views...
def daily_entry(request):
''' page to make daily entries '''
vars = Variable.objects.filter(id__gt = 0 )
if request.method != 'POST':
# No data submitted. GET submitted. Create a blank form
form = DailyEntryForm()
else:
#POST data submitted. Process data
form = DailyEntryForm(data=request.POST)
if form.is_valid():
data = form.save(commit=False)
data.created_by = request.user
data.save()
return HttpResponseRedirect(reverse('entry_new'))
context = {'form': form, 'vars': vars}
return render(request, 'entry_new.html', context)
and HTML...
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
{% for var in vars %}
<div>
<ul>
<h3>{{ var.variable }}</h3>
<form class="" action="" method="post">
{% csrf_token %}
{{ form|crispy }}
<input type="hidden" name="variable_id" value="{{ var.id }}" >
<input type="hidden" name="variable_name" value="{{ var.variable }}">
<input type="submit" name="" value="Save" />
</ul>
</div>
{% endfor %}
{% endblock content %}
Any help, well, helps...
Thanks!
I am writing a view that retrieve an answer from game2.html, check the answer; if the answer is correct, the view will redirect user to correct.html, if the answer is incorrect, then user will be redirected to incorrect.html.
The problem now is after clicking the submit button, user won't be redirected. But the score is updated.
After I clicked submit button the url will change from http://localhost:8000/game2/ to http://localhost:8000/game2/?ans2=4&game2Answer=Submit instead of redirect to correct.html or incorrect.html
I guess it might be the problem of my submit button that doesn't trigger the redirect function, or it is the problem of the way I write redirect function in views, as the score is actually updated if the answer is correct.
So, how can i fix it to make it able to redirect to either correct.html or incorrect.html after going into the if-else statement.
morse_logs/views.py
#login_required()
def game2(request):
"""The Game2 page"""
if request.user and not request.user.is_anonymous:
user = request.user
def verifyGame2(val1):
user_score, created = userScore.objects.get_or_create(user=user)
if val1 == 4:
# user's score declared in model increase 5points
# display correct and 5 points added to user
user_score.score += 5
user_score.save()
return redirect('morse_logs:incorrect')
else:
# user's score declared in model has no point
# display incorrect and 0 point added to user
return redirect('morse_logs:incorrect')
ans2 = request.GET.get('ans2', '')
if ans2 == '':
ans2 = 0
verifyGame2(int(ans2))
return render(request, 'morse_logs/game2.html')
game2.html
{% extends "morse_logs/base.html" %}
{% block content %}
<title>GAME 2</title>
<div>
<h1>GAME 2</h1>
<h2>2 + 2 = ?</h2>
<form action="" method="post" >
<input type="number" id="ans1" name="ans1"/><br><br>
<input type="submit" name="game1Answer"/>
</form>
</div>
{% endblock content %}
morse_logs/correct.html
{% extends "morse_logs/base.html" %}
{% block content %}
<title>Correct!</title>
<div>
<h1>Congratulations! Your answer is CORRECT!</h1>
</div>
{% endblock content %}
morse_logs/incorrect.html
{% extends "morse_logs/base.html" %}
{% block content %}
<title>Inorrect...</title>
<div>
<h1>Unfortunately! Your answer is Incorrect!</h1>
</div>
{% endblock content %}
morse_logs/urls.py
from django.urls import path, include
from morse_logs import views
app_name = 'morse_logs'
urlpatterns = [
#The path() function is passed four arguments, two required: route and view, and two optional: kwargs, and name.
# Home Page
path(r'', views.index, name='index'),
# Page that shows all topics
path(r'topics/', views.topics, name='topics'),
path(r'cipher/', views.cipher, name='cipher'),
path(r'decipher/', views.decipher, name='decipher'),
path(r'tutorialIndex/', views.tutorialIndex, name='tutorialIndex'),
path(r'gameDirectory/', views.gameDirectory, name='gameDirectory'),
path(r'game1/', views.game1, name='game1'),
path(r'game2/', views.game2, name='game2'),
path(r'correct/', views.correct, name='correct'),
path(r'incorrect/', views.incorrect, name='incorrect'),
]
You should change your
redirect('morse_logs:incorrect.html')
to
redirect('url_name')
And also remove the app_name if you are using django version >2.0
First, I changed the template form method from "GET" to "POST" and add {% csrf_token %}.
Secondly, I changed the view into 2 parts:
1st part is when user first enter game2.html(GET request), it will render game2.html to user.
2nd part is basically what I have done before, but this time I added a case that respond to user's POST request, and from there to do redirections to either correct.html or incorrect.html
game2.html
{% extends "morse_logs/base.html" %}
{% block content %}
<title>GAME 2</title>
<div>
<h1>GAME 2</h1>
<h2>2 + 2 = ?</h2>
<form method="POST">
{% csrf_token %}
<input type="number" id="ans2" name="ans2"/><br><br>
<input type="submit" name="Submit"/>
</form>
</div>
{% endblock content %}
views.py
#login_required()
def game2(request):
"""The Game2 page"""
if request.method == "GET":
return render(request, 'morse_logs/game2.html')
elif request.method == "POST":
if request.user and not request.user.is_anonymous:
user = request.user
user_score, created = userScore.objects.get_or_create(user=user)
ans2 = request.POST.get('ans2', '') #fetch the POST data from template
if ans2 == '':
ans2 = 0
ans2 = int(ans2)
if ans2 == 4:
# user's score declared in model increase 5points
# display correct and 5 points added to user
user_score.score += 5
user_score.save()
return redirect(reverse('morse_logs:correct'))
else:
# user's score declared in model has no point
# display incorrect and 0 point added to user
return redirect(reverse('morse_logs:incorrect'))
I have a list of entries which are displayed in a webpage. Each entry has the same input form. But my problem arises when data is put into the input form, it appears on every single one of them. How do I change this.
Each input form is treated as a single cloned entity distributed over many entries.
views.py
def topic(request, topic_id, type): #
topic = Topic.objects.get(id = topic_id, type = 't_topic')
entries = topic.entry_set.order_by('-date_added')
images = Image.objects.filter(imgtopic__in = entries)
ArticleFormSet = formset_factory(CheckAnswer, extra = 2)
if request.method == 'POST':
formset = ArticleFormSet(request.POST)
if form.is_valid():
return HttpResponseRedirect(reverse('learning_logs:index'))
else:
formset = ArticleFormSet()
context = {'topic': topic, 'entries': entries, 'images': images, 'formset': formset}
return render(request, 'learning_logs/topic.html', context)
topic.html template
{%load staticfiles %}
{% block content %}
{% for entry in entries(n) %}
<div class = 'secondary-container'>
<li>
<div class = 'date'>
<p >{{ entry.date_added|date:'M d, Y H:i'}}</p>
</div>
{%include 'learning_logs/view_files.html'%}
<div class = 'video-container'>
{%include 'learning_logs/video.html' %}
</div>
<div class = 'entry-text'>
<p>{{ entry.text|linebreaks }}</p>
<p>$ {{entry.price_set.get.ptext}}</p>
</div>
</li>
<li>
<p> Enter Answer: </p>
<form action = "{%url 'learning_logs:topic' topic.id topic.type%}" method = 'post'>
{{formset.management_form}}
<table>
{% for form in formset%}
{{form.as_p}}
{% csrf_token %}
<button name = "submit">Submit answer</button>
{% endfor %}
</table>
</form>
</div>
forms.py
class CheckAnswer(forms.Form):
your_answer = forms.CharField(label = "Enter Your Key", max_length = 100)
def clean(self):
cleaned_data=super(CheckAnswer, self).clean()
your_answer = cleaned_data.get("your_answer")
try:
p = Keys.objects.get(key = your_answer)
except Keys.DoesNotExist:
raise forms.ValidationError("Incorrect code.")
My new problem is that I can't separate the forms into the different lists. Since extra = 2, I get 2 instances of forms on the same entry list.
I tried using the {%for form in formset%} command in the topic.html template to give each entry a form, but I get an of ['ManagementForm data is missing or has been tampered with'] when I click submit.
Image of the problem
i'm trying to get the data from my views.py to the html page.
if the views.py code is this
def VerifiedBySuperuser(request):
if request.method == 'POST':
vbs = MaanyaIT_EXAM48_ManageQuestionBank()
vbs.QuestionID = MaanyaIT_EXAM48_ManageQuestionBank.objects.get(QuestionID=request.POST.get(QuestionID, None))
vbs.QuestionInEnglishLang = request.POST.get('QuestionInEnglishLang', None)
vbs.save()
else:
return render(request, 'exam48app/verifiedbysuperuser.html')
then what shoud the code of html page to view my all data to the tamplates..
this is my html page
<form class="from-horizontal" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="post-entry">
{{ MaanyaIT_EXAM48_ManageQuestionBank.QuestionInEnglishLang }}
</div>
</form>
now what should i do?
From your comment, you need to know How to write/render the data from view to html template
I will demonstrate a simple example for you,
Assuming you have a view as below,
def VerifiedBySuperuser(request):
if request.method == 'GET':
context = {
"T_Name": "My Name",
"T_Age": 50,
"T_Phone": 1478523699
}
return render(request, 'verifiedbysuperuser.html', context=context)
and a HTML template as follows,
<!DOCTYPE>
<html>
<body>
Name : {{ T_Name }}<br>
Age : {{ T_Age }}<br>
Phone : {{ T_Phone }}<br>
</body>
</html>
When you access your view, you will get a response like this,
In your case, you can pass as many attributes to template as dict (shown in my example) and in template/html keys of context (that is T_Name,T_Name etct) becomes variable. So you can directly use them in HTML inside the twin braces ({{ variable_name }})
As far as I knew, this is the general procedure for template rendering/ html rendering
UPDATE-1
def VerifiedBySuperuser(request):
if request.method == 'POST':
obj = MyModel.objects.get(id=some_id)
other_data = [1,2,3,4,] # some specific data
context = {
"post_data": request.data,
"object_instance": obj,
"some_other_data": other_data
}
return render(request, 'verifiedbysuperuser.html', context=context)
I would like to filter data in Django (admin.py) with text writen in HTML input textbox. I need to filter companies by city in which they are and list of all cities is too long. I would like to replace list of all cities in filter by one text input. I found something similar
here http://djangosnippets.org/snippets/2429/ but there are two problems:
author did not posted models.py, so it is difficuilt to change code for my needs (+ no comments)
there is used class UserFieldFilterSpec(RelatedFilterSpec): but I need to use AllValuesFilterSpec instead of RelatedFilterSpec (more in file django/contrib/admin/filterspecs.py), because list of towns are in the same class as comapny (there shoud by class of towns and they should be referencing to company by foreign key (ManyToMany relationship), but for some reasons it have to be done this way)
important part of models.py looks something like this
class Company(models.Model):
title = models.CharField(max_length=150,blank=False)
city = models.CharField(max_length=50,blank=True)
and something from admin.py
class CatalogAdmin(admin.ModelAdmin):
form = CatalogForm
list_display = ('title','city')
list_filter = ['city',]
So again, I need to:
1. instead of list od cities display one text input in Django filter
2. After inputing city neme in that text input, filter data by city (request for filtering can be sent with some submit button or through javascript)
Thank yoy for all posts.
In case anybody still need this. It is little hackish in template, but implemented without a piece of js.
filters.py:
from django.contrib.admin import ListFilter
from django.core.exceptions import ImproperlyConfigured
class SingleTextInputFilter(ListFilter):
"""
renders filter form with text input and submit button
"""
parameter_name = None
template = "admin/textinput_filter.html"
def __init__(self, request, params, model, model_admin):
super(SingleTextInputFilter, self).__init__(
request, params, model, model_admin)
if self.parameter_name is None:
raise ImproperlyConfigured(
"The list filter '%s' does not specify "
"a 'parameter_name'." % self.__class__.__name__)
if self.parameter_name in params:
value = params.pop(self.parameter_name)
self.used_parameters[self.parameter_name] = value
def value(self):
"""
Returns the value (in string format) provided in the request's
query string for this filter, if any. If the value wasn't provided then
returns None.
"""
return self.used_parameters.get(self.parameter_name, None)
def has_output(self):
return True
def expected_parameters(self):
"""
Returns the list of parameter names that are expected from the
request's query string and that will be used by this filter.
"""
return [self.parameter_name]
def choices(self, cl):
all_choice = {
'selected': self.value() is None,
'query_string': cl.get_query_string({}, [self.parameter_name]),
'display': _('All'),
}
return ({
'get_query': cl.params,
'current_value': self.value(),
'all_choice': all_choice,
'parameter_name': self.parameter_name
}, )
templates/admin/textinput_filter.html:
{% load i18n %}
<h3>{% blocktrans with filter_title=title %} By {{ filter_title }} {% endblocktrans %}</h3>
{#i for item, to be short in names#}
{% with choices.0 as i %}
<ul>
<li>
<form method="get">
<input type="search" name="{{ i.parameter_name }}" value="{{ i.current_value|default_if_none:"" }}"/>
{#create hidden inputs to preserve values from other filters and search field#}
{% for k, v in i.get_query.items %}
{% if not k == i.parameter_name %}
<input type="hidden" name="{{ k }}" value="{{ v }}">
{% endif %}
{% endfor %}
<input type="submit" value="{% trans 'apply' %}">
</form>
</li>
{#show "All" link to reset current filter#}
<li{% if i.all_choice.selected %} class="selected"{% endif %}>
<a href="{{ i.all_choice.query_string|iriencode }}">
{{ i.all_choice.display }}
</a>
</li>
</ul>
{% endwith %}
Then according to your models in admin.py:
class CatalogCityFilter(SingleTextInputFilter):
title = 'City'
parameter_name = 'city'
def queryset(self, request, queryset):
if self.value():
return queryset.filter(city__iexact=self.value())
class CatalogAdmin(admin.ModelAdmin):
form = CatalogForm
list_display = ('title','city')
list_filter = [CatalogCityFilter,]
Ready to use filter would look like this.
I'm running Django 1.10, 1.11 and r_black's solution didn't completely fit because Django was complaining that filter fields must inherit from 'FieldListFilter'.
So a simple change for the filter to inherit from FieldListFilter took care of Django complaining and not having to specify a new class for each field, both at the same time.
class SingleTextInputFilter(admin.FieldListFilter):
"""
renders filter form with text input and submit button
"""
parameter_name = None
template = "admin/textinput_filter.html"
def __init__(self, field, request, params, model, model_admin, field_path):
super().__init__(field, request, params, model, model_admin, field_path)
if self.parameter_name is None:
self.parameter_name = self.field.name
if self.parameter_name in params:
value = params.pop(self.parameter_name)
self.used_parameters[self.parameter_name] = value
def queryset(self, request, queryset):
if self.value():
return queryset.filter(imei__icontains=self.value())
def value(self):
"""
Returns the value (in string format) provided in the request's
query string for this filter, if any. If the value wasn't provided then
returns None.
"""
return self.used_parameters.get(self.parameter_name, None)
def has_output(self):
return True
def expected_parameters(self):
"""
Returns the list of parameter names that are expected from the
request's query string and that will be used by this filter.
"""
return [self.parameter_name]
def choices(self, cl):
all_choice = {
'selected': self.value() is None,
'query_string': cl.get_query_string({}, [self.parameter_name]),
'display': _('All'),
}
return ({
'get_query': cl.params,
'current_value': self.value(),
'all_choice': all_choice,
'parameter_name': self.parameter_name
}, )
templates/admin/textinput_filter.html (unchanged):
{% load i18n %}
<h3>{% blocktrans with filter_title=title %} By {{ filter_title }} {% endblocktrans %}</h3>
{#i for item, to be short in names#}
{% with choices.0 as i %}
<ul>
<li>
<form method="get">
<input type="search" name="{{ i.parameter_name }}" value="{{ i.current_value|default_if_none:"" }}"/>
{#create hidden inputs to preserve values from other filters and search field#}
{% for k, v in i.get_query.items %}
{% if not k == i.parameter_name %}
<input type="hidden" name="{{ k }}" value="{{ v }}">
{% endif %}
{% endfor %}
<input type="submit" value="{% trans 'apply' %}">
</form>
</li>
{#show "All" link to reset current filter#}
<li{% if i.all_choice.selected %} class="selected"{% endif %}>
<a href="{{ i.all_choice.query_string|iriencode }}">
{{ i.all_choice.display }}
</a>
</li>
</ul>
{% endwith %}
Usage:
class MyAdmin(admin.ModelAdmin):
list_display = [your fields]
list_filter = [('field 1', SingleTextInputFilter), ('field 2', SingleTextInputFilter), further fields]
While it's not actually your question, this sounds like a perfect solution for Django-Selectables you can with just a few lines add an AJAX powered CharField Form that will have it's entries selected from the list of cities. Take a look at the samples listed in the link above.
Below is the fix for field name..in queryset function
class SingleTextInputFilter(admin.FieldListFilter):
"""
renders filter form with text input and submit button
"""
parameter_name = None
template = "admin/textinput_filter.html"
def __init__(self, field, request, params, model, model_admin, field_path):
super().__init__(field, request, params, model, model_admin, field_path)
if self.parameter_name is None:
self.parameter_name = self.field.name
if self.parameter_name in params:
value = params.pop(self.parameter_name)
self.used_parameters[self.parameter_name] = value
def queryset(self, request, queryset):
variable_column = self.parameter_name
search_type = 'icontains'
filter = variable_column + '__' + search_type
if self.value():
return queryset.filter(**{filter: self.value()})
def value(self):
"""
Returns the value (in string format) provided in the request's
query string for this filter, if any. If the value wasn't provided then
returns None.
"""
return self.used_parameters.get(self.parameter_name, None)
def has_output(self):
return True
def expected_parameters(self):
"""
Returns the list of parameter names that are expected from the
request's query string and that will be used by this filter.
"""
return [self.parameter_name]
def choices(self, cl):
all_choice = {
'selected': self.value() is None,
'query_string': cl.get_query_string({}, [self.parameter_name]),
'display': ('All'),
}
return ({
'get_query': cl.params,
'current_value': self.value(),
'all_choice': all_choice,
'parameter_name': self.parameter_name
}, )