Favorite system in Django - javascript

Image
$(document).ready(function(){
$(".like").click(function(){
$(this).toggleClass("heart");
});
});
.like {
padding-right: 6px;
color: #00000030;
font-size: 1.6em;
padding-top: 5px;
animation: like 0.5s linear;
}
.heart {
color: #FF0000;
animation: heart 0.5s linear;
}
{% for m in musicl %}
<div class="card">
<div class="top">
<div class="year">{{m.Year}}</div>
<span class="like"><i class="fa fa-heart"></i></span>
</div>
<div class="middle">
<a href="https://google.com" id="link" target="_blank">
<div class="img-container"><img src="{{ m.Image.url }}"></div>
</a>
</div>
<a href="https://google.com" id="link" target="_blank">
<div class="bottom">
<div class="title">{{m.Name}}</div>
<div class="genre">{{m.Genre}}</div>
</div>
</a>
</div>
{% endfor %}
models.py
class Music(models.Model):
Name = models.CharField(max_length=100, blank=False)
Year = models.IntegerField(('year'), choices=YEAR_CHOICES, default=datetime.datetime.now().year)
Genre = MultiSelectField(choices=GENRE_CHOICES)
Image = models.ImageField(blank=False, null=True)
def __str__(self):
return self.Name
Views.py
def home(request):
return render(request, template_name='main/home.html', context={"musicl": Music.objects.all})
def wishlist(request, id):
pass
How do I connect the User model to this favorite system and keep track of the favorite list in a view function(wishlist), in other words when someone clicks on the fav icon, I want that specific card to be saved to the wishlist view corresponding to that User model

To connect your UserModel with Frontend we need to push the data (music_id) from UI to backend.
If you want to do this with django-template then you can use django-forms.
https://docs.djangoproject.com/en/3.0/topics/forms/
However it you want to go on some event based such as click, following are steps...
to do this there are couple of things required.
Wishlist additional model required to store wishlist music
views.py to verify input and save wishlist
url-dispatcher url -> views(your bussiness logic) -> models(save data, wishlist in your case)
post-call to django-backend (using ajax, since you want to use store data on icon click)
1. Model Definition
class Music(models.Model):
Name = models.CharField(max_length=100, blank=False)
Year = models.IntegerField(('year'), choices=YEAR_CHOICES, default=datetime.datetime.now().year)
Genre = MultiSelectField(choices=GENRE_CHOICES)
Image = models.ImageField(blank=False, null=True)
def __str__(self):
return self.Name
class WishlistMusic(models.Model):
## this can be depend on your choice eg (user_id, guest_id etc)
some_id = models.IntegerField(('some_id'))
## relation to Music
music = models.ForeignKey(Music, on_delete=models.DO_NOTHING)
2. views.py
from music.models import Music, WishlistMusic
from django.core.exceptions import ObjectDoesNotExist
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def wishlist(request):
music_id = request.POST.get('music_id')
if not music_id:
raise ValueError("Required music_id to set wishlist")
## can be set user id once authentication is set
##some_id = request.user.pk
some_id = 3 ## Say
try:
music = Music.objects.get(pk=music_id)
wishlist_obj = {
'some_id': some_id,
'music': music
}
WishlistMusic(**wishlist_obj).save()
except ObjectDoesNotExist:
## Your action
## raise or Return HTTP response with failure status_code
return HttpResponse('Some error occured, unable to add to wishlist') ## or can set for render
return HttpResponse('Added to wishlist') ## or can set for render
#csrf_exempt used because we are going to POST call using ajax, django-provide Cross Site Request Forgery protection, however its not recommended to use #csrf_exempt in production environment.
more details on https://docs.djangoproject.com/en/3.0/ref/csrf/
3. URL-Dispatcher/Path
here we have model and views under music app so below urls.py for redirect /music url to music app url
for refr. my proj structure as
proj_name -> music_track
from django.contrib import admin
from django.urls import path, include
from music import urls as music_urls
urlpatterns = [
path('admin/', admin.site.urls),
path('music/', include(music_urls)),
]
music/urls.py
from django.contrib import admin
from django.urls import path
from music import views
urlpatterns = [
path('mymusic/', views.home), ## IP:PORT/mymusic your homepage
path('wishlist/', views.wishlist), ## IP:PORT/mymusic your post api to save wishlist
]
4. POST API call from front-end to django.
js
$(document).ready(function(){
$(".like").click(function(){
$(this).toggleClass("heart");
var pk = $(this).find('input[id="abc"]').val();
var data = {
'music_id': pk
};
$.ajax({
type: 'POST',
url: '../wishlist/',
data: data,
success: function(json) {
alert(json); // your actions after save, you can just pop-up some ui element that added to wishlist
}
})
});
});
I just added one ui element (inside like class span) in html to hold the primary key of music which is required to add wishlist in model since we set music_id set as foreign key in WishlistMusic model.
.html
........
<a href="https://google.com" id="link" target="_blank">
<div class="bottom">
<div class="title" id="title">{{m.Name}}</div>
<div class="genre" id="genre">{{m.Genre}}</div>
</div>
</a>
<span class="like" id="abc"><input type="hidden", id="abc", value="{{m.pk}}"/>aa<i class="fa fa-heart"></i></span>
.......
Following are the references you can go through for further details
https://simpleisbetterthancomplex.com/tutorial/2016/08/29/how-to-work-with-ajax-request-with-django.html
https://docs.djangoproject.com/en/3.0/ref/urls/

