How can i send a information in Html to Django(backend)? - html

How do I send a clicked link in html or selected information in the ComboBox to Django?
views.py
def musicList(request):
musics = Song.objects.filter()
print(musics)
con = sqlite3.connect(str(request.user)+".db")
cursor = con.cursor()
cursor.execute("Select name From sqlite_master Where type='table';")
tables = list()
for i in cursor.fetchall():
tables.append(i[0])
context = {
"musics":musics,
"tables":tables,
}
return render(request,"musicList.html",context)
musicList.html
{% for music in musics %}
<tr>
<th scope="row">{{music.id}}</th>
<td>{{music.artist}}</td>
<td>{{music.song_name}}</td>
<td>{{music.song_type}}</td>
<td>{{music.owner}}</td>
<td>
<div class="dropdown">
<button type="button" class="btn btn-primary btn-sm dropdown-toggle" data-toggle="dropdown">
Choice a Music List
</button>
<div class="dropdown-menu">
{% for table in tables %}
<a class="dropdown-item" href="add_to_list/{{music.id}}" value="{{table}}">{{table}}</a>
{% endfor %}
</div>
</div>
</td>
</tr>
{% endfor %}
What do I do to return the value corresponding to the "value" of the link that the user clicked from the "dropdown-menu" to a different function in views.py

There are several methods to communicate from the template to the view.
1. Post method:
Make a form with inputs, check-boxes.. etc and their values, and retrieve the values in the view:
request.POST.get('value')
2. Via Url:
urls.py
urlpatterns = [
...
path('add_to_list/<int:music_id>/<str:value>', views.musicList, name='musicList'),
...
]
views.py
def detail(request, music_id, value):
...
More advanced explanation in the official documentation here.
You can also use
Query Parameters:
localhost:8000/?id=123
request.GET.get('id')

Related

Specify the pages that navbar items should appear on with Bootstrap in Django

I am trying to specify the page that this navbar dropdown should appear on. I tried adding this line:
{% if request.resolver_match.url_name == 'club_selection' %} class = "active" {% endif %} but that doesn't seem to do anything for me. Maybe I am using it wrong. If anybody knows how to do this correctly it would be a massive help.
club_selection_dropdown.html
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item dropdown">
<li {% if request.resolver_match.url_name == 'club_selection' %} class = "active" {% endif %}>
<a class="nav-link" href="/" id="club--dropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
Current Clubs <span class="bi-arrow-down-circle-fill"></span>
</a>
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="club-dropdown">
{% for club in clubs %}
<form action = "{% url 'group_check' user.id %}" method = "post">
{% csrf_token %}
<input type="hidden" name="club_name" value="{{ club.club_name }}">
<style>
.btn:hover {
background-color: lightgrey;
}
.btn-group.special {
display: flex;
}
.special .btn {
flex: 1;
}
</style>
<div class="btn-group special" role="group">
<input type = "submit" value = "{{club.club_name}}" class="btn col-xs-11 text-left" style=".btn-primary:hover; text-align:left; padding-left:6px">
</div>
</form>
{% endfor %}
</ul>
</li>
</li>
</ul>
</div>
views.py
def club_selection(request):
list_of_clubs = ClubList()
clubs = list_of_clubs.club_list
return render(request, 'club_selection.html', {'clubs':clubs})
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.home, name = 'home'),
path('log_in/', views.LogInView.as_view() , name = 'log_in'),
path('sign_up/', views.sign_up, name = 'sign_up'),
path('log_out/', views.log_out, name = 'log_out'),
path('show_current_user_profile/', views.show_current_user_profile, name = 'show_current_user_profile'),
path('user/<int:user_id>', views.ShowUserView.as_view(), name='show_user'),
path('officer_user/<int:user_id>', views.ShowOfficerView.as_view(), name='show_user_officer'),
path('member_list/', views.MemberListView.as_view(), name = 'member_list'),
path('officer/', views.officer, name = 'officer'),
path('officer_promote_applicants/', views.ApplicantListView.as_view(), name = 'officer_promote_applicants'),
path('officer_main/', views.OfficerMainListView.as_view(), name = 'officer_main'),
path('reject_accept_handler/<int:user_id>', views.reject_accept_handler, name = 'officer_promote_applicants'),
path('profile/',views.profile,name = 'profile'),
path('password/', views.password, name='password'),
path('owner/', views.owner, name = 'owner'),
path('officer_list/', views.OfficerListView.as_view() ,name = 'officer_list'),
path('owner_member_list', views.OwnerMemberListView.as_view(), name = 'owner_member_list'),
path('promote_member/<int:user_id>', views.promote_member, name = 'promote_member'),
path('demote_officer/<int:user_id>', views.demote_officer, name = 'demote_officer'),
path('transfer_ownership/<int:user_id>', views.transfer_ownership, name = 'transfer_ownership'),
path('club_selection/', views.club_selection, name = 'club_selection'),
# path('club_dropdown/', views.club_dropdown, name = 'club_dropdown'),
path('group_check/<int:user_id>', views.group_check, name = 'group_check'),
path('application_form/', views.application_form, name = 'application_form'),
path('create_new_club/', views.create_new_club, name = 'create_new_club')
You can do it like that :
{% if 'club-selection' in request.path %}class="active"{% endif %}
So if the term appears in the path of your url show the active class.
Note : Do that only if you want to set active class to a bunch of endpoint sharing the same namespace.
Else you can do that :
{% if 'club-selection' == request.path %}class="active"{% endif %}
There is good chance that your template processor is not setup properly, so make sure you have the following in your settings.py within the template variable and inside the context_processors :
"context_processors": [
....
"django.template.context_processors.request",
....
]
Relaunch your server and try again

