Django flash database object - django

I want to make an app where someone can search for something. When he searches he will get all of the things in the database that start with anything he wrote. I am using the messages framework.Here is the backend code:
def home(request):
if request.method == 'POST':
name = request.POST['name']
search = Team.objects.filter(name__startswith=name).all()
if not search:
messages.info(request, 'There wasnt')
else:
#looping all the items that search has
for i in search:
#flash the object
messages.info(request,i)
return render(request,'home.html')
And the HTML code:
{%if messages%}
{%for msg in messages%}
<div class='searching'>
#showing the name and the title of the object
<p style='color:white;margin-left:25px;'>{{msg.name}} {{msg.title}}</p>
</div>
{%endfor%}
{%endif%}
<form action='' method='post'>
{% csrf_token %}
<input class="form-control" type='text' name='name'>
<br>
<button class='btn btn-primary btn-lg'>OK</button>
</form>
But when I run it I don't get anything. Also I don't use extra_tags because I want the name and the title appear in the same div.
What should I do?
Pls can someone reply? I really need a help. Plsss.
Thanks.

Related

How Do You Trigger HTMX Page Refresh After User Updates Any Part of The Page?

I have been working with HTMX and it's pretty cool compared to the dreaded formsets and Javascript. I have it working....My only issue is when the user updates the form anywhere...you have to manually refresh the page to reset the list of todos. My issue is identical to this one...https://stackoverflow.com/questions/66664407/dynamically-update-table-when-creating-new-enty-using-htmx but there is no resolution listed.....
Here's a quick overview of my code...
My view...
def create_to_do(request):
user = User.objects.get(id=request.user.id)
to_dos = NewToDo.objects.filter(created_by=user)
form = ToDoForm(request.POST or None)
if request.method == "POST":
if form.is_valid():
to_do = form.save(commit=False)
to_do.created_by = user
to_do.creation_date = timezone.now()
to_do.save()
return redirect("MyToDoList:detail-to-do", pk=to_do.id)
else:
return render(request, "partials/to_do_form.html", {
"form":form
})
context = {
"form": form,
"user": user,
"to_dos": to_dos,
}
return render(request, "create_to_do.html", context)
Partial detailview....
<button class="button35" hx-get="{% url 'MyToDoList:update-to-do' to_do.id %}" hx-swap="outerHTML">
Update
</button>
<button class="button34" hx-post="{% url 'MyToDoList:delete-to-do' to_do.id %}" hx-swap="outerHTML">
Delete
</button>
</div>
Partial todo form....
<div hx-target="this" hx-swap="outerHTML" class="">
<form method="POST">
{% csrf_token %}
{% if to_do %}
<button class="button35" hx-post="{% url 'MyToDoList:update-to-do' to_do.id %}">
Save
</button>
<button class="button34" hx-get="{% url 'MyToDoList:detail-to-do' to_do.id %}">
Cancel
</button>
</div>
{% else %}
<button class="button35" hx-post=".">
Save
</button>
</div>
{% endif %}
</form>
</div>
My main create form html..
<button class="button36" hx-get="{% url 'MyToDoList:create-to-do-form' %}" hx-swap="beforeend" hx-target="#bookforms">Add Form</button>
<div id="bookforms" class=""></div>
<div class="">
{% if to_dos %}
{% for to_do in to_dos %}
{% include "partials/to_do_detail.html" %}
{% endfor %}
{% endif %}
After a day of playing and pulling my hair out..it's all working as I want...I just need to figure out how to incorporate a dynamic page load if anything changes so that the entire page gets reloaded....so that the records get sorted according to my number field...
Thanks in advance for any thoughts or suggestions.
So thanks to a kind soul on Facebook....I added this Javascript to my code and it works.
$(document).on("click", ".yourclass", function(){
location.reload();
});
In case you need this, I had the problem when I have to update two/mutliple parts of the page after post.
I manage to solve it by trigger_client_event
Thanks to this issue: How do I manually trigger a hx-get event of an element from JavaScript
HTMX rocks!

How to retrieve data from a form in Django