I think best you can do is to manually create a new row in the music object in a script like this, and put that behind the JavaScript click event:
from app.models import Music
Music.objects.create(Name=name_variable, Year=year_variable, Genre=genre_variable, Image=image_variable)
Music.save()

Related

Django Ajax success send context in new url

I have a first page with a Launch button, the process is done and them all is redirect to a result page where I can download the different results. Without Ajax and with "regular" Django, the process is working. However, because of other functionalities in the first page, I have to work with Ajax. And if I do not redifined the success part of Ajax, nothing is appenning..
I have a function view for the first page :
def launchCtd(request):
"""
This Function is activate when user click on the launch button of the convertToDose page.
It receive the request, create the JSON file and launch the ConvertToDose Analysis. Then it redirect to the Result page
"""
if request.method == 'POST':
#DO stuff
context = {
'filename': img_out_path,
'protocol_file': json_pactrlRectth,
}
#return render(request, 'result.html', context)
return JsonResponse(context, safe=False)# I trie to pass the url but it was not a success...
else:
#Ini Forms
context = {
#Send Forms
}
return render(request, 'template.html', context)
the template of the first page (only ajax part)
$.ajax({
url: "",
type: "POST",
data: formData,
processData: false,
contentType: false,
beforeSend: function (xhr, settings) {
xhr.setRequestHeader("X-CSRFToken", $('input[name="csrfmiddlewaretoken"]').val());
},
success: function(data){
//print okay with JSONResponse in view
console.log(data.protocol_file)
//First try to send data in new url => undefined element, after = I tried with data and with template data in the 1st page
//protocol_file = $("input[name='json_path']")
//filename = $("input[name='img_path']")
//Second try to send data in new url => undefined
$('#protocol_file').html(data.protocol_file);
$('#filename').html(data.filename);
//Third try => GetElementById is undifined error
//document.GetElementById("protocol_file").innerHTML = $("input[name='json_path']")
//document.GetElementById("filename").innerHTML = $("input[name='img_path']")
//Fourth try => synthaxe error, I also tried with a + like in some forum but it consider like a str and concat all...
window.location.href="/filmchromique/result/" {data:data}
#this one is working but with no data sended ....
//window.location.href="/filmchromique/result/"
},
error: function (data, textStatus, jqXHR) {
console.log(data)
}
});
The view of the result page :
class displayResultPage(TemplateView):
template_name = 'result.html'
def post(self, request, *args, **kwargs):
self.object = self.get_object()
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
def get_context_data(self, **kwargs):
kwargs = super(displayResultPage, self).get_context_data(**kwargs)
return kwargs
def post(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
bar = self.request.POST.get('foo', None)
if bar: self.template_name = 'result.html'
return self.render_to_response(context)
In my template result, I have nothing particular, only maybe these part could be interesting :
<div style="padding-bottom: 30%" class="row gx-5 justify-content-center">
{% if protocol_file is not null %}
<p id="protocol_file">Your file is here : {{ filename }}</p>
{% else %}
<h1 style="color: indianred">You must launch an analysis before accessing an image on this page</h1>
{% endif %}
{% if protocol_file is not null %}
<div class="row gx-5 justify-content-center">
<div class="col-lg-4 col-xl-6">
<a class="btn btn-primary btn-md" href="{% url 'json:downloadFile' protocol_file %}">Save protocol to local</a>
</div>
<br>
<div class="col-lg-4 col-xl-6">
<a class="btn btn-primary btn-md" href="{% url 'json:downloadFile' filename %}">Save image to local</a>
</div>
<br>
</div>
I do not find a way to send the context. If you have any idea how I can do it please
Have a good day
EDIT
The problem seems not to be in the Ajax side but in the result view, here named displayResultPage. I used the debugger, and in the second post def, data are in the request (POST). So I had the idea to add them in the current context :
def post(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
context["filename"] = self.request.POST.get("img_path")
context["protocol_file"] = self.request.POST.get("json_path")...
But the data are not displayed in the template.
When I use the debbugger, following the workflow :
the post function is called -> self.get_context_data called in the
post function -> return self.render_to_response of the post function
-> something done in class TemplateView -> come back in the get_context_data of displayResultPage -> something done in class
TemplatView -> page displayed
in the "come back in the get_context_data of displayResultPage" step, I do not find my data given to the context in the "the post function is called" step.
If you have any idea why, I think it is the solution here :) If I find a way I will post it.
Thanks

How to after django form is submitted to be redirected to another webpage and have form data to be sent to backend database

Aim: for when django form is submitted for data to be sent and saved to admin side.
problem: i can redirect it to another page after form is submitted but when i go onto admin side the data is not saved. how can i fix this? using django or javascript?
html:
<form method="post" >
{% csrf_token %}
{{form.as_p}}
<input class="btn" type="submit" value="Log In">
</form>
models.py:
from django.db import models
from django import forms
class Customer(models.Model):
first_name = models.CharField(max_length=200, verbose_name='')
last_name = models.CharField(
max_length=200, verbose_name='')
def __str__(self):
return self.first_name + ', ' + self.last_name
forms.py:
from django.forms import ModelForm
from django import forms
from .models import Customer
class CustomerForm(ModelForm):
class Meta:
model = Customer
fields = '__all__'
views.py:
from django.shortcuts import render
from .forms import CustomerForm
def index(request):
form = CustomerForm()
if request.method == 'POST':
form = CustomerForm(request.POST)
if form.is_valid():
form.save()
context = {'form': form}
return render(request, 'app/index.html', context)
Ash this is what it gives me:
if you need any other files just ask
the redirect error i get
After writing form.save() you can say:
return redirect(link to redirect to)
This will redirect you to the chosen place after the form is validated and saved.
Add one line after your form will save
# put link inside -> " "
return redirect("Link")
Change the html as method="POST"
if request.method == 'POST':
form = CustomerForm(request.POST)
if form.is_valid():
form.save()
return redirect('urlname')
else:
form = CustomerForm()
context = {'form': form}
return render(request, 'app/index.html', context)

Ajax POST method to Django. Always results in "Not Ajax"

I have been trying to create an AJAX function which sends two JS variables, Score and Mistake, back to the Django backend and to update an extended user model with them.
To do this I started with an AJAX function which looks like this:
$(document).ready(function() {
$("#test").submit(function(event){
event.preventDefault();
console.log("form submitted!");
$.ajax({
type:"POST",
url:"/update/quiz/",
data: {
csrfmiddlewaretoken: window.CSRF_TOKEN,
'score': score,
'mistake' : mistake
},
success: function(){
$('#message').html("<h2>Contact Form Submitted!</h2>")
}
});
return false;
});
});
Views.py
class Quiz(TemplateView):
template_name='quiz.html'
def post(self, request, *args, **kwargs):
if request.is_ajax():
message = "Yes, Ajax!"
else:
message = "Not Ajax!"
return HttpResponse(message)
URLS.py
from django.urls import path
from home.views import HomepageName, Homepage, Quiz
from . import views
urlpatterns = [
path('quiz/', Quiz.as_view()),
path('update/quiz/', Quiz.post),
path('<slug:slug>/', HomepageName.as_view()),
path('', Homepage.as_view()),
]
And the template
<form method='POST' id ='test'>
{% csrf_token %}
<input type='submit' value='Test button'/>
<div id = 'message'>Initial text</div>
</form>
I've already tried to move around the URL routing and add a new URL thinking that would work but when the Submit button is clicked then it always loads a new page and then on that page it shows "Not Ajax!"
I assume that it is doing the default HTML form action and not the AJAX since their is no output to the console either which I added to get some more information
Thanks for all your help. Please comment if I need to provide more information!

django messages for a successfully delete,add or edit item

I have started using django messages for creating items.
It works great for creating adding a new item.
but.. I want to have functions for each action -
delete,create,edit ( I have different buttons for each)
I have only post function.. it really confuse me when I try to create a message that the item has been deleted successfuly.. how can I know a delete was submitted and not post? since everything goes through post function.
The PostEdit and Delete don't have the "request" that it requires for messages.
So for now I h ave only messages.succuess that runs everytime I create a server.
I want to have a different message for delete, edit, create and same for errors.
Does anyone have a clue?
index.html -
{% if messages %}
<ul class="messages">
{% for message in messages %}
<div class="alert alert-success alert-dismissible fade show" role="alert">
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
{% endfor %}
</ul>
{% endif %}
views.py -
# Create your views here.
from django.shortcuts import render_to_response
from django.shortcuts import get_object_or_404
from django.shortcuts import render, redirect
from django.template import RequestContext
from django.views.generic import TemplateView, UpdateView, DeleteView, CreateView
from DevOpsWeb.forms import HomeForm
from DevOpsWeb.models import serverlist
from django.core.urlresolvers import reverse_lazy
from simple_search import search_filter
from django.db.models import Q
from django.contrib import messages
class HomeView(TemplateView):
template_name = 'serverlist.html'
def get(self, request):
form = HomeForm()
query = request.GET.get("q")
posts = serverlist.objects.all()
forms = {}
if query:
posts = serverlist.objects.filter(Q(ServerName__icontains=query) | Q(Owner__icontains=query) | Q(Project__icontains=query) | Q(Description__icontains=query) | Q(IP__icontains=query) | Q(ILO__icontains=query) | Q(Rack__icontains=query))
else:
posts = serverlist.objects.all()
for post in posts:
forms[post.id] = HomeForm(instance=post)
args = {'form' : form,'forms': forms, 'posts' : posts}
return render(request, self.template_name, args)
def post(self,request):
form = HomeForm(request.POST)
posts = serverlist.objects.all()
forms = {}
if form.is_valid(): # Checks if validation of the forms passed
post = form.save(commit=False)
post.save()
messages.success(request,'{0} has been added successfully!'.format(post.ServerName))
return redirect('serverlist')
messages.error(request,'Servername is required, please refresh the page and try again.')
for post in posts:
forms[post.id] = HomeForm(instance=post)
args = {'form' : form, 'forms': forms, 'posts' : posts}
return render(request, self.template_name,args)
class PostDelete(DeleteView):
model = serverlist
success_url = reverse_lazy('serverlist')
class PostEdit(UpdateView):
template_name = 'serverlist.html'
model = serverlist
form_class = HomeForm
#messages.success(request,"The server has been edited successfully")
#fields = ['ServerName','Owner','Project','Description','IP','ILO','Rack','Status']
success_url = reverse_lazy('serverlist')
Override the delete method in the deleteview for changing the message type:
class PostDelete(SuccessMessageMixin, DeleteView):
model = serverlist
success_url = reverse_lazy('serverlist')
success_message = "Object deleted"
def delete(self, request, *args, **kwargs):
messages.warning(self.request, self.success_message)
return super(PostDelete, self).delete(request, *args, **kwargs)
You can do the same by overriding the update method for UpdateView.
class PostEdit(UpdateView):
template_name = 'serverlist.html'
model = serverlist
form_class = HomeForm
#messages.success(request,"The server has been edited successfully")
You can't call messages.success in the class definition like that. The call has to go in a method like post or form_valid.
The messages framework has a SuccessMessageMixin which you might find useful. You add the mixin to each view, and set success_message:
class PostDelete(SuccessMessageMixin, DeleteView):
model = serverlist
success_url = reverse_lazy('serverlist')
success_message = "Object deleted"
See the docs on adding messages to class-based views for more info.

How to integrate Django form with Ajax?

I've gone through many tutorials in how to integrate ajax with django form but all were complicated. I have a Signup model with Signup form and a views like the following.
models.py
from django.db import models
class SignUp(models.Model):
name = models.CharField(max_length=120, blank=True, null=True)
email = models.EmailField()
def __unicode__(self):
return self.email
and forms.py
from django import forms
from .models import SignUp
class SignUpForm(forms.ModelForm):
class Meta:
model = SignUp
fields = ['name', 'email']
def clean_name(self):
name = self.cleaned_data.get('name')
return name
def clean_email(self):
email = self.cleaned_data.get('email')
try:
match = SignUp.objects.get(email=email)
except SignUp.DoesNotExist:
return email
raise forms.ValidationError('This email address is already subscribed.')
views.py
from django.shortcuts import render
from django.core.mail import send_mail
from django.conf import settings
from .forms import SignUpForm
def index(request):
form = SignUpForm(request.POST or None)
if form.is_valid():
name = form.clean_name()
email = form.clean_email()
instance = form.save()
subject = 'Bruke Church news'
from_email = settings.EMAIL_HOST_USER
to_email = [email]
contact_message = "%s:Thank you for signing up for our newsletter via %s. we'll be in touch" %(
name,
email)
send_mail (subject,
contact_message,
from_email,
to_email,
fail_silently=False)
context = {
"form": form
}
return render(request, "index.html",context)
and my html form looks like this
<form action="" method="POST">
{% csrf_token %}
{{form|crispy}}
<input type="submit" value="Sign up" class="btn btn-primary">
</form>
This code runs well but it loads the full page and I want to load only the form. After googling, I found a concept of Ajax but am really having problem in doing so. please help me Thank you
Example of Ajax Post
on button click submit
this method needs to run
put this in your HTML
function AddData(){
var name = $("#name").val();
var email = $("#email").val();
// You should extract each and every id from your form fields
var signupData = { name:name, csrfmiddlewaretoken: '{{ csrf_token }}',email:email};
$.ajax({
type: "POST",
url: "../../index/",
data: signupData,
success: function(data) {
alert("You Have Sucessfully Signed Up ");
},
statusCode: {
500: function() {
alert("You Have Already Signed Up ");
}
},
})
}
In your Views.py
def index(request):
if request.method == 'POST': # From Frontend we are getting the data in a POST method and we are checking if front end is giving POST Method or not
get_email = request.POST.get('email') # Taking The DATA from front end in form of POST to Django USER EMAIL ADDRESS
get_name = request.POST.get('name')# Taking The DATA from front end in form of POST to Django NAME
queryset_list = SignUp.objects.all().values_list("email",flat=True)# Performing a Django Query and getting all Signup Email Address
if get_email in queryset_list:
return HttpResponse(status=500)
else:
SignUp.objects.create(name=get_name,email=get_email)
return HttpResponse('')

Categories

Resources