Queryset for current logged in user Django - django

I am doing queryset with my model. Now the queryset is displaying all the data in my html page. But I want to display only the logged in users data.
models.py
class Data(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
Status = models.CharField(max_length=10, blank=False)
Date = models.DateField(blank=True, null=True)
views.py
#login_required
def search(request):
status_list = Data.objects.all()
status_filter = UserFilter(request.GET, queryset=status_list)
return render(request, 'users/data.html', {'filter': status_filter})
filters.py
class UserFilter(django_filters.FilterSet):
class Meta:
model = Data
fields = {
'Date': ['year','month', ], 'user': ['exact', ],
}
I tried with different views.py also but it didn't work.
#login_required
def search(request, user):
status_list = Data.objects.get(user=self.request.user).search(query)
status_filter = UserFilter(request.GET, queryset=status_list)
return render(request, 'users/data.html', {'filter': status_filter})
data.html
<!DOCTYPE html>
{% load django_tables2 %}
{% load staticfiles %}
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
{% block content%}
<form method="get">
{{ filter.form.as_table }}
</select>
<button type="submit" class="btn btn-primary">
<span class="glyphicon glyphicon-search"></span> Search
</button>
</form>
<ul>
{% for user in filter.qs %}
<li>{{ user.username }} - {{ user.get_full_name }}</li>
{% endfor %}
</ul>
<table id="datatable" style="margin-top: 20px" style="margin-
bottom:20px" class="table table-bordered" >
<thead>
<tr>
<th>user</th>
<th>EndDate</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{% for Data in filter.qs %}
<tr>
<td>{{ Data.user }}</td>
<td>{{ Data.EndDate }}</td>
<td>{{ Data.Status }}</td>
</tr>
{% empty %}
<tr>
<td colspan="5">No data</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock content%}
</body>
Above I added my HTML code also.Please look into html code also.

There could be better ways to do this. As you are still learning below code does the trick.
#login_required
def search(request, *args, **kwargs):
status_list = Data.objects.get(user=request.user)
month = request.GET.get("month", None)
year = request.GET.get("year", None)
if month:
status_list = status_list.filter(Date__month=month)
if year:
status_list = status_list.filter(Date__year=year)
return render(request, 'users/data.html', {'filter': status_list})

You can simplify your code, django provides many helpers function to help to programmer.
in your views.py you can do:
#login_required
def search(request):
status_list = Data.objects.all()
status_filter = status_list.filter(user=request.user) //get current user id
return render(request, 'users/data.html', {'filter': status_filter})

status_list = Data.objects.get(user=self.request.user)
is wrong as self is only used in class based views. No wonder it did not work.
Please try with the below code instead
status_list = Data.objects.filter(user=request.user) or
status_list = Data.objects.get(user=request.user)
So, the final code will be like
#login_required
def search(request):
status_list = Data.objects.get(user=request.user)
render(request, 'users/data.html', {'filter': status_list})

Below code should work fine.
{% for data in filter %}
<li>{{ data.user.username }} - {{ data.user.get_full_name }}</li>
{% endfor %}
{% for Data in filter %}
<tr>
<td>{{ Data.user }}</td>
<td>{{ Data.Date }}</td>
<td>{{ Data.Status }}</td>
</tr>
{% empty %}
As you would not be using filters, so filters.py should be removed.
This will also not work. Make the changes as required.
{{ filter.form.as_table }}

Related

How do I bring through my data in Django Template view?