how to pass value from html to view in django?

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>

Calling a function from HTML

HTML:
<button type="button" class="btn btn-primary">Notifications
<span class="badge badge-light"></span>
</button>
python:
def notif():
not_num = False
if count > 0:
return count
else
return not_num
def count():
return 8
Can I get a way to call "notif" function into HTML body?
What I want is to do an "if" inside an HTML button that tells me how many notifications I have and if I don´t have any, it doesn´t show me anything.
You probably need to use built-in if template tag.
Something like:
{% if notifications %}
<button type="button" class="btn btn-primary">Notifications ({{ notifications|length }})
<span class="badge badge-light"></span>
</button>
{% else %}
No notifications.
{% endif %}
This way it will show you the button if you have notifications.
For more info read this
You can also create custom template tags for more complex problems, read this

Django - System architecture for reusing user registration form on multiple pages

I was figuring how to reuse the same registration form and view on multiple templates and pages, and in different formats. E.g. on the page, in a modal etc. I am however some trouble in figuring out the best practice for solving this problem. One thing I am actively trying to avoid is repeating myself, but I can't seem to find a solution that is satisfying enough.
At the moment I have one central view that handles user registrations that looks like this. At the moment it can only handle to output one form on the signup_form template, but I want to extend that to the index page and be able to be outputted in a modal as well.
Views.py
def signup(request):
template_name = 'core/authentication/signup_form.html'
custom_error_list = []
if request.method == "POST":
form = SignUpForm(request.POST)
if form.is_valid():
#Check for duplciate email
email = form.cleaned_data.get('email')
username = form.cleaned_data.get('username')
if email and User.objects.filter(email=email).exclude(username=username).exists():
custom_error_list.append("A user with that email already exists")
else:
user = form.save(commit=False)
user.is_active = False
user.save()
current_site = get_current_site(request)
subject = 'Activate your StockPy Account'
sender = '' #Insert sender address here
message = render_to_string('core/authentication/account_activation_email.html', {
'user': user,
'domain': current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'token': account_activation_token.make_token(user)
})
user.email_user(subject, message)
return redirect('authentication:account_activation_sent')
else:
form = SignUpForm()
return render(request, template_name, {'form': form, 'custom_error_list': custom_error_list})
#Activate the user as he/she clicks the email verification link which lead to tihs view
def activate(request, uidb64, token):
try:
#Using a [:1] is ad-hoc solution to get rid of the starting 'b' symbol
uid = force_text(urlsafe_base64_decode(uidb64[1:]))
user = User.objects.get(pk=uid)
except (TypeError, ValueError, OverflowError, User.DoesNotExist):
user = None
if user is not None and account_activation_token.check_token(user, token):
user.is_active = True
user.profile.email_confirmed = True
user.save()
login(request, user)
return redirect(template_name)
else:
return render(request, 'core/authentication/account_activation_invalid.html')
forms.py
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from django import forms
class LoginForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = ['email','password']
class SignUpForm(UserCreationForm):
email = forms.EmailField(max_length=254, widget=forms.TextInput(attrs={'placeholder': 'Email...', 'class' : 'form-control', 'pattern' : '[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,3}$'}))
class Meta:
model = User
fields = ['email', 'username', 'password1', 'password2']
def __init__(self, *args, **kwargs):
super(SignUpForm, self).__init__(*args, **kwargs)
self.fields['username'].widget = forms.TextInput(attrs={
'class': 'form-control',
'placeholder': 'Username...',
})
self.fields['password1'].widget = forms.TextInput(attrs={
'class': 'form-control',
'placeholder': 'Password...',
'type': 'password',
})
self.fields['password2'].widget = forms.TextInput(attrs={
'class': 'form-control',
'placeholder': 'Password again...',
'type': 'password',
})
My signup form currently looks like this.
signup_form.html
{% extends 'base.html' %}
{% load static %}
<!-- End Navbar -->
{% block page-header %}
<div class="section section-signup" style="background-image: url({% static 'core/assets/img/bg8.jpg' %}); background-size: cover; background-position: top center; min-height: 700px;">
<div class="container">
<div class="row">
<div class="card card-signup" data-background-color="orange">
<form class="form" method="POST" action="">
{% csrf_token %}
<div class="header text-center">
<h4 class="title title-up">Sign Up</h4>
<div class="social-line">
<a href="#twitter" class="btn btn-neutral btn-twitter btn-icon btn btn-round">
<i class="fa fa-twitter"></i>
</a>
<a href="#facebook" class="btn btn-neutral btn-facebook btn-icon btn-lg btn-round">
<i class="fa fa-facebook-square"></i>
</a>
<a href="#google" class="btn btn-neutral btn-google btn-icon btn-round">
<i class="fa fa-google-plus"></i>
</a>
</div>
</div>
<div class="card-body">
<!-- Output error messages -->
{% for field in form %}
<div style="color:red; list-decorations:none;" class="text-center">
{{ field.errors.as_text }}
</div>
{% endfor %}
{% for error in custom_error_list %}
<div style="color:red;" class="text-center">
* {{ error }}
</div>
{% endfor %}
<!-- Output all fields -->
{% for field in form %}
<div class="input-group form-group-no-border">
<span class="input-group-addon">
<i class="now-ui-icons
{% if field.name == 'email' %} ui-1_email-85{% endif %}
{% if field.name == 'username' %} users_circle-08{% endif %}
{% if field.name == 'password1' %} ui-1_lock-circle-open{% endif %}
{% if field.name == 'password2' %} ui-1_lock-circle-open{% endif %}
"></i>
</span>
{{ field }}
<!-- Give input box red border if data is not valid -->
{% if field.errors %}
<script>
var element = document.getElementById("{{ field.id_for_label }}");
element.classList.add("form-control-danger");
</script>
{% endif %}
</div>
{% endfor %}
<div class="text-center">
Already registered? Log in here
</div>
<!-- If you want to add a checkbox to this form, uncomment this code -->
<!-- <div class="checkbox">
<input id="checkboxSignup" type="checkbox">
<label for="checkboxSignup">
Unchecked
</label>
</div> -->
</div>
<div class="footer text-center">
<button type="submit" class="btn btn-neutral btn-round btn-lg">Get Started</button>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock page-header %}
And a small example snippet of my index.html of how I want to implement it ish.
index.html
<div class="main">
<div class="section section-about-us">
<div class="container">
<div class="col-md-8 ml-auto mr-auto text-center">
{{ form }}
</div>
</div>
</div>
</div>
I have really tried to find a smooth way of doing this, but without result unfortunately.
It seems as though you already know how to implement the same form in multiple templates, but you've having trouble avoiding repetition in your code. To that end, here are some suggestions for reducing the amount of repetition you'll encounter when duplicating this form across multiple pages:
Validate data within your form rather than your view. Currently, you are checking for duplicate e-mail addresses within views.py. If you duplicated your form, you'd have to re-write that code all over again. Instead, why not move it into forms.py in a custom cleaning method (see Django docs on custom form cleaning).
Write functions for actions that will be repeated. For example, currently, you are sending an activation e-mail to your user within views.py. It makes more sense to write a function within your user/models.py called something like send_activation_email(). Whenever you want to send an activation e-mail to a user, you can then call user.send_activation_email() rather than duplicating your entire block of activation e-mail code (see Django docs on model methods).
Use inclusion tags to avoid repetition in your templates. If there's a block of code that you find yourself repeating in your templates, you can use Django's inclusion tags to include a snippet of HTML across multiple templates. This allows you to serve the same form in multiple locations without re-writing your code. If you want to style your form differently across multiple pages, you could wrap it in DIVs with different IDs and use CSS to style the form differently depending on which DIV it's wrapped in. (see Django docs on inclusion tags)

