I found an similar question here, but unlike there and unlike in django official tutorial , I don't have a separate Choice class. How can I restrict every user to vote just one? What should I change in my code?
my models.py:
from django.contrib.auth.models import User
class Law(models.Model):
#some code here
yes_votes = models.IntegerField(default=0)
no_votes = models.IntegerField(default=0)
class Voter(models.Model):
user = models.ForeignKey(User)
law = models.ForeignKey(Law)
my views.py:
class LawDetailView(generic.DetailView):
model = Law
template_name = 'law_detail.html'
def get_queryset(self):
"""
Excludes any petitions that aren't published yet.
"""
return Law.objects.filter(pub_date__lte=timezone.now())
class LawResultsView(generic.DetailView):
model = Law
template_name = 'law_results.html'
def law_yes_vote(request, law_id):
if Voter.objects.filter(law_id=law_id, user_id=request.user.id).exists():
return render(request, 'law_detail.html', {
'law': p,
'error_message': "Sorry, but you have already voted."
})
else:
p = get_object_or_404(Law, pk=law_id)
p.yes_votes += 1
p.save()
return HttpResponseRedirect(reverse('laws:law_results', args=(p.id,)))
def law_no_vote(request, law_id):
if Voter.objects.filter(law_id=law_id, user_id=request.user.id).exists():
return render(request, 'law_detail.html', {
'law': p,
'error_message': "Sorry, but you have already voted."
})
else:
p = get_object_or_404(Law, pk=law_id)
p.no_votes += 1
p.save()
return HttpResponseRedirect(reverse('laws:law_results', args=(p.id,)))
my law_detail.html:
{% if request.user.is_authenticated %}
{% if error_message %}
<h1 >{{ error_message }}</h1>
{% else %}
<div class="row" id="row-voting">
<form action="{% url 'laws:law_yes_vote' law.id %}" method="post">
{% csrf_token %}
<button class="btn btn-success" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" >
<label >YES</label>
</form>
<form action="{% url 'laws:law_no_vote' law.id %}" method="post">
{% csrf_token %}
<button class="btn btn-danger" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" >
<label >NO</label>
</form>
</div>
{% endif %}
{% else %}
<h1>Please, register</h1>
{% endif %}
It looks like you have forgotten to create the voter instance after the user has voted.
def law_yes_vote(request, law_id):
if Voter.objects.filter(law_id=law_id, user_id=request.user.id).exists():
return render(request, 'law_detail.html', {
'law': p,
'error_message': "Sorry, but you have already voted."
})
else:
p = get_object_or_404(Law, pk=law_id)
p.yes_votes += 1
p.save()
Voter.objects.create(law_id=law_id, user_id=request.user.id)
return HttpResponseRedirect(reverse('laws:law_results', args=(p.id,)))
You'll need to update law_no_vote in the same way.
Related
I was trying to iterate request.POST.get() to get some inputs from my view's corresponding html file using concatenation.
However, no matter whether the input is filled, it always says that the input returns the fallback. (As in the default response that the programmer gives.)
Does anyone know how to solve this? I'm trying to make it so it adds each choice to the set of choices for each question.
create.html
{% extends "polls/base.html" %}
{% block title %}Create a Poll{% endblock title %}
{% block header %}Create:{% endblock header %}
{% load custom_tags %}
{% block content %}
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="{% url 'polls:create' %}" method="post"> {% csrf_token %}
{% for field in questionfields %}
{% if field == 'question_text' %}
<label for="{{ field }}">{{ field|capfirst|replace }}:</label>
<input type="text" name="{{ field }}" id="{{ field }}">
<br>
{% endif %}
{% endfor %}
<br>
{% for choice in choicenumber|rangeof %}
<br>
<label for="choice{{ forloop.counter }}">Choice {{ forloop.counter }}</label>
<input type="text" name="choice{{ forloop.counter }}" id="choice{{ forloop.counter }}">
<br>
{% endfor %}
<br>
<br>
<input type="submit" value="Create" name="submit">
</form>
{% endblock content %}
views.py
def create(request):
choicenumber = 3
context = {
'questionfields': Question.__dict__,
'choicenumber': choicenumber,
}
submitbutton = request.POST.get('submit', False)
if submitbutton:
new_question = Question.objects.create(question_text=request.POST.get('question_text', ''), pub_date=timezone.now())
if new_question.question_text == '':
context = {
'questionfields': Question.__dict__,
'error_message': "No poll question entered.",
'choicenumber': choicenumber,
}
del new_question
return render(request, 'polls/create.html', context)
else:
new_question.save()
for i in range(choicenumber):
choice = request.POST.get(('choice' + str(i)), '')
new_question.choice_set.add(choice)
new_question.save()
return HttpResponseRedirect(reverse('polls:results', args=(new_question.id,)))
else:
return render(request, 'polls/create.html', context)
The error: TypeError at /polls/create/
'Choice' instance expected, got ''
Request Method: POST
Request URL: http://127.0.0.1:8000/polls/create/
Django Version: 3.0.8
Exception Type: TypeError
Exception Value: 'Choice' instance expected, got ''
The error was in line 52 of the file:
new_question.choice_set.add(choice)
I would be really thankful if anyone could help.
EDIT::
The models as requested:
models.py
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __str__(self):
return self.question_text
def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days=1) <= self.pub_date <= now
was_published_recently.boolean = True
was_published_recently.admin_order_field = 'pub_date'
was_published_recently.short_description = 'Published recently?'
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return self.choice_text
Then else part should be like this:
else:
new_question.save(commit=False)
for i in range(choicenumber):
choice = request.POST.get('choice' + str(i), '')
if choice:
choice_obj = Choice.objects.create(question=new_question,choice_text=choice)
new_question.choice_set.add(choice_obj)
new_question.save()
return HttpResponseRedirect(reverse('polls:results', args=(new_question.id,)))
i want search from all my model in database , so i create this search functions for do this ... but always i got ' No results for this search '
how to fix this ?
view.py:
def search(request):
if request.method == 'GET':
query= request.GET.get('q')
submitbutton= request.GET.get('submit')
if query is not None:
home_database= Homepage.objects.filter(name__icontains=query,app_contect__icontains=query,page_url__icontains=query,app_image__icontains=query)
pcprograms_database= PCprogram.objects.filter(name__icontains=query,app_contect__icontains=query,page_url__icontains=query,app_image__icontains=query)
androidapk_database= AndroidApks.objects.filter(name__icontains=query,app_contect__icontains=query,page_url__icontains=query,app_image__icontains=query)
androidgames_database= AndroidGames.objects.filter(name__icontains=query,app_contect__icontains=query,page_url__icontains=query,app_image__icontains=query)
antiruvs_database= Antivirus.objects.filter(name__icontains=query,app_contect__icontains=query,page_url__icontains=query,app_image__icontains=query)
systems_database= OpratingSystems.objects.filter(name__icontains=query,app_contect__icontains=query,page_url__icontains=query,app_image__icontains=query)
pcgames_database= PCgames.objects.filter(name__icontains=query,app_contect__icontains=query,page_url__icontains=query,app_image__icontains=query)
results= list(chain(home_database,pcprograms_database,androidapk_database,androidgames_database,antiruvs_database,systems_database,pcgames_database))
context={'results': results,
'submitbutton': submitbutton}
return render(request, 'html_file/enterface.html', context)
else:
return render(request, 'html_file/enterface.html')
else:
return render(request, 'html_file/enterface.html')
html search form :
<form id="search_form" action="{% url 'search' %}" method="GET" value="{{request.GET.q}}">
<input id="search_box" type="text" name="q" value="{{request.GET.q}}"
placeholder=" Search For ... "/>
<input id="search_button" type="submit" name="submit" value="Search"/>
</form>
html file :
{% if submitbutton == 'Search' and request.GET.q != '' %}
{% if results %}
<h1> <small> Results for </small><b>{{ request.GET.q }}</b> : </h1>
<br/><br/>
{% for result in results %}
<label id="label_main_app"> <img id="img_main_app_first_screen" src="{{result.app_image.url}}" alt="no image found !" height="170" width="165" > {{result.name}} <br><br> <p id="p_size_first_page"> {{result.app_contect}} <br> <br> <big> See More & Download </big> </p>
</label>
{% endfor %}
{% else %}
<h3> No results for this search </h3>
{% endif %}
{% endif %}
any help please ?
If you are trying to filter with multiple model fields you need Q from django.db.models
Homepage.objects.filter(Q(name__icontains=query)&Q(app_contect__icontains=query),....
I'm trying to submit this form through this model and views, but I am getting the TypeError which is shown in the screenshot. Though I want to also submit it to the database. I have taking all my value just to drop it into database.
I'd be very happy if you'd assist to solve the save() method as well.
student.py:
#login_required
#student_required
def take_exam(request, pk):
course = get_object_or_404(Course, pk=pk)
student = request.user.student
question = course.questions.filter()
#correct_answers = student.course_answers.filter(answer__question__quiz=course, answer__is_correct=True).count()
total_questions = course.questions.count()
choice = Answer.objects.filter()
marks_obtainable = Details.objects.get(course_id=course)
if request.method == 'POST':
question_pk = request.POST.getlist('question_pk')
question_obj = Question.objects.filter(id=int(question_pk))
choice_pk = [request.POST['choice_pk{}'.format(q)] for q in question_obj]
#print(marks_obtainable.marks_obtained)
zipped = zip(question_obj, choice_pk)
for x, y in zipped:
correct_answers = Answer.objects.filter(question_id=x, is_correct=True).values("id").first()['id']
print(x, y, correct_answers)
if int(y) == int(correct_answers):
#z = TakenQuiz(student=student, course=course, \
#question=x, selected_choice=y, marks_obtained=marks_obtainable, is_correct=True)
print("correct")
else:
print("Not Correct")
return render(request, 'classroom/students/take_exam_form.html', {
'course': course,
'question': question,
'course': course,
'total_questions': total_questions,
'choice': choice,
'marks_obtainable': marks_obtainable
})
models.py:
class Question(models.Model):
course = models.ForeignKey(Course, on_delete=models.CASCADE, related_name='questions')
text = models.CharField('Question', max_length=500)
def __str__(self):
return self.text
class Answer(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name='answers')
text = models.CharField('Answer', max_length=255)
is_correct = models.BooleanField('Correct answer', default=False)
def __str__(self):
return self.text
take_exam_form.html:
<h2 class="mb-3">{{ course.name }}</h2>
Course id <h2 class="mb-3">{{ course.id }}</h2>
Student id <h2 class="mb-3">{{ request.user.id }}</h2>
Total Question: <h2 class="mb-3">{{ total_questions }}</h2>
Mark Obtainable <h2 class="mb-3">{{ marks_obtainable.maximum_marks }}</h2>
<form method="post" novalidate>
{% csrf_token %}
{% for questions in question %}
<input type="hidden" name="question_pk" value="{{ questions.pk }}">
<h3 class="text-info">{{ questions.text|safe }}</h3>
{% for choices in questions.answers.all %}
<input class="form-check-input" type="radio" name="choice_pk{{ questions.pk }}" id="choices-{{ forloop.counter }}" value="{{ choices.pk }}">
<label class="form-check-label" for="choices-{{ forloop.counter }}">
{{ choices.text|safe }}
</label>
{% endfor %}
{% endfor %}
<button type="submit" class="btn btn-primary">Submit Now →</button>
</form>
I can see that the only int() call is in
int(y)
Try this print(type(y)). Maybe y is a list object. That's why the error said:
The arg must be string or ... not a list
I am working in ang django project onlinevoting. In my template I use
looping to loop all the positions and also the candidates. I have trouble in saving many data at once in one attribute for example in my model I have:
class Vote(models.Model):
candidate_id = models.ForeignKey('Candidate', blank=True, null=True)
election_id = models.ForeignKey('Election', blank=True, null=True)
user_id = models.ForeignKey('User', blank=True, null=True)
def __str__(self):
return "%s %s" % (user_id.first_name, election_id.year)
and in my template vote.html:
<form method="POST" class="form-horizontal" role="form">
{% if success %}
<div class="alert alert-success">
×
<strong>Success!</strong> {{ success }}
</div>
{% endif %}
{% if exist %}
<div class="alert alert-warning">
×
<strong>Warning!</strong> {{ exist }}
</div>
{% endif %}
{% csrf_token %}
<div class="form-group ">
{% for position in positions %}
<label for="cname" class="control-label col-lg-2">{{ position }}<span class="required">*</span></label>
{% for candidate in candidates %}
{% if position.pk == candidate.position_id.pk %}
<div class="col-lg-3">
<input type="checkbox" name="candidate_id" value="{{ candidate.pk }}">{{ candidate }}<br>
</div>
{% endif %}
{% endfor %}
</div>
{% endfor %}
<button class="btn btn-primary" type="submit">Save</button>
<button class="btn btn-default" type="button">Cancel</button>
</div>
</div>
</form>
How can I add/save all the candidates? because the user can select many candidates and I want to save them at once. This is my views.py
def vote(request):
if request.user.is_authenticated and request.user.is_admin:
candidates = Candidate.objects.all()
election = Election.objects.all().filter(is_active=True)
positions = Position.objects.all()
user = get_object_or_404(User, pk=request.user.pk)
try:
if request.method == 'POST':
candidate_id = request.POST['candidate_id']
vote = Vote.objects.create(candidate_id=candidate_id)
vote.save()
vote.election_id = election
vote.save()
vote.user_id = user
vote.save()
else:
form = VoteForm()
return render(request,'system/vote.html', {'form':form, 'candidates': candidates,
'election': election, 'user': user,
'positions': positions})
except:
exist = "ERROR!"
form = VoteForm()
return render(request,'system/vote.html', {'form':form, 'exist': exist})
elif not request.user.is_authenticated:
return redirect('system.views.user_login')
I'm trying to make a search form for Django.
Its a typical search form and then returns a table of matches. I wish to paginate the tables returned.
The problem lies in the Previous and Next buttons.
The links for the return query goes to /records/search/?query=a (search sample is a)
The page outputs the table and its previous and next links. However the links redirect to /records/search/?page=2 and the page displays a blank table.
Any help on which links I should pass for Prev/Next?
search.html:
{% extends 'blank.html' %}
{% block content %}
<div class="row">
<form id="search-form" method="get" action=".">
{{ form.as_p }}
<input type="submit" value="Search" />
</form>
</div>
<br><br>
//display table code//
{% if is_paginated %}
<div class="pagination">
<span class="step-links">
{% if agent_list.has_previous %}
forrige
{% endif %}
<span class="current">
Page {{ agent_list.number }} of {{ agent_list.paginator.num_pages }}.
</span>
{% if agent_list.has_next %}
Next
{% endif %}
</span>
</div>
{% endif %}
{% endblock %}
and the search view:
def search_page(request):
form = SearchForm()
agents = []
show_results=False
if request.GET.has_key('query'):
show_results=True
query=request.GET['query'].strip()
if query:
form=SearchForm({'query': query})
agents = \
Agent.objects.filter(Q(name__icontains=query))
paginator = Paginator(agents, 10)
page = request.GET.get('page')
try:
agents = paginator.page(page)
except PageNotAnInteger:
agents = paginator.page(1)
except EmptyPage:
agents = paginator.page(paginator.num_pages)
variables = RequestContext(request,
{ 'form': form,
'agent_list': agents,
'show_results': show_results,
'is_paginated': True,
}
)
return render_to_response('search.html', variables)
I've seen the similar questions but I can't understand/make them work. Any help?
Edit:
For a quickfix (haven't really looked at the cons)
I added a variable in my view:
variables = RequestContext(request,
{ 'form': form,
'agent_list': agents,
'show_results': show_results,
'is_paginated': True,
**'query': query,**
}
)
Where query without the quotes is the recieved query variable.
Then simply change the URL to:
Previous
If you have a better way of answering the question, please do or appending a URL to your currently opened URL.
I would recommend putting the solution in a template tag like so:
myapp/templatetags/mytemplatetags.py:
from django import template
register = template.Library()
#register.simple_tag
def url_replace(request, field, value):
d = request.GET.copy()
d[field] = value
return d.urlencode()
#register.simple_tag
def url_delete(request, field):
d = request.GET.copy()
del d[field]
return d.urlencode()
Then from templates do:
{% load mytemplatetags %}
...
previous
you can use {{ request.get_full_path }} this tag to get current url.
Next
this worked for me
The below works before and after a search form has been submitted:
Views.py
class PostListView(ListView):
model = Post #.objects.select_related().all()
template_name = 'erf24/home.html' # <app>/<model>_<viewtype>.html
context_object_name = 'posts' # default >> erf24/post_list.html
ordering = ['date_posted']
paginate_by = 3
def is_valid_queryparam(param):
return param != '' and param is not None
def invalid_queryparam(param):
return param == '' and param is None
class SearchView(ListView):
model = Post #.objects.select_related().all()
template_name = 'erf24/home.html' # <app>/<model>_<viewtype>.html
context_object_name = 'posts' # default >> erf24/post_list.html
ordering = ['date_posted']
paginate_by = 3
def get_queryset(self): # new
key = self.request.GET.get('key')
minp = self.request.GET.get('min')
maxp = self.request.GET.get('max')
if is_valid_queryparam(key):
obj = Post.objects.filter(Q(content__icontains=key) | Q(location__icontains=key)).distinct().order_by('date_posted')
if is_valid_queryparam(minp):
obj = Post.objects.filter(Q(price__gte=minp)).distinct().order_by('date_posted')
if is_valid_queryparam(maxp):
obj = Post.objects.filter(Q(price__lte=maxp)).distinct().order_by('date_posted')
if is_valid_queryparam(minp) & is_valid_queryparam(maxp):
obj = Post.objects.filter(Q(price__gte=minp) & Q(price__lte=maxp)).distinct().order_by('date_posted')
if is_valid_queryparam(key) & is_valid_queryparam(minp) & is_valid_queryparam(maxp):
obj = Post.objects.filter(Q(content__icontains=key) | Q(location__icontains=key)).distinct()
obj = obj.filter(Q(price__gte=minp) & Q(price__lte=maxp)).order_by('date_posted')
if invalid_queryparam(key) & invalid_queryparam(minp) & invalid_queryparam(maxp):
obj = Post.objects.all()
return obj
url.py
urlpatterns = [
path('', PostListView.as_view(), name='erf24-home'),
path('search/', SearchView.as_view(), name='erf24-search'),
]
Home.html
<form action="{% url 'erf24-search' %}" method="GET">
<div class="form-group">
<label for="inputAddress">Search keyword</label>
<input type="text" class="form-control" id="key" name="key" placeholder="keyword">
</div>
<label for="">Price</label>
<div class="form-row">
<div class="form-group col-md-6">
<input type="number" class="form-control" id="min" name="min" placeholder="min price">
</div>
<div class="form-group col-md-6">
<input type="number" class="form-control" id="max" name="max" placeholder="max price">
</div>
</div>
<button type="submit" class="btn btn-primary btn-sm mt-1 mb-1">Search</button>
<button type="reset" class="btn btn-secondary btn-sm mt-1 mb-1">Clear</button>
</form>
{% for post in posts %}
<article class="media content-section">
<div class="media-body">
<div class="article-metadata">
<img class="rounded-circle article-img" src="{{ post.author.profile.image.url }}" alt="">
{{ post.author }}
<small class="text-muted">{{ post.date_posted }}</small>
<!-- use |date: "specs" to filter date display -->
</div>
<h2>
{{ post.price }}
</h2>
<p class="article-content">{{ post.content }}</p>
<p class="article-content">{{ post.location }}</p>
<p><a class="like-btn" data-href="{{ post.get_api_like_url }}" href="">{{ post.likes.count }}
{% if user in post.likes.all %} Unlike
{% else %} Like
{% endif %}
</a></p>
</div>
{% for image in post.image_set.all %}
<img class="account-img" src="{{ image.image.url }}" alt="">
{% endfor %}
</article>
{% endfor %}
{% if is_paginated %}
{% if page_obj.has_previous %}
First
Previous
{% endif %}
{% for num in page_obj.paginator.page_range %}
{% if page_obj.number == num %}
{{ num }}
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
{{ num }}
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
Next
Last
{% endif %}
{% endif %}
Worked like a charm :) Enjoy!
You can use {{ request.get_full_path }} template tag
Next
you can use this, I use it because I use filters in the url itself, so all the url params are used to build the next or previous url
import re
from django import template
register = template.Library()
PAGE_NUMBER_REGEX = re.compile(r'(page=[0-9]*[\&]*)')
#register.simple_tag
def append_page_param(value,pageNumber=None):
'''
remove the param "page" using regex and add the one in the pageNumber if there is one
'''
value = re.sub(PAGE_NUMBER_REGEX,'',value)
if pageNumber:
if not '?' in value:
value += f'?page={pageNumber}'
elif value[-1] != '&':
value += f'&page={pageNumber}'
else:
value += f'page={pageNumber}'
return value
then, in your pagination nav you can call it like this:
{% append_page_param request.get_full_path page_obj.previous_page_number %}