How to display specific output for specific username in django? - django

I have made a simple django app. In my models.py I have defined a table-
class events(models.Model):
id_campaign = models.CharField(default='newevent',max_length=100)
status = models.CharField(default='100',max_length=100)
name = models.CharField(default='100',max_length=100)
This is my views.py -
from django.shortcuts import render
# Create your views here.
from django.views.generic import TemplateView
from django.shortcuts import render
from website.models import *
from website.models import events
from django.views.generic import ListView
class HomePageView(TemplateView):
template_name = 'base.html'
class AboutPageView(TemplateView):
template_name = 'about.html'
class ContactPageView(TemplateView):
template_name = 'contact.html'
class Success(TemplateView):
template_name = 'success.html'
def get_context_data(self, **kwargs):
context = super(Success, self).get_context_data(**kwargs)
query_results = events.objects.all()
context.update({'query_results': query_results})
return context
And this is the success.html -
{% if user.is_authenticated %}
<header>
Logout
</header>
{% block content %}
<h2>you are logged in successfully. this is your personal space.</h2>
<table>
<tr>
<th>id_campaign</th>
<th>status</th>
<th>name</th>
</tr>
{% for item in query_results %}
<tr>
<td>{{ item.id_campaign }}</td>
<td>{{ item.status }}</td>
<td>{{ item.name }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
{% else %}
<h2>you are not logged in.</h2>
{%endif %}
I need to check the username in success.html and based on the user I need to show results, how do I do that?
if request.user.is_authenticated():
username = request.user.username
if username is 'xyz' then I want to display the values from query_results and if username is 'abc' then I don't want to display.
P.S. - I am absolutely new to django

You can use builtin template tag if and do it as below
{% if username == 'xyz' %}
{% else %}
{% endif %}
Refer this link for documentation.

Related

Django - Calling function in ListView or model to change model bolean status

I want to call a function - from a model or from a Listview that will change Order.isDone status - TRUE or FALSE after clicking the button in template.
Model.py:
class Order(models.Model):
isDone = models.BooleanField(default=False, verbose_name='Zrealizowane')
views.py:
class OrderListView (ListView):
model = Order
template_name = 'orders/orders_list.html'
ordering = ['-orderDate']
urls.py:
urlpatterns = [
path('', views.home, name='page-home'),
path('orders_list/', OrderListView.as_view(), name='page-orders-list'),
path('completed_orders_list/', OrderCompletedListView.as_view(), name='page-completed-orders-list'),
path('orders/order_create/', OrderCreateView.as_view(), name='page-order-create'),
path('orders/<int:pk>/delete/', OrderDeleteView.as_view(), name='page-order-delete'),
]
template:
<tbody>
{% for order in object_list %}
{% if order.isDone == False %}
<tr>
<td>
<button type="button" class="btn btn-secondary" data-toggle="modal" data-target="#exampleModalCenter">Szczegóły</button>
<form action="{% url 'page-orders-list' order.id %}" method="post">
{% csrf_token %}
<button class="btn btn-info btn-sm">Finish order</button>
<form>
<a class="btn btn-danger adminButton" href="{% url 'page-order-delete' order.id %}">Usuń</a>
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
What is the easiest way to do this ?
I suggest using another view for this. You can use the get method in the view to change the status of the order. The in your HTML you would only need to use a link instead of a form.
So something like this:
views.py
class OrderFinishView(RedirectView):
success_url = None # After finishing the order, where do you want to redirect the user?
def get(self, request, *args, **kwargs):
order_id = self.kwargs['pk_order'] # pk_order must be in your URL
order = get_object_or_404(Order, pk=order_id)
order.is_done = True
order.save()
return super().get(request, *args, **kwargs)
urls.py
urlpatterns = [
path('', views.home, name='page-home'),
path('orders_list/', OrderListView.as_view(), name='page-orders-list'),
path('completed_orders_list/', OrderCompletedListView.as_view(), name='page-completed-orders-list'),
path('orders/order_create/', OrderCreateView.as_view(), name='page-order-create'),
path('orders/<int:pk>/delete/', OrderDeleteView.as_view(), name='page-order-delete'),
path('orders/<int:pk_order>/finish', OrderFinishView.as_view(), name='page-order-finish'),
]
template
<tbody>
{% for order in object_list %}
{% if order.isDone == False %}
<tr>
<td>
<a href={% url 'page-order-finish' order.id %}>Finish</a>
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
Another idea is to use an UpdateView to update your order with a PartialOrderForm which would only contain the is_done field.
I used the #vinkomlacic's solution, but i changed the return of get function:
def get(self, request, *args, **kwargs):
order_id = self.kwargs['pk_order'] # pk_order must be in your URL
order = get_object_or_404(Order, pk=order_id)
order.isDone = True
order.save()
return redirect(self.success_url)
Seems to be working properly now after setting success_url in class

How to update a single item in a list from the template in Django?

I am looking for the best way to make an updateable list from model objects in Django.
Let's say that I have a models.py:
class Foo(models.Model):
bar = models.CharField(max_length=10, blank=True)
foo = models.CharField(max_length=30, blank=True)
and I have a views.py that shows the objects from that model:
def my_view(request):
person_list = Person.objects.all()
ctx= {'person_list': person_list}
return render(request, 'my_app/my_view.html', ctx)
Then I have a template, my_view.html:
...
<table>
<tr>
<th>bar</th>
<th>foo</th>
<th></th>
</tr>
{% for item in person_list %}
<tr>
<td>{{item.bar}}</td>
<td>{{item.foo}}</td>
<td style="width: 5%;"><button type="submit" name="button">Change</button></td>
</tr>
{% endfor %}
</table>
...
So, I would like to add a form and make one of those fields changeable from within this template.
I would like users to be able to change item.foo and then click the change button and it sends the update to the model.
I tried making it a form, and using forms.py to create a form where users can put an input, and then submit the form, and that looked like this, my_view.html:
...
...
<table>
<tr>
<th>bar</th>
<th>foo</th>
<th></th>
</tr>
{% for item in person_list %}
<form method="post">
{% csrf_token %}
<tr>
<td>{{item.bar}}</td>
<td>{{item.foo}}</td>
<td>{{form.foo}}</td>
<td style="width: 5%;"><button type="submit" name="button">Change</button></td>
</tr>
</form>
{% endfor %}
</table>
...
...
And that was not working, because I couldn't figure out where to send the PK for that particular item in the Model.
Any help is appreciated.
You can do it using class-based views very easily
Say this is your models.py
class MyModel(models.Model):
alpha = models.CharField(max_length=200)
beta = models.CharField(max_length=200)
gama = models.CharField(max_length=200)
delta = models.CharField(max_length=200)
Your views.py should be like this
from django.views.generic import UpdateView
from .models import MyModel
class MyModelUpdateView(UpdateView):
model = MyModel
fields = ['beta'] # Include the fields you want to update form your template
As a reference, this will be your CreateView in views.py file
class MyModelCreateView(CreateView):
model = MyModel
template_name = 'myapp/myapp_form.html'
fields = ['alpha', 'beta', 'gama', 'delta']
This will be your urls.py
from .views import MyModelUpdateView
urlpatterns = [
....
path('app/<int:pk>/update/', MyModelUpdateView.as_view(), name='model-update'),
....
]
The default template for UpdateView is the one used for CreateView, myapp_form.html in this case. This will be your basic form template
{% extends 'base.html' %}
{% block content %}
<form method="POST">
{% csrf_token %}
{{ form }}
<button type="submit">Create</button>
</form>
{% endblock %}

How to display the contents of a table as a table in django?

I have made a simple django app. In my models.py I have defined a table-
class events(models.Model):
id_campaign = models.CharField(default='newevent',max_length=100)
status = models.CharField(default='100',max_length=100)
name = models.CharField(default='100',max_length=100)
This is my views.py -
from django.shortcuts import render
# Create your views here.
from django.views.generic import TemplateView
from django.shortcuts import render
from website.models import *
from website.models import events
from django.views.generic import ListView
class HomePageView(TemplateView):
template_name = 'base.html'
class AboutPageView(TemplateView):
template_name = 'about.html'
class ContactPageView(TemplateView):
template_name = 'contact.html'
class Success(TemplateView):
template_name = 'success.html'
def MyView(self, request):
query_results = events.objects.all()
return render(request, self.template_name)
And this is the success.html -
{% if user.is_authenticated %}
<header>
Logout
</header>
{% block content %}
<h2>you are logged in successfully. this is your personal space.</h2>
<table>
<tr>
<th>id_campaign</th>
<th>status</th>
<th>name</th>
</tr>
{% for item in query_results %}
<tr>
<td>{{ item.id_campaign }}</td>
<td>{{ item.status }}</td>
<td>{{ item.name }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
{% else %}
<h2>you are not logged in.</h2>
{%endif %}
My issue is that once the user logs in he is only able to see the hardcoded column names but the column values are not visible. It is as if the {% for item in query_results %}. part is not working.
What should I do? I want to view the contents in a tabular way?
Also I need to check the username and based on the user I need to show results, how do I do that?
if request.user.is_authenticated():
username = request.user.username
if username is 'xyz' then I want to display the values from query_results and if username is 'abc' then I don't want to display.
P.S. - I am absolutely new to django
You are using TemplateView in wrong way.
You need to override the get_context_data() method in your TemplateView.
class Success(TemplateView):
template_name = 'success.html'
def get_context_data(self, **kwargs):
context = super(Success, self).get_context_data(**kwargs)
query_results = events.objects.all()
context.update({'query_results': query_results})
return context
It should work fine now.
You've misunderstood how class-based views work. Your MyView method is never called (although note that even if it was, it still doesn't actually do anything to send query_results to the template).
You need to define the get_context_data method, which returns a dictionary:
class Success(TemplateView):
template_name = 'success.html'
def get_context_data(self, *args, **kwargs):
query_results = events.objects.all()
return {'query_results': query_results}
But note that a much better way is to use the appropriate generic view; you want to display a list of items, so use a ListView.
class Success(ListView):
template_name = 'success.html'
model = events
and in your template do {% for item in events_list %}.

How to pass a variable from a template to a view in Django

I am not able to GET a variable from a template into another view.
I have a table with some records. Each row has a button which I would like to click and retrieve more details about the record in another page. I have been looking online but I cannot figure out how I should implement this. Everything I have tried either crashed or gave back None.
list.html
{% for trainee in trainees_list %}
<tr>
<td>{{ trainee.last_name }}</td>
<td>{{ trainee.first_name }}</td>
<td><a class="btn btn-primary" href="{% url 'traineedetails'%}" value="{{ trainee.pk }}" >View</a></td>
</tr>
{% endfor %}
view.py
def traineedetails(request):
if request.method == 'GET':
trainee_details = request.POST.get('trainee.pk')
print(trainee_details)
return render(request, 'trainee_details.html')
def listoftrainees(request):
trainees_list = UserTraining.objects.all()
return render_to_response('list.html', {'trainees_list': trainees_list})
url.py
urlpatterns = [
path('traineedetails', views.traineedetails, name='traineedetails'),
path('listoftrainees', views.listoftrainees, name='listoftrainees'),
]
form.py
class UserTrainingForm(forms.ModelForm):
scope_requirements = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple, choices=microscopes.MICROSCOPES)
class Meta:
model = UserTraining
fields = (
'first_name',
'last_name',
)
model.py
class UserTraining(models.Model):
first_name = models.CharField('first name', max_length = 100)
last_name = models.CharField('last name', max_length = 100)
I would like to be able to click on the button in the row of the table and retrive more information about the record.
You pass the value directly in the url like : traineedetails/<pk>
In the template:
{% for trainee in trainees_list %}
<tr>
<td>{{ trainee.last_name }}</td>
<td>{{ trainee.first_name }}</td>
<td><a class="btn btn-primary" href="{% url 'traineedetails' trainee.pk%}">View</a></td>
</tr>
{% endfor %}
Edit your urls.py:
path('traineedetails/<pk>', views.traineedetails, name='traineedetails'),
Then you can retrieve it in your view like this:
from django.shortcuts import get_object_or_404
def traineedetails(request, pk):
if request.method == 'GET':
#try to get your objet or throw a 404 error
trainee = get_object_or_404(UserTraining, pk=pk)
#pass it back to the template
return render(request, 'trainee_details.html',{'trainee':trainee})

