I want to make a system of likes on the site, and I need to create an entry in the table on the button. When a person clicks on like, the table writes row 1 and when dislike 0
views.py
def forum(requset):
model = Quetions.objects.all()
answer = Answer.objects.all()
count = Answer.objects.all().count()
count_answer = Quetions.objects.all().count()
paginator = Paginator(model, 1) # Show 25 contacts per page.
page_number = requset.GET.get('page')
question_id = requset.GET.get('id',False)
page_obj = paginator.get_page(page_number)
requestanswer = requset.GET.get('id',False)
like_disli = like.objects.filter(like_dislike = "1").count()
dislike = like.objects.filter(like_dislike = "0").count()
createlike =
objects = {
'model': page_obj,
'answer':answer,
'count':count,
'count_question':count_answer,
'page_obj':page_obj,
'question':question_id,
'id':model,
'request':requestanswer,
'like':like_disli,
'dislike':dislike,
'createlike':createlike,
}
return render(requset,'forum.html',objects)
forum.html
<span>
<i class="fas fa-thumbs-up" style="color: blue;margin-right: 5px;" onclick="incrementClick()"></i>{{like}}<i class="fas fa-thumbs-down" style="color: red;margin-right: 5px;margin-left: 10px;" onclick="dislikeclick()"></i>{{dislike}}
</span>
{% block js %}
<script>
var a = "{{createlike}}"
function incrementClick() {
a
}
function dislikeclick() {
dislikedisplay(++dislikecounter);
}
function updateDisplay(val) {
document.getElementById("counter-label").innerHTML = val;
}
function dislikedisplay(val){
document.getElementById("counter").innerHTML = val
}
</script>
{% endblock js %}
tell me how to do it???
Related
I have a page that displays some information about website admins such as username, skills, Instagram profile and bio. The admins are able to edit their profile information and the update is being saved using JavaScript fetch. When I click on the save button everything except the Instagram profile which is a URLField gets updated. For Instagram element to be updated I need to reload the page. How can I make it get updated without reloading the page? Everything is correct in the console log.
about.js:
document.addEventListener("DOMContentLoaded", function(){
const button = document.querySelectorAll("#edit_profile")
button.forEach(function(button){
button.onclick = function(){
const username = document.getElementById(`username_${memberID}`);
const skills = document.getElementById(`skills_${memberID}`);
const bio = document.getElementById(`bio_${memberID}`);
var instagram = document.getElementById(`instagram_${memberID}`).href;
let edit_username = document.createElement("textarea");
edit_username.setAttribute("rows", "1");
edit_username.innerHTML = username.innerHTML
edit_username.id = `edit_username_${memberID}`;
edit_username.className = `form-control username ${usernameID}`;
let edit_skills = document.createElement("textarea");
...
let edit_instagram = document.createElement("textarea");
edit_instagram.setAttribute("rows","1");
edit_instagram.innerHTML = instagram;
edit_instagram.id = `edit_instagram_${memberID}`;
edit_instagram.className = "form-control social-media";
const saveButton = document.createElement("button");
saveButton.innerHTML = "Save";
saveButton.id = `saveButton_${memberID}`;
saveButton.className = "btn btn-success col-3";
saveButton.style.margin = "10px";
document.getElementById(`edit_${memberID}`).append(edit_username);
...
document.getElementById(`edit_${memberID}`).append(edit_instagram);
document.getElementById(`edit_${memberID}`).append(saveButton);
// When the save button is clicked
saveButton.addEventListener("click", function(){
edit_username = document.getElementById(`edit_username_${memberID}`);
...
edit_instagram = document.getElementById(`edit_instagram_${memberID}`);
fetch(`/edit_profile/${memberID}`,{
method: "POST",
body: JSON.stringify({
username: edit_username.value,
skills: edit_skills.value,
instagram: edit_instagram.value,
bio: edit_bio.value,
})
})
.then(response => response.json())
.then(result => {
console.log(result);
if(result[`error`]){
cancel(memberID)
}
else {
username.innerHTML = result.username;
secusername.innerHTML = result.username;
skills.innerHTML = result.skills;
instagram = result.instagram;
bio.innerHTML = result.bio;
}
})
})
}
});
})
about.html:
{% for member in team_members %}
<div class="col" id="border">
<!--If user is admin, show edit button-->
{% if user.is_superuser %}
<div class="position-relative" id="edit_button_{{member.id}}" style="display: block;">
<button class="btn btn-lg position-absolute top-0 end-0" id="edit_profile" data-id="{{member.id}}" data-username="{{member.username}}">
<i class="fa fa-edit fa-solid" style="color: white; margin-right: 5px;"></i></button>
</div>
{% endif %}
<!--Edit form-->
<div class="form-group" id="edit_{{member.id}}">
</div>
<!--Display username,skills,socials and bio-->
<div id="remove_{{member.id}}" style="display: block;">
<h3 class="username" id="username_{{member.id}}">{{member.username}}</h3>
<p class ="skills" id="skills_{{member.id}}">{{member.skills}}</p>
<p><a class="social-media" href="{{member.instagram}}" id="instagram_{{member.id}}"><i class="fa-brands fa-instagram fa-solid" style="color: #e3c142; margin-right: 5px;"></i></a>
<a class="social-media" href="{{member.itch_profile}}" id="itch_{{member.id}}"><i class="fa-brands fa-itch-io" style="color: #e3c142;"></i></a>
<div class="bio">
<strong class="username" id="secusername_{{member.id}}" style="font-size: large;">{{member.username}}, </strong><p id="bio_{{member.id}}">{{member.bio}}</p>
</div>
</div>
</div>
</div>
{% endfor %}
views.py:
#csrf_exempt
def edit_profile(request, member_id):
if request.method != "POST":
return JsonResponse({"error": "POST request required."}, status=400)
team_members = Team.objects.get(id = member_id)
body_unicode = request.body.decode('utf-8')
body = json.loads(body_unicode)
username = body['username']
skills = body['skills']
instagram = body['instagram']
itch_profile = body['itch_profile']
bio = body['bio']
Team.objects.filter(id=member_id).update(username=f'{username}',skills=f'{skills}',instagram=f'{instagram}',itch_profile=f'{itch_profile}',bio=f'{bio}')
return JsonResponse({"message": "Successful", "username": username, "skills": skills, "instagram":instagram, "itch_profile":itch_profile, "bio": bio}, status=200)
You're assigning the instagram variable to the href attribute of the edit_instagram element, rather than its value. Since the fetch request is sending the value of the edit_instagram element, the Instagram URL will not be updated in the backend if the instagram variable is assigned to the href attribute.
So you can change the line of code where you assign the instagram variable to the following:
var instagram = document.getElementById(`instagram_${memberID}`).value;
Also, you need to update the 'instagram' element value after successful fetch call:
instagram.href = result.instagram;
This should update the Instagram URL field in the backend without requiring a page reload.
Assigned the instagram variable to the element itself instead of its href:
var instagram = document.getElementById(`instagram_${memberID}`)
Then, updated the href after the fetch call as Nova suggested:
instagram.href = result.instagram;
I would like to auto-calculate my deposit amount height in a form. Therefore, I included JavaScript to make it happen.
The idea: After entering the net into the form, the suitable deposit height will be displayed in the amount field. And there is nothing to do for the user here.
I really appreciate any suggestions since I am total beginner with Django.
I tried to access the field via known methods like netObj.fishing_type and ['fishing_type'] but I feel like this is not the issue. Somehow I can't access the model fields of the triggered record.
html file:
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content%}
<p> </p>
<div class ="form-group">
<form method="POST" action="{% url 'put_deposit' %}" enctype="multipart/form-data">
{% csrf_token %}
{{form|crispy}}
<script>
// Get the input elements by targeting their id:
const net_input = document.getElementById('id_net');
const vessel_input = document.getElementById('id_vessel');
const amount = document.getElementById('id_amount');
// Create variables for what the user inputs, and the output:
let netObj = 0;
let vesselObj = 0;
let height = 0;
// Add an event listener to 'listen' to what the user types into the inputs:
net_input.addEventListener('input', e => {
netObj = e.target.value;
console.log(netObj);
updateAmount()
});
// Update the value of net based on what the user inputs in for gross and tier
function updateAmount(e) {
if ((Date.now() - netObj.prod_date)>3) {
height = 900;
} else {
height = 600;
}
term = netObj['fishing_type];
if(term == 'Surrounding' || term == 'Trawl'){
height = height *2;
} else if(term == 'Longline' || term=='Seine' ){
height = height *1.5;
} else{
height = height *1.25;
}
amount.value = height;
}
</script>
<button type="Submit" class="btn btn-outline-dark">Submit</button></div>
{% endblock content%}
Extract of models.py:
class Net(models.Model):
net_id = models.IntegerField(primary_key=True, default = None)
prod_date = models.DateField()
weight = models.DecimalField(default=0, max_digits=6, decimal_places=2)
material = models.CharField(max_length=100)
fishing_type = models.CharField(max_length=100, default=None)
def __str__(self):
return '{}: {}'.format(self.fishing_type, self.material)
class Deposit(models.Model):
dep_id = models.BigAutoField(primary_key=True, default=None)
dep_date = models.DateField()
harbour = models.CharField(max_length=100)
vessel = models.ForeignKey(Vessel, to_field='VID', on_delete=models.CASCADE)
net = models.ForeignKey(Net, to_field='net_id', on_delete=models.CASCADE)
amount = models.DecimalField(default=0, max_digits=8, decimal_places=2)
forms.py:
from django.forms import ModelForm
from myapp.models import *
class UploadForm(ModelForm):
class Meta:
model = Deposit
fields = ['dep_date', 'harbour',
'vessel', 'net',
'amount']
I want to create a pop up which opens up clicking the button 'Dissolve'. The pop up should say: 'Are you sure you want to delete this field?' and have two buttons: Okay and Cancel. If Cancel is chosen it should simply close the pop up. If Okay is clicked, it should redirect to the previous page and delete that job on the previous page's table.
My current code for the button is:
<button type="button" class="btn btn-primary">Dissolve</button>
My current code for the job in module.py is:
class Job(models.Model):
def __unicode__(self):
return self.name
name = models.CharField('Job Name',max_length=128)
# when the job was created
date_created = models.DateTimeField('Date Created', auto_now=True)
# what entity/organization needs this job?
client_organization = models.CharField('What organization do you represent?', max_length=64)
# short description
description = models.TextField('Job Description', max_length=256)
# end product to be delivered
deliverable = models.TextField('Deliverable', max_length=256)
# when Job is due for completion
duedate = models.DateTimeField('Date Due')
# all persons who may be affected by project
#stakeholders = models.TextField('Stakeholders')
# important technical requirements
#additional_information = models.TextField('Additional Information', blank = True)
# budget estimate
#budget = models.CharField('Budget', max_length=64)
# file attachments
#attachments = models.FileField(upload_to='job', blank = True)
creator = models.ForeignKey(User,related_name = 'jobs')
organizations = models.ManyToManyField(Organization, through = 'JobRequest', blank=False, null=True)
#organizations = models.CharField(default="nothing",null=True,max_length = 256)
contact_information = models.CharField('Contact Information', max_length = 256, blank = False, null=True)
skill_required = models.CharField('Volunteer skills required', max_length=256, blank = False, null=True)
hours_day = models.CharField('Number of hours per day', max_length=256, blank = False, null=True)
# Job is closed after a jr is confirmed
closed = models.BooleanField(default = False)
# some tags to determine what organizations to submit job to
categories = models.ManyToManyField(Category, related_name = 'jobs')
#categories = models.CharField(default="nothing",null=True, max_length = 256)
status = models.IntegerField(default = 0, choices = ((0, 'Pending'), (1, 'Approved'), (2, 'Disapproved'), (3, 'Closed')))
active = models.BooleanField(default = False)
class Meta:
permissions = (
( 'view_job','Can view Job' ),
( 'edit_job','Can edit Job'),
( 'is_creator', 'Is a creator of Job')
)
My current code for the previous page's HTML is:
<div class="col-sm-6">
<div class="panel panel-primary">
<div class="panel-heading">
Your Jobs
</div>
<div class="panel-body">
<ul class="list-group">
{% for job in jobs %}
<a class="list-group-item" href="{% url 'job_dash' job.id %}">
{{ job.name }}
</a>
{% endfor %}
<br>
<a href = '/job_creation' class="btn btn-danger"> <i class="fa fa-
plus"></i> Create Job</a>
</ul>
</div>
I am modifying a FormSet using JavaScript/jQuery by dynamically adding a form to a Django FormSet. For example, I start with one form asking about a User's education. The User can then press an add button to add an identical form to input information about secondary schooling (e.g. grad school). The form gets added in the browser and I can input data, but when I POST the data, it only shows one form in the FormSet with the information from the second form in the browser.
POST DATA
edu-0-degree u'Doctorate'
first_name u'User'
last_name u'One'
Submit u'Submit'
edu-0-date_started u'01/01/12'
edu-MIN_NUM_FORMS u'0'
edu-0-school u'School Two'
edu-INITIAL_FORMS u'0'
edu-MAX_NUM_FORMS u'1000'
edu-0-date_finished u'01/01/16'
edu-0-id u''
edu-TOTAL_FORMS u'2'
csrfmiddlewaretoken u'qgD2supjYURWoKArWOmkiVRoBPF6Shw0'
I'm then getting an error saying:
ValidationError: [u'ManagementForm data is missing or has been tampered with'].
Here are the relevant pieces of code:
views.py
def build_profile(request):
EducationFormset = modelformset_factory(EducationModel, AddEducationForm, extra=1)
if request.method == "POST":
education_formset = EducationFormset(request.POST, prefix='edu')
for form in education_formset:
if form.is_valid() and form.has_changed():
education = EducationModel(
school = form.cleaned_data['school'],
date_started = form.cleaned_data['date_started'],
date_finished = form.cleaned_data['date_finished'],
degree = form.cleaned_data['degree'],
user = current_user
)
education.save()
return HttpResponseRedirect(reverse('private', args=[current_user.username]))
context = {
'edu_formset' : forms['education'],
}
return render(request, "build_profile.html", context)
(Here I've tried with and without the form.has_changed() piece with the same result.)
Template build_profile.html
<h2>Education</h2>
{{ edu_formset.management_form }}
{% for form in edu_formset.forms %}
<div id="{{ form.prefix }}-row" class="dynamic-form">
{{ form|crispy }}
<div {% if forloop.first %} class="hidden" {% endif %}>
<button type="button" class="btn btn-default btn-sm delete-row">
<span class="glyphicon glyphicon-minus" aria-hidden="true"></span>
</button>
</div>
</div>
{% endfor %}
<div class="btn-group btn-group-xs" role="group" aria-label="...">
<button type="button" class="btn btn-default add-row">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
</button>
</div>
build_profile.js (The code to dynamically add forms to the FormSet)
function updateElementIndex(el, prefix, ndx) {
var id_regex = new RegExp('(' + prefix + '-\\d+)');
var replacement = prefix + '-' + ndx;
if ($(el).attr("for")) $(el).attr("for", $(el).attr("for").replace(id_regex, replacement));
if (el.id) el.id = el.id.replace(id_regex, replacement);
if (el.name) el.name = el.name.replace(id_regex, replacement);
}
function addForm(btn, prefix) {
var formCount = parseInt($('#id_' + prefix + '-TOTAL_FORMS').val());
var row = $('.dynamic-form:first').clone(true).get(0);
$(row).removeAttr('id').insertAfter($('.dynamic-form:last')).children('.hidden').removeClass('hidden');
$(row).children().not(':last').children().each(function() {
updateElementIndex(this, prefix, formCount);
$(this).val('');
});
$(row).find('.delete-row').click(function() {
deleteForm(this, prefix);
});
$('#id_' + prefix + '-TOTAL_FORMS').val(formCount + 1);
return false;
}
function deleteForm(btn, prefix) {
$(btn).parents('.dynamic-form').remove();
var forms = $('.dynamic-form');
$('#id_' + prefix + '-TOTAL_FORMS').val(forms.length);
for (var i=0, formCount=forms.length; i<formCount; i++) {
$(forms.get(i)).children().not(':last').children().each(function() {
updateElementIndex(this, prefix, i);
});
}
return false;
}
$(document).ready( function () {
$('.add-row').click( function () {
return addForm(this, 'edu')
});
$('.delete-row').click( function () {
return deleteForm(this, 'edu')
});
});
What am I doing wrong?
You're getting the ValidationError because edu_TOTAL-FORMS = 2 and only 1 form from the formset is in your post args. View source in the browser and make sure that the names of your forms are prefixed properly. It looks like both forms have the edu-0 prefix and when you submit only the last one on the form is posted.
I want to set up two div entries on a page that are refreshed from a database at different rates.
I'd like to have one div display random entries from the database every second, and below that, every 10 seconds a random entry is selected and has 500 points added to its score.
I can do the second (lottery_Winner):
<div id="lottery_Winner" class = "tableCenter">
{% for entry in lottery_winner %}
<li class = "lot"> <a> {{"WINNER"}}</a> </li>
<li class = "lot"> <span id="entry-text">{{ entry.text }}</span> <span id="score">{{ entry.score }}</span></li>
<script>
$(document).ready(function() {
var currentid = {{entry.id}};
var args = {'lotteryid':currentid};
$.get("/lotteryWinner/", args).done(function(data) {
$("#score").text(data);
});
});
</script>
{% endfor %}
</div>
<script>
setTimeout(function() {
$.ajax({
url: "",
context: document.getElementById("lottery_Winner"),
success: function(data){
$("#lottery_Winner").html(data);
}
});
}, 5000);
</script>
but when I do the first (lottery_Cycle), I get unexpected results - they both refresh the same time (undesired), there is a "ghost" element for one or both of the divs, and the lottery_cycle div entry can get the 500 points, the Winner and Cycle have the same entries and the page refresh cascades until it hangs periodically.
Here's the code I tried:
<div id="lottery_Cycle" class = "tableCenter">
{% for entry in lottery_winner %}
<li class = "lot"> <a> {{"LOTTERY"}}</a> </li>
<li><a href="/entries/{{ entry.id }}/"> <div class = "lot" style = "text-align: left";>{{ entry.text }}
<div style="float: right">{{ entry.score }}</div></a></li>
{% endfor %}
</div>
<div id="lottery_Winner" class = "tableCenter">
{% for entry in lottery_winner %}
<li class = "lot"> <a> {{"*** LOTTERY WINNER ***"}}</a> </li>
<li class = "lot"> <span id="entry-text">{{ entry.text }}</span> <span id="score">{{ entry.score }}</span></li>
<script>
$(document).ready(function() {
var currentid = {{entry.id}};
var args = {'lotteryid':currentid};
$.get("/lotteryWinner/", args).done(function(data) {
$("#score").text(data);
});
});
</script>
{% endfor %}
</div>
<script>
setTimeout(function() {
$.ajax({
url: "",
context: document.getElementById("lottery_Winner"),
success: function(data){
$("#lottery_Winner").html(data);
}
});
}, 5000);
setTimeout(function() {
$.ajax({
url: "",
context: document.getElementById("lottery_Cycle"),
success: function(data){
$("#lottery_Cycle").html(data);
}
});
}, 1000);
</script>
and here is relevant part of views.py;
def lottery(request):
context = {
'lottery_cycle': Entry.objects.random(),
'lottery_winner': Entry.objects.random(),
}
return render(request, 'entries/lottery.html', context);
def lotteryCycle(request):
c = Entry.objects.random()[0]
return HttpResponse("%s,%s,%s" % (c.id, c.text, c.score))
def lotteryWinner(request):
lottery_id = request.GET.get('lotteryid')
if request.method=='GET':
l = Entry.objects.get(pk=lottery_id)
l.score +=500
l.save()
return HttpResponse(l.score)
else:
pass
return HttpResponse('done')
(I tried setInterval as well as setTimeout, same result) Is there any advice on getting the two div refreshes working properly on different timings?