Display pages with specific tag in Django

i'am using bootstrap Tab panes and i need to show posts with specific tag in each pane without reloading the page of course
for more detail i'm using Django with Wagtail CMS my app based on models file
EDIT : add tag dict to context
models.py:
class BlogIndex(Page):
intro = RichTextField(blank=True)
def get_context(self, request):
base_tags = ['foo','boo','voo']
# Update context to include only published posts, ordered by reverse-chron
context = super(BlogIndex, self).get_context(request)
blogpages = self.get_children().live().order_by('-first_published_at')
context['blogpages'] = blogpages
context['base_tags'] = base_tags
return context
class BlogPageTag(TaggedItemBase):
content_object = ParentalKey('BlogPage', related_name='tagged_items')
class BlogPage(Page):
#info
tags = ClusterTaggableManager(through=BlogPageTag, blank=True)
#contentpanel ....
note: i am using taggit but it seems that i didn't well handle it
blog_index.html
<div>
<ul class="nav nav-tabs" role="tablist">
{% for tag in base_tags %}
<li role="presentation" ><a href="#{{tag}}" aria-controls="{{tag}}"
role="tab" data-toggle="tab">{{tag}}</a></li>
{% ednfor %}
</ul>
<!-- Tab panes -->
<div class="tab-content">
{% for tag in base_tags %}
<div role="tabpanel" class="tab-pane" id="{{tag}}">
#this is what i'am thinking of
#for posts in blogpages :
# if post tag == "{{tag}}":
# show post
</div>
</div>
</div>
If you have a few specific tags, you can call them in the template by define them below.
On the other hand if tags will increase continuously, It might be better to create a new model for tags.
class PostListView(ListView):
model = Post
def get_context_data(self, **kwargs):
context = super(PostListView, self).get_context_data(**kwargs)
all_list = Post.objects.all()
news_list = Post.objects.filter(tag='news')
context = {
'all_list': all_list,
'news_list': news_list,
}
return context
Edit:
You can show like this;
{% for object in news_list %}
{{ object.title }}
{{ object.timestamp }}
{% endfor %}