I am working on a weather app where the client will be entering the name of the city in a search bar, and the name will be used to gain weather data from an API. To get the name of the city from the form, I have created this condition in view:
if request.method == 'POST':
city = request.data
print(city)
however when being printed, this error occurs: 'WSGIRequest' object has no attribute 'data'
What am I doing wrong? Or is there a completely different way to do this?
you must get data from template like this: (name of function in views.py is something same as in url.py.
def something(request):
if request.method == 'POST':
city = request.POST.get('data')
print(city)
data is the name of your input tag in template:
<input name='data'>
Update:
you need to have a action for your form. it includes a url. this url connect you to your view function for this form.
also you must add name to your input tag not your form tag.
template:
<form method="POST" action = "{% url "url_something" %}" >{% csrf_token %}
<div class="field has-addons">
<div class="control is-expanded">
<input class="input" type="text" placeholder="City Name" name="data" >
</div>
<div class="control">
<button class="button is-info" type="submit">
Search City
</button>
</div>
</div>
</form>
in url.py you must have a url like this.:
url(r'^something', views.something, name='url_something'),

add multiple forms to page on button click

I am working on developing a permitting app using django. This is my first django project so bear with me here...
we have a default utility permit that contains some basic info like property owner and address. Then from that you can attach a sewer, or water or row or any combination of related tables to the permit. Basically I am looking for a way to return a page with the default utility permit then have a series of links or buttons to add more forms to that page.
I made some model forms for each of the models and can display them individually on the page
forms.py
class UtilityPermitForm(forms.ModelForm):
class Meta:
model = UtilityPermit
fields = ['...']
class SewerPermitForm(forms.ModelForm):
class Meta:
model = SewerPermit
fields = ['...']
class WaterPermitForm(forms.ModelForm):
class Meta:
model = WaterPermit
fields = ['...']
I successfully added them to a list and could iterate through and get them to add
views.py
class BuildForms(View):
permits = []
utility_form = UtilityPermitForm
sewer_form = SewerPermitForm
water_form = WaterPermitForm
permits.append(utility_form)
permits.append(sewer_form)
permits.append(water_form)
template_name = 'engineering/UtilityPermitForm2.html'
def get(self, request, *args, **kwargs):
out_permits = []
for form in self.permits:
out_permits.append(form())
return render(request, self.template_name, {'form': out_permits})
def post(self, request, *args, **kwargs):
if request.GET.get('testButton'):
return HttpResponse("I guess")
form = self.utility_form(request.POST)
return render(request, self.template_name, {'form': form})
def add_permit(self, request, permit):
# need to get a thing to add a permit to the list
pass
.html
{% block content %}
<div>
<form class="site_form" action={% url 'engineering:utility_permit' %} method="post">
{% csrf_token %}
{% for item in form %}
{{ item }}
<hr>
{% endfor %}
<input type="submit" value="Submit">
</form>
</div>
{% endblock content %}
so again, my problem is I want to start with a one permit and then have links or buttons to add each form as needed. I'm a bit at a loss here and any help would be greatly appreciated.
EDIT:
so I have this base permit that comes up when a user navigates to it like so, and I want to have a user click the add sewer permit button or link or whatever
and then the corresponding permit will come up
you can create multiple same form in one page dynamically using formset
see Documentation
and maybe this tutorial is exactly what you are looking for.
EDITED
if I understand your question correctly, how about this:
first, it would be better to separate your form with dictionaries instead of list in your views.py
context = {
'utility_form': self.utility_form,
'sewer_form': self.sewer_form,
'water_form': self.water_form
}
return render(request, self.template_name, context)
then in your .html file,
if you want to add one form each time you click the button, my trick is:
show your base permit form first (said utility_form), button to add other form, and hide your other form first.
<div class="form-container">
<form class="site_form" action={% url 'engineering:utility_permit' %} method="post">
{% csrf_token %}
{{ utility_form }}
<div id="additional-forms"></div> <!-- notice this div -->
<hr>
<input type="submit" value="Submit">
</form>
</div>
<button class="add-sewer-form">Sewer Permit</button>
<div id="sewer-form-template" style="display: none;">
<div class="sewer-form-container">
{{ sewer_form }}
</div>
</div>
and then using jquery to add onclick listener, clone that hidden form, then insert it after base form (actually inside div with id additional-forms).
$('.add-sewer-form').click(function(){
let sewer_form = $('#sewer-form-template .sewer-form-container:first').clone(true);
$(sewer_form).appendTo($('#additional-forms'))
});
I haven't test it yet, but when you click the add button, it should be give result like this:
<div class="form-container">
<form class="site_form" action={% url 'engineering:utility_permit' %} method="post">
{% csrf_token %}
{{ utility_form }}
<div id="additional-forms">
<div class="sewer-form-container">
{{ sewer_form }}
</div>
</div>
<hr>
<input type="submit" value="Submit">
</form>
</div>
<button class="add-sewer-form">Sewer Permit</button>
<div id="sewer-form-template" style="display: none;">
<div class="sewer-form-container">
{{ sewer_form }}
</div>
</div>
Hope it can answer your question :)
First add the button
<button><button>
Then add onclick attribute to it which will help react on click
<button onclick='do'><button>
Then create script that contain the function to display the other form
<script>
function do() {
document.getElementById('form').innerHTML ='add your form here'
}
</script>
all together
<button onclick='do'><button>
<script>
function do() {
document.getElementById('form').innerHTML ='add your form here'
}
</script>