Displaying FK's in Django forms as a select field properly

I have two Django models:
from django.db import models
class Show(models.Model):
show_title = models.CharField(max_length=250)
def __unicode__(self):
return self.show_title
class ShowDates(models.Model):
show_date = models.DateTimeField(default=datetime.now)
show = models.ForeignKey(Show)
def __unicode__(self):
return str(self.show_date)
I am putting some Shows in the admin.py as well as some dates associated to the show.
from django.contrib import admin
from .models import Show, ShowDates
class ShowDatesInline(admin.StackedInline):
model = ShowDates
extra = 0
class ShowAdmin(admin.ModelAdmin):
list_display = ('show_title',)
inlines = [ShowDatesInline]
admin.site.register(Show, ShowAdmin)
This is working great for entering in the shows and their respective dates. I am confused as to how to display the dates as a form select field that are related to the show. I currently have the following in my views.py
from django.shortcuts import render
from django.core import urlresolvers
from .models import Show
from .forms import ShowDatesForm
def index(request, template):
shows = Show.objects.all()
return render(request, template, {
'shows': shows,
})
and here is the template using this code:
<table class='table'>
<thead>
<tr>
<th>Show Title</th>
<th>Show Date(s)</th>
</tr>
</thead>
<tbody>
{% for show in shows %}
<tr>
<td>{{ show.show_title }}</td>
<td>
<form action="." method="post">
{% csrf_token %}
<select name="attributes" class="required" required>
<option value="">---- Please Select ----</option>
{% for show_date in show.showdates_set.all %}
<option value="{{ show_date.show_date }}">
{{ show_date.show_date }}
</option>
{% endfor %}
</select>
</form>
</td>
</td>
{% endfor %}
</tbody>
</table>
I feel this is the wrong way to go about it. Can someone lend a hand as to how to display the show dates related to the proper show so that when a user saves this form, the proper show and showdate save?
If you use a ModelForm, django will handle all of that for you.