I'm trying to display my data from my HealthStats model to my template, however I can only pull through the user field. I've added the other fields to my template, but they're not showing. I would also like to be able to filter the output to only show records of the logged in user.
Models.py
class HealthStats(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
date = models.DateField(auto_now=True)
weight = models.DecimalField(max_digits=5, decimal_places=2)
run_distance = models.IntegerField(default=5)
run_time = models.TimeField()
class Meta:
db_table = 'health_stats'
ordering = ['-date']
def __str__(self):
return f"{self.user} | {self.date}"
Views.py:
class HealthHistory(generic.TemplateView):
model = HealthStats
template_name = 'health_hub_history.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['stats'] = HealthStats.objects.all()
return context
health_hub_history.html
{% extends 'base.html' %}
{% load static %}
{% block content %}
<div class="container-fluid">
<div class="row">
<div class="col-sm-12 text-center">
<h1>My Health History</h1>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-auto text-center p-3">
<table class="table table-striped table-hover table-bordered">
<tr>
<td>User:</td>
<td>Weight (lbs):</td>
<td>Date:</td>
<td>Run Distance (km):</td>
<td>Run Time (HH:MM:SS):</td>
</tr>
{% for stat in stats %}
<tr>
<td>{{ user }}</td>
<td>{{ weight }} </td>
<td>{{ date }}</td>
<td>{{ run_distance }}</td>
<td>{{ run_time }}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
</div>
{% endblock content %}
Any help would be appreciated!
In your template do this:
{% for stat in stats %}
<tr>
<td>{{stat.user}}</td>
<td>{{stat.weight}} </td>
<td>{{stat.date}}</td>
<td>{{stat.run_distance}}</td>
<td>{{stat.run_time}}</td>
</tr>
{% endfor %}
hope it will work

How do I use django_tables2 with a filter?

I'm displaying data on a webpage, and I would like to migrate this code to use the table I created in tables.py. I can't figure out how to do it without breaking the filter.
views.py
def PlatListView(request):
queryset = Plat.objects.all().values('id', 'description','status', 'phase__number','phase','schedule_found').annotate(lot_count=Sum('phase__lot_count')).order_by('description')
f = PlatFilter(request.GET, queryset=queryset)
return render(request, 'blog/filtertable2.html', {'filter': f})
filters.py
class PlatFilter(django_filters.FilterSet):
community = ModelChoiceFilter(queryset=Community.objects.all())
tables.py
import django_tables2 as tables
class PlatTable(tables.Table):
id = tables.Column()
description = tables.Column()
status = tables.Column()
phase__number = tables.Column()
lot_count = tables.Column()
schedule_found = tables.Column()
class Meta:
ordering = 'description'
#model = Plat
filtertable2.html
{% extends "blog/base.html" %}
{% block content %}
{% load bootstrap4 %}
<form method="get">
{{ filter.form.as_p }}
<input type="submit" />
</form>
<table>
<tr>
<th>Description</th>
<th>Status</th>
</tr>
{% for obj in filter.qs %}
<tr>
<td> {{ obj.description }}</td>
<td>{{ obj.status }}</td>
</tr>
{% endfor %}
</table>
{% endblock content %}
In your view you construct the table with the data from the filter:
def PlatListView(request):
queryset = Plat.objects.annotate(
lot_count=Sum('phase__lot_count')
).order_by('description')
f = PlatFilter(request.GET, queryset=queryset)
table = PlatTable(data=f.qs)
return render(request, 'blog/filtertable2.html', {'filter': f, 'table': table})
You can then render the table with:
{% extends "blog/base.html" %}
{% block content %}
{% load bootstrap4 %}
{% load render_table from django_tables2 %}
<form method="get">
{{ filter.form.as_p }}
<input type="submit" />
</form>
{% render_table table %}
{% endblock content %}
I do not see any particular reason for using Values QuerySet, ie values(). You can simply annotate the value with queryset:
def plat_list_view(request): # using snake_case when defining a method name.
queryset = Plat.objects.annotate(lot_count=Sum('phase__lot_count')).order_by('description')
f = PlatFilter(request.GET, queryset=queryset)
return render(request, 'blog/filtertable2.html', {'filter': f})

I wrote a way to add comments, but it didn't run

My idea is to create a model of articles and comments. When users initiate comments, they can directly create data, but adding comments in the actual operation does not respond.
#views.py
def details(request, article_id):
detail = LifeArticle.objects.get(id=article_id)
comment = LifeComment.objects.get(article=detail)
return render(request, 'lifedetail.html', locals())
def addcomment(request, article_id):
article = LifeArticle.objects.get(id=article_id)
if request.method == "POST":
content = request.POST['content']
r = LifeComment.create(article=article, user=request.user, content=content)
msg = '添加成功'
return render(request, 'lifedetail.html', locals())
else:
return render(request, 'lifedetail.html',)
#urls.py
urlpatterns = [
url(r'^life/(?P<article_id>\d+)/', views.details),
url(r'^article/life/(?P<article_id>\d+)/addcoment/', views.addcomment)
]
#lifedetail.html
{% if detail %}
<div id='article'>
<form action="/article/life/{{detail.id}}/addcoment/" method="POST">
{% csrf_token %}
<tr>
<td>{{ detail.title }}</td>
<td>{{ detail.content }}</td>
<td>{{ detail.user }}</td>
</tr>
</div>
<div id="comment">
{% if comment %}
<tr>
<td>{{ comment.content }}</td>
<td>{{ comment.user }}</td>
</tr>
</div>
{% else %}
<p>暂无评论</p>
{% endif %}
<input type="text" name="content">
<input type="submit" value="提交">
</form>
{% else %}
<p>暂无文章</p>
{% endif %}
{{msg}}
</div>
These are my code. Now I can't find the reason. I'm also looking at Django2.2's documentation to find the problem
I think the problem is in this line:
r = LifeComment.create(article=article, user=request.user, content=content)
I think you should use objects here:
r = LifeComment.objects.create(article=article, user=request.user, content=content)
Also, you need to send detail information from context:
def addcomment(request, article_id):
article = LifeArticle.objects.get(id=article_id)
if request.method == "POST":
# rest of the code
else:
return render(request, 'lifedetail.html', context={'detail':article})

Django: Updating and Deleting objects using Django Views

The task which I am trying to achieve is to give the power to the logged-in user to update and delete their contact list via Django views. I coded all the templates and views.py functionality but has not been able to proceed forward.
Here is what I was able to achieve:
"views.py":
#login_required
def update_contact(request,contact_id=1):
current_user = request.user.get_username()
user = User.objects.filter(username=current_user).first()
output = UserContacts.objects.filter(current_user_id=user.id)
count = output.count()
contact_obj =get_object_or_404(UserContacts,id = contact_id)
form = UserContactForm()
if request.method == "POST":
form = UserContactForm(request.POST,instance=contact_obj)
if form.is_valid():
form.save(commit=True)
return index(request)
else:
print('Error Form Invalid')
my_dict = {'output':output,'form':form}
return render(request,'basic_app/update.html',my_dict)
Here is my template for update.html for updating contact:
{%extends 'basic_app/base.html' %}
{% block body_block %}
<div class="jumbotron">
<h1>Welcome to update contact page</h1>
<br />
{% if output %}
<table class="table table-striped">
<thead class="thead-dark">
<th>First Name</th>
<th>Edit</th>
</thead>
{% for contact in output %}
<tr>
<td>{{ contact.first_name}}</td>
<td>Edit</td>
</tr>
{% endfor %}
</table>
{% else %}
<div class="alert alert-warning" role="alert">
No contact records found!
</div>
{% endif %}
</div>
{% endblock %}
URLS.Py:
app_name = 'basic_app'
urlpatterns = [
url(r'^register/$',views.register,name='register'),
url(r'^user_login/$',views.user_login,name='user_login'),
url(r'^new_contact/$',views.new_contact,name='new_contact'),
url(r'^view_contacts/$',views.view_contacts,name='view_contacts'),
url(r'^update/(?P<contact_id>[\d]+)$',views.update_contact,name='update'),
url(r'^delete/$',views.delete_contact,name="delete")
]
Here is the error I am currently stuck with
Any help would be greatly appreciated!
In your urls.py the name of the update url is update:
url(r'^update/(?P<contact_id>[\d]+)$',views.update_contact,name='update')
But in your template your are using update_contact as name.
<td>Edit</td>
Try first to change the name in the template:
<td>Edit</td>

Saving data from ModelForm

I am new to Django and I'm trying to save data using ModelForm. Template 'Vlozit' has a ModelForm and when submitted, I want the data saved in the DB and the redirect to base.html that actually loads the data from the DB and lists the output. The problem is that all works fine but the data is not saved. Please help me find what I am missing. Thank you.
Here's the model:
class Customer(models.Model):
Name = models.CharField(max_length=30)
Description = models.CharField(max_length=150)
Creation_Date = models.DateField(default=datetime.now)
Active = models.BooleanField(default=False)
def __unicode__(self):
return self.Name
Customers = models.Manager()
Here's the ModelForm:
class CustomerForm(forms.ModelForm):
Description = forms.CharField(widget=forms.Textarea)
class Meta:
model = Customer
Here's the view:
def vlozit(request):
if request.method == 'POST':
form = CustomerForm(request.POST, instance=Customer)
if form.is_valid():
form.save(True)
return HttpResponseRedirect(reverse('Base.html'))
else:
form = CustomerForm()
return render_to_response("Vlozit.html", {'form': form}, context_instance = RequestContext(request))
Here's the template 'Vlozit':
{% extends "base.html" %}
{% block head %}
{{ form.media }}
<script>
$(function() {
$( "#id_Creation_Date" ).datepicker();
});
</script>
{% endblock %}
{% block title %}{{block.super}} - Vlozit{% endblock %}
{% block content %}
<div id="content">
<form method="POST" action="{% url url_home %}">
{% csrf_token %}
<table>
<tr>
<td>Name</td>
<td>{{ form.Name }}</td>
</tr>
<tr>
<td>Description</td>
<td>{{ form.Description }}</td>
</tr>
<tr>
<td>Creation Date</td>
<td>{{ form.Creation_Date }}</td>
</tr>
<tr>
<td>Active</td>
<td>{{ form.Active }}</td>
</tr>
</table>
<input type="submit" value="Vlozit">
</form>
</div>
{% endblock content %}
As Timmy says in the comments, you don't catch the case where the form is not valid. Not only do you not show errors in the template, but you also don't even redisplay the template if form.is_valid() is False. Move the last line of the view back one indentation level, and add {{ form.errors }} to the template.