In django, how to use another model data from function based views

So I have a form that updates a key_instance object with a borrower. Currently my app needs the user to enter the name of the borrower, but I want it to display a dropdown list of data from another model the user model to select from, is there anyway to do this in a class based view? Here are my views.py and my template. What I was thinking is that I would like to use a get_list_or_404 on the user model and display it as a drop down list in the template and use that selection to populate the form field.
I manged to get the dropdown list to display in my template but I'm not sure as to how to save that value in my views.
Does anyone know if this is the right way or if this is doable? Thank you!!
views.py
def submit_key_request(request, pk):
"""
View function for renewing a specific keyInstance by admin
"""
key_inst=get_object_or_404(KeyInstance, pk=pk)
names = get_list_or_404(Users)
# If this is a POST request then process the Form data
if request.method == 'POST':
# Create a form instance and populate it with data from the request (binding):
form = UpdateKeyForm(request.POST)
# Check if the form is valid:
if form.is_valid():
# process the data in form.cleaned_data as required (here we just write it to the model due_back field)
key_inst.is_requested = True
key_inst.status = 'r'
key_inst.date_requested = datetime.date.today()
key_inst.borrower = form.cleaned_data['borrower']
key_inst.save()
# redirect to a new URL:
return HttpResponseRedirect(reverse('all-available-keys') )
# If this is a GET (or any other method) create the default form.
else:
form = UpdateKeyForm(initial={'borrower': 'N/A'})
return render(request, 'catalog/keyinstance_request_update.html', {'form': form, 'keyinst':key_inst})
template
{% extends "base_generic.html" %}
{% block content %}
<div class="wrapper">
<div class="centered"> <h1>Request Keys For Room: {{keyinst.roomkey}}</h1></div>
<div class="square-box">
<div class="square-content">
<form action="" method="post" >
{% csrf_token %}
<table style="display: inline-flex">
{{ form}}
</table>
<select name = 'name'>
{% for name in names %}
<option value="{{ name }}">{{ name }}</option>
{% endfor %}
</select>
<p>
(Please use their login name i.e. <b>{{ user.get_username }}</b>)
</p>
<p><input required id="checkBox" type="checkbox" onclick="validate()"> I accept the terms and conditions</p>
<p id="text" style="display:none">You Have Agreed To the Terms and Conditions</p>
<input type="submit" value="Submit" />
</form>
</div>
</div>
</div>
{% endblock %}
Here is how I manged to do it, Not sure if this is the best 'pythonic' or best practice. Please let me know if it's not.
my views.py
def submit_key_request(request, pk):
"""
View function for renewing a specific keyInstance by admin
"""
key_inst=get_object_or_404(KeyInstance, pk=pk)
names = get_list_or_404(User)
# If this is a POST request then process the Form data
if request.method == 'POST':
name = request.POST['name']
key_inst.is_requested = True
key_inst.status = 'r'
key_inst.date_requested = datetime.date.today()
key_inst.borrower = name
key_inst.save()
return HttpResponseRedirect(reverse('all-available-keys') )
# If this is a GET (or any other method) create the default form.
else:
pass
return render(request, 'catalog/keyinstance_request_update.html', {'keyinst':key_inst, 'names':names})
template
{% extends "base_generic.html" %}
{% block content %}
<div class="wrapper">
<div class="centered"> <h1>Request Keys For Room: {{keyinst.roomkey}}</h1></div>
<div class="square-box">
<div class="square-content">
<form action="" method="post" >
{% csrf_token %}
</br>
<select name = 'name' required>
{% for key in names %}
<option value="{{ key }}">{{ key }}</option>
{% endfor %}
</select>
<p>
(Please use their login name i.e. <b>{{ user.get_username }}</b>)
</p>
<p><input required id="checkBox" type="checkbox" onclick="validate()"> I accept the terms and conditions</p>
<p id="text" style="display:none">You Have Agreed To the Terms and Conditions</p>
<input type="submit" value="Submit" />
</form>
</div>
</div>
</div>
{% endblock %}

