I have a web page built in django that shows all rows of a sqlite table in bootstrap cards. Basically each card is a row of the table.
I want to give the user the ability to filter these cards, so the page instead of showing every objects in the database's table should display only the objects relevant to the user. The result of the search can be displayed at another URL, it's irrelevant.
I can build a html form to get info from the user and I can write a python function that search the database and print out specific rows based on an input keyword,
but I can't make these things work together.
Any hint or piece of code would be a great help, unfortunately I know nothing about php so if there's a way to do so without it would be great. Thanks all.
# this is my view function, it shows all the objects in the table at a #specific URL
def index_u(request):
universities = University.objects.all()
return render(request, 'index_uni.html', {'universities': universities})
/* this is index_uni.html */
{% block content %}
<div class="row">
{% for university in universities %}
<div class="col">
<div class="card" style="width: 18rem;">
<img src="{{ university.image_url}}" class="card-img-top">
<div class="card-body">
<h5 class="card-title">{{university.name}}</h5>
<p class="card-text">{{university.region}}</p>
Go
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock %}
#this function takes an input and diplays specific rows
#I don't know how make this works in the html page, it works fine in terminal
def search_data():
region_choice = input("insert region here: ")
command = "SELECT name FROM university_university WHERE region = ?;"
c.execute(command, [region_choice])
for row in c:
print(row)
#here my model
class University(models.Model):
name = models.CharField(max_length=58, default=True)
city = models.CharField(max_length=58, default=True)
region = models.CharField(max_length=58, default=True)
country = models.CharField(max_length=58, default=True)
number_of_students = models.IntegerField(default=True)
image_url = models.CharField(max_length=2083, default=True)
is_public = models.BooleanField(default=True)
ranking = models.IntegerField(default=True)
colleges = models.BooleanField(default=True)
scholarship = models.BooleanField(default=True)
uni_canteen = models.BooleanField(default=True)
page_url = models.CharField(max_length=2083, default=True)
You can make a query with:
def index_u(request):
region = request.GET.get('region')
universities = University.objects.all()
if region is not None:
universities = universities.filter(region=region)
return render(request, 'index_uni.html', {'universities': universities})
You can then create for example a form, like:
<form method="get" action="url-of-index_u">
<input type="text" name="region">
<input type="submit">
</form>
<! -- render the universities -->
Related
I want to add multiple values for a user in Django. in that a user may have several records displayed.
Records should belong to a specific user selected.
Models.py looks like :
class Medrecs(models.Model):
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
title = models.CharField(max_length=60, null=True)
clinician = models.ForeignKey(Clinician, on_delete=models.PROTECT)
Patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
meds = models.TextField()
def __str__(self):
return self.title
models.ForeignKey doesnt work either. It displays records to all patients but I want a specific patient/user selected. OneToOne will display for specific user but only once.
Views.py looks like:
def my_profile(request):
meds = Medrecs.objects.all()
if request.user.is_authenticated:
return render(request, 'MyDoc/my_profile.html', {'meds': meds})
else:
return redirect('MyDoc:login_patient')
And my template looks like :
{% if meds %}
{% for m in meds %}
<div class="col-sm-6 panel-primary">
<img class="logo" style="height: 35px; width: 35px; margin-right: 15px;" src="{{ user.patient.image.url }}">
<p>St.Denvers Hospital,</p><br>
<p>Healthcare is our compassion</p>
<p>{{ m.title }}</p>
<div class="panel panel-primary">
<div class="panel-heading active">
<h3 class="text-success">Doctor:{{ m.clinician }}</h3>
<p>Name: {{ m.patient }}</p>
</div>
<div class="panel-body">
<p>Medication: {{ m.meds }}</p>
</div>
</div>
</div>
{% endfor %}
{% endif %}
This works fine but i can only add one patient record and i want multiple for the same user. At the Django database it tells me theres a record for that user.
NB:/The user is also a patient.
Asking for help ..>>
You have a one to one relationship in your model which means one user to one record.
change the relationship to Foreign Key so that multiple records can go to one user.
What you need to change it to:
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="records")
and in the view you are querying all of the records which is not what you want.
Views.py
if request.user.is_authenticated:
meds = Medrecs.objects.all().filter(user=request.user)
return render(request, 'MyDoc/my_profile.html', {'meds': meds})
With this you are filtering all the records that belong to this user
I try to remove comment so, I tried the first time by the class-based view then I hashed it to try the second way by normal function to know what's going on here. so, when I try to delete the comment by ID nothing does happen it's just directing me to the web page without deleting the comment so in this case the program runs but doesn't remove the object so, what is going on here?
Note: the posts and comments on the same page and slug field on that page are following by post not comment.
if the title of the post is: new title so, the slug will be new-title depending on the post
question_view.html
<div class="user-answer">
<div class="row">
<div class="col-xs-12">
{% for comment in my_question.comment_set.all %}
<div class="comments">
<div class="col-xs-0">
<div class="avatar">
<a href="{% url 'account:view_profile' comment.username %}">
<img class="img-circle img-thumbnail" style="width:50px; height: 50px;" src="{{ comment.logo }}">
</a>
</div>
</div>
<div class="col-xs-10">
<!-- --Comment itself-- -->
<div class="user_comment">
<p>{{ comment }}</p>
<div class="fa fa-caret-left comment-arrow"></div>
</div>
<!-- start Options in comment -->
<div class="sub-options">
{% if request.user.username == comment.username %}
<!-- --Edit comment-- -->
<div class="edit-comment">
<a>Edit</a>
</div>
<!-- --Delete comment-- -->
<div class="delete-comment">
<form method="post" action="{% url 'community:delete_comment' comment.pk %}">
{% csrf_token %}
<input type="hidden" name="delete-comment" value="{{ comment.comment }}">
<input type="submit" value="delete">
</form>
</div>
{% endif %}
<!-- end Options in comment -->
<!-- --comment Date-- -->
<div style="display: inline-block;color: #8e8e8e" class="comment-date">
<p>{{ comment.date|time }}</p>
</div>
</div>
</div>
<div class="clearfix"></div>
</div>
{% endfor %}
</div>
</div>
</div>
views.py
# Delete post
# class DeleteComment(DeleteView, SingleObjectMixin):
# model = Comment
# pk_url_kwarg = 'pk'
# template_name = 'community/question_view.html'
# queryset = Comment.objects.all()
#
# def get_success_url(self):
# title = UserAsking.objects.get(title=self.object)
# slug = UserAsking.objects.get(title=title).ask_slug
# return reverse_lazy('community:question_view', kwargs={'user_slug': slug})
#
# def get_object(self, queryset=None):
# request_comment = self.request.POST['delete-comment']
# return self.get_queryset().filter(pk=request_comment).get()
def delete_comment(request, pk):
if request.method == 'POST':
comment = Comment.objects.get(pk=pk)
del comment
return redirect('community:user_questions')
urls.py
urlpatterns = [
# path('delete-comment/<int:pk>/', views.DeleteComment.as_view(), name="delete_comment"),
path('delete-comment/<int:pk>/', views.delete_comment, name="delete_comment"),
]
models.py
class Comment(models.Model):
userasking = models.ForeignKey(UserAsking, on_delete=models.CASCADE)
comment = models.TextField(max_length=500, blank=True)
date = models.DateTimeField(auto_now_add=True)
userprofile = models.ForeignKey(UserProfile, on_delete=models.CASCADE, default=1)
name = models.CharField(max_length=30, blank=False, default='empty')
logo = models.ImageField(upload_to='images/', default='images/default-logo.jpg', blank=True)
username = models.CharField(max_length=30, blank=False, default='empty')
def __str__(self):
return self.comment
I hope if you can explain by class based-view what's happening I will appreciate that.
note that: if you could understand exactly what's happening you will know that is no error appears to me, therefore, I get no exception or traceback. thank you in advance.
Try this:
def delete_comment(request, pk):
if request.method == 'POST':
comment = Comment.objects.get(pk=pk).delete()
return redirect('community:user_questions')
Your function only deletes the object but not the database entry since you don't trigger a valid SQL operation (delete in this case).
You just delete the object comment again which was assigned previously, but you don't affect the database entry:
def delete_comment(request, pk):
if request.method == 'POST':
comment = Comment.objects.get(pk=pk)
del comment
return redirect('community:user_questions')
More on delete() in the official docu:
Deleting objects¶
Update on your comment:
You can't use Python's del statement to interact with database entries in Django.
Pythons del statement is used to delete objects initially created by Python like lists, variables, etc. etc.
In order to interact with your database in Django, you have to use the toolbox of Django's built-in Model instance which basically translates raw SQL operations into easy to use methods.
So maybe you can adapt a proper wording to highlight the differences by calling database "objects" entries and python objects: well, objects..
However, Django still offers the option to use raw SQL as fallback.
I need some advice on what to do. I am developing an app for a course at my university. The userstory I working on at the moment is: "As a user I want to be able to report films that doesn´t exist."
My thought was to have a report-button at my film_detail.html, where clicking this button would trigger the BooleanField in my model, and mark the film as reported. When clicking the report-button I was thinking on just having a pop-up window to confirm the reporting, and I believe I won´t need to create a complete new view for this(?).
Does anyone have any idea on how to do this (cause I´m kinda stuck), or maybe having a better idea?
**models.py**
class Film(models.Model):
title = models.CharField(max_length=100)
title_short = models.CharField(max_length=17, default=None, null=True)
plot = models.TextField()
poster = models.ImageField(default="default.png", upload_to="posters")
release_date = models.DateField(blank=True, null=True)
date_posted = models.DateTimeField(default=timezone.now)
reported = models.BooleanField("Is reported", default=False)
#class Admin:
# list_display = ("is_reported")
#def is_reported(self):
# return self.reported == True
#is_reported.BooleanField = False
**HTML**
{% extends "board/base.html" %}
{% block content %}
<article class="media content-section">
<img class="rounded-circle film-img" src="/media/{{object.poster}}">
<!-- Mulighet for å ha en "add review"-knapp på siden der hvor filmene vises. -->
<!-- <i class="material-icons right">rate_review</i>add review -->
<a onclick="myFunction()" class="waves-effect waves-light red darken-4 btn"><i class="material-icons right">report</i>report</a>
<script>
function myFunction() {
alert("Are you sure you want to report this film?");
}
</script>
<div class="media-body">
<h2 class="film-title">{{ object.title }}</h2>
<p class="film-plot">{{ object.plot }}</p>
</div>
</article>
{% endblock content %}
There are definitely different ways on implementing it. One way is to expose an API with a url like: films/report with PUT method. After getting confirmation from the user, you can easily send an Ajax request.
I created a custom plugin for my project in Django/Django-CMS and the plugin has a list of testimonials that the user pick when adding the plugin to the page. The model is this:
class TestimonialsPlugin(CMSPlugin):
n_testimonials = models.PositiveIntegerField(
verbose_name=_('Number of Testimonials'), default=5)
speed_autoplay = models.PositiveIntegerField(
verbose_name=_('Speed of slider (milliseconds)'), default=3000)
picked_testimonials = models.ManyToManyField(Testimonials,
verbose_name=_('picked_testimonials'),
blank=True, null=True)
In the edit mode I can se the testimonials in my page and I can publish without errors but when I see the published page the testimonials doesn't show. The plugin template is being rendered but the picked_testimonials gives None. Here's the template:
<div class="max-width1440 block clearfix relative">
<div class="small-only-text-left small-12 small-offset-0 medium-text-center medium-offset-1 medium-10 large-offset-1 large-10 column pt-px60 pb-px40 pl-px40 pr-px40 slider-testimonials">
{% for testimonial in instance.picked_testimonials.all %}
{% if forloop.counter0 < instance.n_testimonials %}
<div class="slider column">
<blockquote class="acta_mediumitalic size36 pl-px80 pr-px80 line-height140">
{% render_model testimonial "description" %}
</blockquote>
<div class="mt-px30">
<p class="acta_book size20 softblack">{{ testimonial.author }},<span>{{ testimonial.city }}</span>
</p>
</div>
</div>
{% endif %}
{% endfor %}
</div>
</div>
When a page is published, a copy of a plugin is created - which does include plugin's fields but not any relations. There is a provision in the CMS to provide copy method for exactly this purpose, see example from documentation:
class ArticlePluginModel(CMSPlugin):
title = models.CharField(max_length=50)
sections = models.ManyToManyField(Section)
def copy_relations(self, oldinstance):
self.sections = oldinstance.sections.all()
The important bit is the copy_relations, which ensures that the new object has the same relational links.
In your case, something along these lines should work:
class TestimonialsPlugin(CMSPlugin):
n_testimonials = models.PositiveIntegerField(
verbose_name=_('Number of Testimonials'), default=5)
speed_autoplay = models.PositiveIntegerField(
verbose_name=_('Speed of slider (milliseconds)'), default=3000)
picked_testimonials = models.ManyToManyField(Testimonials,
verbose_name=_('picked_testimonials'),
blank=True, null=True)
def copy_relations(self, oldinstance):
self.picked_testimonials = oldinstance.picked_testimonials.all()
I'm learning flask and I have a little problem.
I made an index template, where are blog post titles.
{% for title in titles %}
<!-- Main Content -->
<div class="container">
<div class="row">
<div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
<div class="post-preview">
<a href="{{ url_for('post')}}">
<h2 class="post-title">
{{ title[0] }}
</h2>
</a>
<p class="post-meta">Posted by {{ author }}</p>
</div>
</div>
</div>
</div>
{% endfor %}
Here is part of my post.html template.
<div class="container">
<div class="row">
<div class="col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1">
<p>{{ post_text1 | safe }}</p>
<hr>
<div class="alert alert-info" role="alert">Posted by
{{ author }}
</div>
</div>
</div>
</div>
I'm using sqlite3. Currently every title leads to same post.html where is first text from first post.
How to make every title direct to their post text? I mean, if I click on the first title it should bring up post.html and there should be first text. Second title should show second text.
Should I write program, that creates new html for every post or is there any other way?
#app.route('/')
def index():
db = connect_db()
titles = db.execute('select title from entries')
titles = titles.fetchall()
author = db.execute('select author from entries order by id desc')
author = author.fetchone()
return render_template('index.html', titles=titles[:], author=author[0])
#app.route('/post/')
def post():
db = connect_db()
post_text1 = db.execute('select post_text from entries')
post_text1 = post_text1.fetchone()
author = db.execute('select author from entries where id=2')
author = author.fetchone()
return render_template('post.html', post_text1=post_text1[0], author=author[0])
The problem comes from here <a href="{{ url_for('post')}}">.
What this tells Flask is to make a url for post, which is something you have defined in views as def post(argument) but you are not providing an argument. So if for example you are making you are taking your posts based on id, your view would would ask for /<int:post_id>/ in url and post_id would be passed as an argument based on which you would find the specific post and pass that to the template.
Your url_for should reflect this, you should have {{ url_for('post', post_id=title[1]) }} or wherever you are storing your equivalent of post_id (maybe that's title for you).
Edit:
Baed on your edit, your problem is that you are not telling Flask which post to fetch. You need either ID, or slug, or something that will go in the url and will tell you which post you are looking for. Your function right now is static and is always fetching the first entry in your database. The changes required are:
#app.route('/')
def index():
db = connect_db()
titles = db.execute('select title, id from entries')
titles = titles.fetchall()
author = db.execute('select author from entries order by id desc')
author = author.fetchone()
return render_template('index.html', titles=titles, author=author[0])
#app.route('/post/<int:post_id>/')
def post(post_id):
db = connect_db()
post_text = db.execute('select post_text from entries where id = ?', post_id)
post_text = post_text1.fetchone()
author = db.execute('select author from entries where id=2')
author = author.fetchone()
return render_template('post.html', post_text1=post_text, author=author)
<a href="{{ url_for('post', post_id=title[1])}}">
Also your author fetching is weird, you should have them stored (at least their ids) next to entries. Then I'd recomend some naming changes etc. It's hard to just answer the question and not write the code for you, as this is a site for answering specific questions, not writing code on demand :) Try to understand what I wrote here, play around with it a bit more etc. to fully undnerstand.
tl;dr: Posts have to get an argument and then fetch a post identified by that argument, the program can't magically tell which post you clicked on.