I have created a model 'VehicleDetails' in which a user can fill the details of a vehicle and another model 'TripStatus' in which he can update the vehicle location. I wanted to get the latest location for which I did as in my below code. But when i running the server, it returns all the values not the latest value. I would appreciate helping me solve this or suggesting a new approach.
models.py:
class VehicleDetails(models.Model):
Vehicle_No = models.CharField(max_length=20)
class TripStatus(models.Model):
vehicledetails = models.ForeignKey(VehicleDetails, related_name='tripstatuss')
CHOICES = (('Yet to start', 'Yet to start'),('Trip starts', 'Trip starts'), ('Chennai','Chennai'), ('Vizag', 'Vizag'), ('Kolkata', 'Kolkata'))
Vehicle_Status = models.CharField(choices=CHOICES, default="Yet to start", max_length=20)
statustime = models.DateTimeField(auto_now=False, auto_now_add=True)
views:
def status(request):
tripstatus = TripStatus.objects.all().latest('statustime')
context = {
"tripstatus": tripstatus,
}
return render(request, 'loggedin_load/active_deals.html', context)
template:
{% for status in vehicledetails.tripstatuss.all %}
{{status.Vehicle_Status}}
{% endfor %}
Should just have to remove the .all():
tripstatus = TripStatus.objects.latest('statustime')
Or maybe:
tripstatus = TripStatus.order_by('-statustime').first()
Related
I am a new django/python user and I am having an issue using django-filters with related models. I have created a tutorial application for myself with two models:
class Customer(models.Model):
def __str__(self):
return self.Customer_Name
Customer_Name = models.CharField(max_length=100)
SFDC_Customer_Record_Number = models.IntegerField(default='')
Zone = models.CharField(max_length=50, default='')
Government = models.BooleanField(default=False)
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.DO_NOTHING,default=User)
class Vue_Quote(models.Model):
def __str__(self):
return self.Quote_Name
Quote_Name = models.CharField(max_length=100)
SFDC_Golden_Opp_ID = models.IntegerField()
Vue_System_Count = models.IntegerField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.DO_NOTHING,default=User)
Quote_Type = models.CharField(max_length=100)
Customer = models.ForeignKey(Customer , on_delete=models.DO_NOTHING, default='')
I have also created a filter.py file:
import django_filters
from .models import *
class CustomerFilter(django_filters.FilterSet):
class Meta:
model = Customer
fields = {
'Customer_Name': ['icontains'],
'Zone' : ['icontains'],
}
class QuoteFilter(django_filters.FilterSet):
class Meta:
model = Vue_Quote
fields = {
'Quote_Name': ['icontains'],
'author__username' : ['icontains'],
'Customer__Customer_Name' : ['icontains'],
}
In my templates I want to display the filter fields for quoteFilter and customerFilter (this is working). Then I have a sort of gallery/list that iterates through each customer and their respective quotes. My issue is that only my customerFilter works. I cannot find anyway to create nested for loops that can provide results for the user input across both model's fields.
Here is my current html which works for the customer filter but does not attempt to filter the quote content at all:
% extends "base.html" %}
{% load bootstrap %}
{% block content %}
<form method="get">
{{customerFilter.form|bootstrap}}
{{quoteFilter.form|bootstrap}}
<button class= "btn btn-primary" type="submit">Search</button>
</form>
{% if user.is_authenticated %}
<h2>Quote Explorer Gallery</h2>
<p></p>
{% for Customer in customerFilter.qs %}
{% for Quote in Customer.vue_quote_set.all %}
<HTML WITH CONTENT CONTINUES HERE>
Here is my view in case anyone needs to see it:
Customers = Customer.objects.all()
Quotes = Vue_Quote.objects.all().prefetch_related('Customer')
customerFilter = CustomerFilter(request.GET, queryset=Customers)
quoteFilter = QuoteFilter(request.GET, queryset=Quotes)
context = {
'Users': User.objects.all(),
'Customers': customerFilter.qs,
'Quotes': quoteFilter.qs,
'customerFilter' : customerFilter,
'quoteFilter' : quoteFilter,
}
print(context)
return render(request, 'home.html', context)
If anyone can advise how I can change my nested for loop, or how I can address the entire multi-model search differently I would be very grateful. Thank you.
so i'm still on my todo list and i want to know when an activity has passed so as to flag it as expired.
my views.py
def progress(request):
activities = ToDo.objects.all()
today = timezone.localtime(timezone.now())
context = {
'activities' : activities,
'today' : today,
}
return render(request, 'percent.html', context)
in my templates i have it as:
{% for activity in activities %}
{% if activity.end.date < today.date %}
{{activity}} <br>
{% endif %}
{% endfor %}
i'm going to add my models.py for referencing
class ToDo(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE)
todo = models.CharField(max_length=50)
description = models.TextField(max_length=200, blank=True)
created = models.DateField(auto_now=True)
end = models.DateField()
start = models.DateField()
completed = models.BooleanField(default=False)
def __str__(self):
return f'{self.owner} - {self.todo}'
or would it be easier to add an expired boolean field to my models? i'm so confused
Note: You need to use Celery Beat as a scheduler.
import datetime
def expired_activity():
today = datetime.date.today()
expired_activity = ToDo.objects.filter(end=today)
if expired_activity:
expired_activity.update(completed=True)
If you don't want to use any scheduler, you can get expired items in another request, using ORM Manager:
from django.db import models
class ToDoManager(models.Manager):
def active(self):
return self.excude(end__lt=today().date)
def expired(self):
return self.filter(end__lt=today().date)
class ToDo(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE)
todo = models.CharField(max_length=50)
description = models.TextField(max_length=200, blank=True)
created = models.DateField(auto_now=True)
end = models.DateField()
start = models.DateField()
completed = models.BooleanField(default=False)
objects = ToDoManager()
def __str__(self):
return f'{self.owner} - {self.todo}'
And in your view you'll get them in a different requests:
ToDo.objects.active()
ToDo.objects.expired()
Or you can change manager with setting expired flag and saving results when requesting data from db
I'm a newbie in Python and I need some help with my code. Not even sure if my title makes sense.
Basically I have my blog and I'm trying to add a sidebar with popular posts. I have created a PostStatistics class to collect the number of visits in each post which can be seen from Django admin.
The PostStatistics class has a ForeignKey to the Post class.
OK, so my problem is in the PostDetail view. I have a QuerySet there called Popular where I retrieve the 5 most popular posts in the last 7 days. There I retrieve the Post_id and Post__Title. I also need to retrieve the Post SLUG but I have no idea how I can do that.
The slug would be used in the following bit of code:
{{ pop_article.post__title }}
The following is what in my models:
class Post(models.Model):
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True)
author = models.ForeignKey(
User, on_delete=models.CASCADE, related_name='blog_posts')
updated_on = models.DateTimeField(auto_now=True)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=STATUS, default=0)
views = models.PositiveIntegerField(default=0, editable=False)
class Meta:
ordering = ['-created_on']
db_table = "post"
def __str__(self):
return self.title
def get_absolute_url(self):
from django.urls import reverse
return reverse("post_detail", kwargs={"slug": str(self.slug)})
class PostStatistic(models.Model):
class Meta:
db_table = "PostStatistic"
post = models.ForeignKey(Post, on_delete=models.CASCADE)
date = models.DateField('Date', default=timezone.now)
views = models.IntegerField('Views', default=0)
def __str__(self):
return self.post.title
The following is what is in my views:
def PostDetail(request, slug):
template_name = 'post_detail.html'
post = get_object_or_404(Post, slug=slug)
comments = post.comments.filter(active=True)
new_comment = None
context = {}
obj, created = PostStatistic.objects.get_or_create(
defaults={
"post": post,
"date": timezone.now()
},
# At the same time define a fence or statistics object creation
# by two fields: date and a foreign key to the article
date=timezone.now(), post=post
)
obj.views += 1
obj.save(update_fields=['views'])
# Now pick up the list of the last 5 most popular articles of the week
popular = PostStatistic.objects.filter(
# filter records in the last 7 days
date__range=[timezone.now() - timezone.timedelta(7), timezone.now()]
).values(
'post_id', 'post__title'
).annotate(
views=Sum('views')
).order_by(
# sort the records Descending
'-views')[:5] # Take 5 last records
# Comment posted
if request.method == 'POST':
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
# Create Comment object but don't save to database yet
new_comment = comment_form.save(commit=False)
# Assign the current post to the comment
new_comment.post = post
# Save the comment to the database
new_comment.save()
else:
comment_form = CommentForm()
return render(request, template_name, {'post': post,
'comments': comments,
'new_comment': new_comment,
'comment_form': comment_form,
'popular_list': popular
},)
The following is in my HTML:
<div class="card-body">
{% if popular_list %}
<p class="card-text">
{% for pop_article in popular_list %}
{{ pop_article.post__title }}
<br>
{% endfor %}
</p>
{% endif %}
</div>
Thanks in advance!
you need to add post__slug in values of this query in view function like this
popular = PostStatistic.objects.filter(
# filter records in the last 7 days
date__range=[timezone.now() - timezone.timedelta(7), timezone.now()]
).values(
'post_id','post__slug' ,'post__title'
).annotate(
views=Sum('views')
).order_by(
# sort the records Descending
'-views')[:5]
then you will be able to do like this in the template
{{ pop_article.post__title }}
I'm looking for some help with filtering my model twice in Django.
This is my current model:
class Medarbejder(models.Model):
id = models.AutoField(primary_key=True)
slug = models.SlugField(max_length=200)
ma = models.IntegerField(help_text="Indtast medarbejderens MA-nummer. (F.eks 123456)")
fornavn = models.CharField(max_length=30, help_text="Indtast medarbejderens fornavn.")
efternavn = models.CharField(max_length=30, help_text="Indtast medarbejderens efternavn.")
holdnavn = models.CharField(max_length=200, null=False, help_text="Indtast medarbejderens hold.")
delingnavn = models.ForeignKey('Deling', on_delete=models.CASCADE, null=True)
fagnavn = models.ForeignKey('Fag', on_delete=models.CASCADE, null=True)
The model is a model for employees (medarbejder). Now I wish to filter the teamname (holdnavn) with distinct, which I have accomplished. The next step is to then filter all the departments (delingnavn) within each teamname (holdnavn). So when I click on one teamname such as "GSU19", then I wish to get a list of all the departments within that teamname only.
I can't seem to wrap my head around how to do this? I am able to do it with slug and with pk, but both teamname and department are not a slug or a pk, so I'm abit lost to how to get the value in the url and filter again.
This is currently how the URL looks after I click on a specific teamname:
http://127.0.0.1:8000/hold/%3CQuerySet%20%5B%7B'delingnavn_id':%202%7D,%20%7B'delingnavn_id':%204%7D,%20%7B'delingnavn_id':%205%7D,%20%7B'delingnavn_id':%203%7D,%20%7B'delingnavn_id':%206%7D,%20%7B'delingnavn_id':%204%7D,%20%7B'delingnavn_id':%202%7D,%20%7B'delingnavn_id':%204%7D,%20%7B'delingnavn_id':%205%7D,%20%7B'delingnavn_id':%205%7D,%20%7B'delingnavn_id':%206%7D,%20%7B'delingnavn_id':%206%7D,%20%7B'delingnavn_id':%202%7D,%20%7B'delingnavn_id':%203%7D,%20%7B'delingnavn_id':%202%7D,%20%7B'delingnavn_id':%203%7D,%20%7B'delingnavn_id':%203%7D%5D%3E/
I'm getting all the department id's in the url..which is not what I want, I want them to be looped out in my template. Below is my current ListView:
class HoldDetailView(ListView):
model = Medarbejder
template_name = 'evalsys/medarbejder/list.html'
def get_context_data(self, **kwargs):
context = super(HoldDetailView, self).get_context_data(**kwargs)
context['medarbejder_hold'] = Medarbejder.objects.filter().values('holdnavn').distinct().order_by('holdnavn')
context['medarbejder_deling'] = Medarbejder.objects.filter().values('delingnavn_id').distinct()
return context
def get_object(self, holdnavn=None):
if holdnavn:
medarbejder_deling = Medarbejder.objects.filter().values('delingnavn_id').distinct()
else:
medarbejder_deling = self.medarbejder_deling
return render(self, 'evalsys/medarbejder/list.html',
{ 'medarbejder_deling': medarbejder_deling})
Please ask any questions and I'll supply more code, I think my approach is incorrect, but I can't seem to figure out how to go about it.
For clarification:
Delingnavn = DepartmentName and is a foreign key to Departments.
Holdnavn = TeamName
Fornavn = FirstName
Efternavn = LastName
FagNavn = SubjectName
I wish to get all the teamNames, click on one, and see all the departments within that team.
Update
In template:
{% for h in medarbejder_hold %}
<li>
{{ h.holdnavn }}
</li>
{% endfor %}
And I've done it like this because usually I use slug or pk...
URLs:
path('', views.HoldDetailView.as_view(), name='home'),
path('hold/<str:holdnavn>/', views.HoldDetailView.as_view(), name='get_object'),
This code is all over the place, unfortunately. get_object isn't ever called in a ListView, which is just as well; you can't render inside that method, it's for returning an object. And as I said, the URL itself is nonsense, you can't expect to just dump a queryset into a URL.
But it's not clear why you think you need to do either of these. If you want to filter by a specific holdnavn, then just pass that value into the URL and filter appropriately. (Note, I've changed the way you get the list of holdavn to make things a bit simpler.)
{% for holdnavn in medarbejder_hold %}
<li>
{{ holdnavn }}
</li>
{% endfor %}
class HoldListView(ListView):
model = Medarbejder
template_name = 'evalsys/medarbejder/list.html'
context_object_name = 'medarbejder_deling'
def get_context_data(self, **kwargs):
context = super(HoldDetailView, self).get_context_data(**kwargs)
context['medarbejder_hold'] = Medarbejder.objects.filter().values_list('holdnavn').distinct().order_by('holdnavn')
return context
def get_queryset(self):
qs = super().get_queryset()
if 'holdavn' in self.kwargs:
qs = qs.filter(holdavn=self.kwargs['holdavn'])
return qs
I'm new to Django and I'm trying to learn as I go. And I've ended up in a situation where I can't figure out what is the best way forward.
snippet from models.py:
class ProjectMeta(models.Model):
project = models.ForeignKey(Project)
architect = models.CharField(max_length=200)
landscape = models.CharField(max_length=100, blank=True)
engineer = models.CharField(max_length=200, blank=True)
client = models.CharField(max_length=100)
consultant = models.CharField(max_length=100, blank=True)
size = models.DecimalField(max_digits=5, decimal_places=2, blank=True)
location = models.CharField(max_length=200)
date = models.DateField()
STATUS = (
('CP', 'Competition'),
('UC', 'Under construction'),
('CO', 'Completed'),
)
status = models.CharField(max_length=2, choices=STATUS, default=1)
And this is the view:
class ProjectDetailView(DetailView):
model = Project
def get_context_data(self, **kwargs):
context = super(ProjectDetailView, self).get_context_data(**kwargs)
context['projectmeta_list'] = ProjectMeta.objects.all()
return context
But if I want to output ProjectMeta in the template I could iterate over projectmeta_list.
{% for metadata in projectmeta_list %}
<p>Architect: {{ metadata.architect }}</p>
{% endfor %}
But this require alot of repeating myself, and I wont work. Because lets say the architect field is empty, I would get Archiect: printed to the page. Is there a built-in way of converting a model into a dict or list, so I can iterate over it and only print out fields that aren't empty to the page?
I've been looking at get_fields(), would that work? https://docs.djangoproject.com/en/1.10/ref/models/meta/#retrieving-all-field-instances-of-a-model
I tried this in the shell, threw me and AttributeError:
>>> from projects.models import *
>>> Project._projectmeta.get_fields()
You should try wrapping the <p>Architect: {{ metadata.architect }}</p> piece in a conditional {% if metadata.architect != '' %} or some condition to that effect.
Try with another ProjectMeta model. Take a look at this one.
class ProjectMeta(models.Model):
project = models.ForeignKey(Project)
name = models.CharField(max_length=50)
value = models.TextField()
And this query should work. myproject.projectmeta_set.filter(name="status")
You can use built-in default or default_if_none template filters to show a default value if it is None or empty string.
{% for metadata in projectmeta_list %}
<p>Architect: {{ metadata.architect|default:"-" }}</p>
{% endfor %}
Check this for more details.