flask database global variable

in my flask app I am using mongoDB and on the home page I have a form that is returning all the known collections in that particular database. I am asking the user to pick a collection they want to use as I will use that collection set to return all the documents in other routes or views.
Im struggling how to make this global "selected_collection" a global variable that all the routes and views can use.
for example on the index page I am able select a collection then on the submit it would redirect me to view db_selected there I was trying to make the selected_collection a global variable but if i got to the about view it get an error related to
I imagine I should use flask.g but im not sure how to get it to work. I have read some of the documents but they are a little vague to me.
AttributeError: '_AppCtxGlobals' object has no attribute 'selected_collection'
how can i make this work?
app.py file:
# INDEX
#app.route('/', methods=['GET', 'POST'])
def index():
coll_name = get_db_collection()
return render_template('index.html', coll_name=coll_name)
# LOGIN
#app.route('/db_selected', methods=['GET', 'POST'])
def db_selected():
if request.method == 'POST':
selected_collection = request.form['Item_4']
selected_collection = g.selected_collection
return render_template('db_selected.html',
selected_collection=selected_collection)
#app.route('/about')
def about():
app.logger.info('selected_collection is {}'.format(g.selected_collection))
return render_template('about.html')
index.html file:
{%extends 'layout.html'%}
{%block body%}
<div class="jumbotron text-center">
<h1>Welcome to the index.html file !</h1>
</div>
<div class="container">
{% include 'db_query_bar.html' %}
</div>
{%endblock%}
db_query_bar.html
<form class="form-horizontal" action="{{ url_for('db_selected') }}" name="Item_1" method="POST">
<fieldset>
<legend>Select DB</legend>
<div class="form-group">
<label for="select" class="col-lg-2 control-label">Database Collection:</label>
<select id="DB" class="form-control" name="Item_4" style="width: 70%" >
<!-- <option value="">All</option> -->
{% for item in coll_name %}
<option value="{{item}}">{{item}}</option>
{% endfor %}
</select>
<br>
</div>
<div class="form-group">
<div class="col-lg-10 col-lg-offset-2">
<button type="submit" class="btn btn-success">Submit</button>
</div>
</div>
</fieldset>
</form>
Just to answer this for the global variable I ended up placing
app.selected_collection = "Some Value"
in the top of my flask code this will create a global variable I can use in all the views.
app = Flask(__name__)
# CONFIG MONGO CONNECTION DETAILS
app.config['MONGO_HOST'] = 'DB-Host'
app.config['MONGO_DBNAME'] = 'DB-Collection'
app.selected_collection = "Some Value"
# INIT MONGODB
mongo = PyMongo(app)