I am trying to extract the data from a model and show it to a template, but the data are not showing. Any help will be appreciated.
Here is the model:
class Schedule(models.Model):
team1 = models.CharField(max_length=50)
team1_pic = models.ImageField()
team2 = models.CharField(max_length=50)
team2_pic = models.ImageField()
timestamp = models.TimeField(default="", blank=True, null=True)
datestamp = models.DateField(default="", blank=True, null=True)
location = models.CharField(max_length=200)
Here is the view:
def schedule(request):
schedule = Schedule.objects.all()
context = {
'schedule': schedule
}
return render(request, 'schedule.html')
And finally the template:
<!-- Schedule Section Begin -->
<section class="schedule-section spad">
<div class="container">
<div class="row">
<div class="col-lg-8 left-blog-pad">
<div class="schedule-text">
<h4 class="st-title">World Cup 2019</h4>
<div class="st-table">
{% for sch in schedule %}
<table>
<tbody>
<tr>
<td class="left-team">
<img src="{% static 'img/schedule/flag-1.jpg' %}" alt="">
<h4>{{ sch.team1 }}</h4>
</td>
<td class="st-option">
<div class="so-text">{{ sch.location }}</div>
<h4>VS</h4>
<div class="so-text">{{ sch.date }}</div>
</td>
<td class="right-team">
<img src="{% static 'img/schedule/flag-2.jpg' %}" alt="">
<h4>{{ sch.team1 }}</h4>
</td>
</tr>
</tbody>
</table>
</div>
{% endfor %}
</div>
</div>
You need to pass context too.
def schedule(request):
schedule = Schedule.objects.all()
context = {
'schedule': schedule
}
return render(request, 'schedule.html',context)
Related
I have following model, where pagination works ok only if I don't filter by tags. As soon as I filter ads by tags, pagination doesn't work.
class AdListView(ListView):
paginate_by = 2
model = Ad
context_object_name = 'ads'
def get_context_data(self, **kwargs):
if self.request.GET.get('tags') is None:
context = super().get_context_data(**kwargs)
context.update(tags=Tag.objects.all())
return context
else:
tag_submitted = Tag.objects.get(name=self.request.GET.get('tags'))
ads_by_tag = tag_submitted.related_ads.all()
context = {
'ads': ads_by_tag
}
context.update(tags=Tag.objects.all())
return context
What needs to be done so that pagination works for both cases, with and without filter?
below are models.py and template
models.py
class Tag(BaseModel):
def __str__(self):
return str(self.name)
class Ad(BaseModel):
name = models.CharField(max_length=100)
description = models.TextField(max_length=500)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
seller = models.ForeignKey(Seller, on_delete=models.CASCADE)
date_created = models.DateField(auto_now_add=True)
date_modified = models.DateField(auto_now=True)
tags = models.ManyToManyField(Tag, related_name='related_ads')
price = models.PositiveIntegerField(default=0)
archived = models.BooleanField(default=False)
def __str__(self):
return str(self.name)
class Meta:
ordering = ['-date_created']
template
{% block content %}
<div class="container">
<div class="row">
<div class="w-75">
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Title</th>
</tr>
</thead>
<tbody>
{% for ad in ads %}
<tr>
<td>{{ forloop.counter }}</td>
<td> {{ ad.name }} </td>
</tr>
{% empty %}
<li>No ads yet.</li>
{% endfor %}
</tbody>
</table>
</div>
<div class="w-25">
<table class="table">
<thead>
<tr>
<th scope="col">Tags</th>
</tr>
</thead>
<tbody>
{% for tag in tags %}
<tr>
<td> {{ tag }} </td>
</tr>
{% empty %}
<li>No tags yet.</li>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div class="row">
<div class="pagination">
<span class="step-links">
{% if page_obj.has_previous %}
« first
previous
{% endif %}
<span class="current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
next
last »
{% endif %}
</span>
</div>
</div>
</div>
{% endblock %}
so this is a project to learn django, so any other comments on how to improve the code also welcome.
You should not filter in the .get_context_data() [Django-doc]. In Django you pass the (possibly) filtered queryset in .get_queryset(…) [Django-doc]. Django will then paginate the queryset, and add it to the context. By overriding the item in the context, you now have removed the paginated queryset, and added a filtered queryset instead.
You thus provide the filtered queryset, and let Django do the proper pagination:
class AdListView(ListView):
paginate_by = 2
model = Ad
context_object_name = 'ads'
def get_search_querystring(self):
copy = self.request.GET.copy()
copy.pop(self.page_kwarg, None)
return copy.urlencode()
def get_queryset(self, *args, **kwargs):
qs = super().get_queryset(*args, **kwargs)
if 'tags' in self.request.GET:
return qs.filter(tags__name=self.request.GET['tags'])
return qs
def get_context_data(*args, **kwargs):
return super().get_context_data(*args, tags=Tag.objects.all(), **kwargs)
Another problem is the link in the template: by using ?page={{ page_obj.next_page_number }}, this will "drop" the query string [wiki] that contains the search query, and only use page as the only variable in the query string.
In the template we thus can use the URL as:
<a href="?page={{ page_obj.next_page_number }}&{{ view.get_search_queryset|safe }}">
the same should happen with the other pagination links.
Good day dear Community!
my Model:
class CheckList(models.Model):
author = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
...
datecompleted = models.DateTimeField(null=True)
post_date = models.DateTimeField(auto_now=True)
form.py:
class CompletionChecklistForm(forms.ModelForm):
class Meta:
model = CheckList
fields = ('vessels_name', 'datecompleted')
now I'd like to update 'datecompleted' field:
views.py:
class CompleteItemView(UpdateView):
model = CheckList
form_class = CompletionChecklistForm
template_name = 'completion_checklist.html'
success_url = reverse_lazy('home')
def form_valid(self, form):
form.instance.datecompleted = timezone.now()
form.instance.save()
return super(CompleteItemView, self).form_valid(form)
Template:
{% block content %}
<h2 class="d-flex justify-content-center">Completion of current Checklist</h2>
<br>
<br>
<container class="d-flex justify-content-center">
<div class="form-group w-50">
<h4>Complete: {{ object.vessels_name }}?</h4><br>
{{ object.datecompleted }}
<form method="post">
{% csrf_token %}
<div class="clearfix">
<button class="btn btn-danger float-left" type="submit">Yes</button>
No, back
</div>
</form>
</div>
</container>
{% endblock %}
There is no error message but and field value doesn't change as well.
Am I right with my View?
Thank you in advance.
I am trying to write a controller to handle the button click of the "New" button. The goal is for the lower block of code (starting <div ng-show="buttonClick">) to be initially hidden. When "New" button is clicked I would like the lower block of code to appear.
The problem I'm having is that the lower block of code is visible when I load the page. It is never hidden.
{% extends "base.html" %}
{% block content %}
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div class="container-fluid">
<div class="row">
<div class="col-sm-10 col-sm-offset-1">
<h2>Ratings</h2>
<table class="table table-bordered">
<thead>
<tr>
<th>Beer Name</th>
<th>Beer Rating</th>
<th>Notes</th>
<th>Brewer</th>
</tr>
</thead>
<tbody>
{% for rating in ratings %}
<tr>
<td>{{ rating.beer_name }}</td>
<td>{{ rating.score }}</td>
<td>{{ rating.notes }}</td>
<td>{{ rating.brewer }}</td>
<td>Edit</td>
<td><a class="btn btn-primary" href="{% url 'rating-delete' rating.id %}" value="{{ rating.id }}" name="delete" >Delete</a></td>
</tr>
{% endfor %}
</tbody>
</table>
<div ng-app="myApp" ng-controller="myCtrl">
<a ng-model="buttonClick" ng-click="is_clicked()" class="btn btn-primary">New</a>
</div>
</div>
</div>
<div ng-show="buttonClick" >
<div class="container-fluid">
<div class="row">
<div class="col-sm-10 col-sm-offset-1">
<h2>Enter a new rating</h2>
<form role="form" method="post">
{% csrf_token %}
<p>Beer Name: {{ form.beer_name }}</p>
<p>Score: {{ form.score }}</p>
<p>Notes: {{ form.notes }}</p>
<p>Brewer: {{ form.brewer }}</p>
<p><button type="submit" class="btn btn-primary">Submit</button></p>
</form>
</div>
</div>
</div>
</div>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope){
$scope.buttonClick = false;
$scope.is_clicked = function() {
$scope.buttonClick=true;
console.log($scope.buttonClick)
}
})
</script>
{% endblock %}
On this line
app.controller('myCtrl', function($scope)) {
Remove the last )
When your code will work, you will probably have a "blink" effect with your block. It will appear at the loading of the page, then it will disappear when Angular will start. If you have the "blink" effect, you will need to add ng-cloack on the block.
<div ng-show="buttonClick" ng-cloak>
I'd probably try it like this (untested):
<div ng-app="myApp" ng-controller="myCtrl">
<div><a ng-click"buttonClick = !buttonClick" class="btn btn-primary">New</a></div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope)) {
$scope.buttonClick = false;
}
</script>
The page is supposed to display the contents of the database in a table, with a "New" button to add a new entry to the db. When the user clicks the "New" button, a form appears below. It is a ModelForm for the user to input a new entry to the Model, and then submit via a "Submit" button below. This was working as expected, until I added in an AngularJS controller to handle the button click of "New". The problem is my "Submit" button does not work. I want it to submit the data to the ModelForm, but it appears to do nothing.
Here is my template:
{% extends "base.html" %}
{% block content %}
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div class="container-fluid">
<div class="row">
<div class="col-sm-10 col-sm-offset-1">
<h2>Ratings</h2>
<table class="table table-bordered">
<thead>
<tr>
<th>Beer Name</th>
<th>Beer Rating</th>
<th>Notes</th>
<th>Brewer</th>
</tr>
</thead>
<tbody>
{% for rating in ratings %}
<tr>
<td>{{ rating.beer_name }}</td>
<td>{{ rating.score }}</td>
<td>{{ rating.notes }}</td>
<td>{{ rating.brewer }}</td>
<td>Edit</td>
<td><a class="btn btn-primary" href="{% url 'rating-delete' rating.id %}" value="{{ rating.id }}" name="delete" >Delete</a></td>
</tr>
{% endfor %}
</tbody>
</table>
<div ng-app="myApp" ng-controller="myCtrl">
<a ng-model="buttonClick" ng-click="is_clicked()" class="btn btn-primary">New</a>
<div ng-show="buttonClick" ng-cloak>
<div class="container-fluid">
<div class="row">
<div class="col-sm-10 col-sm-offset-1">
<h2>Enter a new rating</h2>
<form role="form" method="post">
{% csrf_token %}
<p>Beer Name: <input type="text" ng-model="myForm.beer_name"></input></p>
<p>Score: <input type="number" step="0.1" ng-model="myForm.score"></input></p>
<p>Notes: <input type="text" ng-model="myForm.notes"></input></p>
<p>Brewer: <input type="text" ng-model="myForm.brewer"></input></p>
<p><button ng-click="submit_to_form(myForm)" type="submit" class="btn btn-primary">Submit</button></p>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http){
$scope.myForm = {beer_name:'beer_name', score:'score', notes:'notes', brewer:'brewer'};
$scope.buttonClick = false;
$scope.is_clicked = function() {
$scope.buttonClick=true;
console.log($scope.buttonClick)
}
$scope.submit_to_form = function(data) {
$http.post('rating-home', data);
}
})
</script>
{% endblock %}
And urls.py:
from django.conf.urls import url
from django.contrib import admin
from ratings.views import home, RatingCreate, delete, edit
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', RatingCreate.as_view(), name='rating-home'),
url(r'rating/add/$', RatingCreate.as_view(), name='rating-add'),
url(r'rating/delete/(?P<row_id>[0-9]+)/$', delete , name='rating-delete'),
url(r'rating/edit/(?P<row_id>[0-9]+)/$', edit , name='rating-edit'),
]
And views.py for the Submit button:
class RatingCreate(View):
""" Create a new Rating """
form_class = RatingForm
template_name = 'home.html'
def get(self, request):
form = self.form_class()
context = {'ratings': Rating.objects.all(), 'form': form}
#return render(request, 'home.html', context)
return render(request, self.template_name, context)
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
_ = form.save()
return redirect('rating-home')
return render(request, self.template_name, {'form: form'})
You should handle submitting the form with angular
<form ng-submit="myFunc(myData)">
<input type="text" ng-model="myData.name">
<input type="text" ng-model="myData.phone">
<button type="submit">Submit</button>
</form>
OR
<form >
<input type="text" ng-model="myData.name">
<input type="text" ng-model="myData.phone">
<button ng-click="myFunc(myData)">Submit</button>
</form>
and your controller:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope){
$scope.myData= {name:'' , phone:''};
$scope.myFunc = function(data) {
console.log(data);
// data(myData array) can be send with angular $http.post() method
// e.g. : $http.post('/myUrl/', data)
}
})
Update:
Here is a good tutorial for angular $http service!
I have a table and buttons inside a loop, this picture shows the results of what I get depending on the search
html
<div class="col-sm-4" ng-repeat="x in names">
<div class="panel panel-primary" id= "{{ x.myIndex }}" >
<div class="panel-heading">
<h3 class="panel-title">{{ x.ID }} {{ x.Name }}
<button ng-click="showCommentsWithID(x.ID)" style="float: right;" class="btn btn-xs btn-primary glyphicon glyphicon-comment"> 42</button>
</h3>
</div>
<div class="panel-body">
<table width="" border="0" ng-repeat="c in comments" id= "{{ c.ID}}" ">
<tr>
<td width="30">{{ c.ID }}</td>
<td >{{ c.Comment}}</td>
</tr>
</table>
</div>
</div>
</div><!-- /.col-sm-4 -->
js
function ContactController($scope,$http) {
$scope.showCommentsWithID= function(myID) {
var page = "mySQL.php?func=getComments&id=" + myID;
$http.get(page).success(function(response) {$scope.comments = response;});
}
}
When I click on the comment Button I want to display the comments according to that ID.
This is working fine except that the comments are loaded to all tables and not only to the table with the right ID. In this example I clicked on ID 1 Coka Cola.
Where do I need to apply a filter the js or html? both? ...
![enter image description here][3]stack.imgur.com/gqyPR.jpg
You can simply bind your comments with your product's id in order to make it unique for each product.
What we need to do is to add product's id to $scope.comments as following:
function ContactController($scope,$http) {
$scope.comments = {}; // Init comments object.
$scope.showCommentsWithID= function(myID) {
var page = "mySQL.php?func=getComments&id=" + myID;
$http.get(page).success(function(response) {$scope.comments[myID] = response;});
}
}
Then, you can simply loop through it:
<table width="" border="0" ng-repeat="c in comments[x.ID]" id= "{{ c.ID}}" ">
<tr>
<td width="30">{{ c.ID }}</td>
<td >{{ c.Comment}}</td>
</tr>
</table>