Django 1.8.3: Showing many-to-many additional fields in template - python

I have the following problem: A project can have multiple Roles, How do I show the roles field in a template? project.role shows blank and the problem is even after using _set.all in the template, I still do not get the contents from the database to show.
Model.py
class Project(models.Model):
"""
Information for each Project
"""
project_name = models.CharField(max_length=255, blank=True, null=True, unique=True)
project_description = models.TextField(null=True, blank=True)
project_url = models.URLField(max_length=200, null=True, blank=True)
#For Admin Purposes and filtering, to keep track of new and old in the database by administrative users
date_added = models.DateTimeField(auto_now_add=True, null=True, blank=True, verbose_name=_('Date added'))
last_modified = models.DateTimeField(auto_now=True, null=True, blank=True, verbose_name=_('Last modified'))
class Role(models.Model):
"""
Information for Role
"""
role = models.CharField(max_length=255, blank=True, null=True)
project_role = models.ManyToManyField(Project)
View.py
class ProjectView(ListView):
template_name = '_projects.html'
model = Project
def get_context_data(self, **kwargs):
context = super(ProjectView, self).get_context_data(**kwargs)
context['projects'] = Project.objects.all()
return context
Template
{% for project_info in projects %}
{{project_info.project_name}}
</br>
{{project_info.project_description}}
</br>
{{project_info.project_url}}
</br>
{% for rolling in project_info.project_role_set.all %}
{{rolling}}
{% endfor %}
{% endfor %}

Try this:
{% for rolling in project_info.role_set.all %}
{{rolling}}
{% endfor %}

Related

Objects have the same ID on production in Django App

I have project in Python Django. It has three models: Project, Files and Agreement.
class Project(models.Model):
project_name = models.CharField(max_length=50)
client_name = models.CharField(max_length=50)
agreement_number = models.CharField(max_length=20)
brief_status = models.CharField(max_length=20, choices=BRIEF_CHOICES, default='nieuzupelniony')
agreement_status = models.CharField(max_length=20, choices=AGREEMENT_CHOICES, default='niedostarczona')
resources_status = models.CharField(max_length=20, choices=RESOURCES_CHOICES, default='niedostarczone')
payment_status = models.CharField(max_length=20, choices=PAYMENT_CHOICES, default='nieoplacone')
message = models.CharField(max_length=200, default='Brak wiadomoĊ›ci')
project_date = models.CharField(max_length=10)
status = models.CharField(max_length=100)
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="project")
modifications = models.CharField(max_length=15, default='2')
corrections = models.CharField(max_length=15, default='3')
def __str__(self):
return self.project_name
class Files(models.Model):
name = models.CharField(max_length=50)
upload = models.FileField(upload_to='uploads/', validators=[validate_file_extension])
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="files")
project = models.ForeignKey(Project, on_delete=models.CASCADE)
def __str__(self):
return self.name
class Agreement(models.Model):
name = models.CharField(max_length=50)
upload = models.FileField(upload_to='uploads/', validators=[validate_file_extension])
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="agreement")
project = models.ForeignKey(Project, on_delete=models.CASCADE)
def __str__(self):
return self.name
In app we have an admin and users. Every user has welcome.html page which display every user project, every user agreement and objects from one additional model which isn't important. When user click on project (user goes to project_detail.html), he can see information about project and there are all files from this project.
def panel(request):
if request.user.is_authenticated:
queryset = Project.objects.filter(user=request.user)
queryset2 = Invoice.objects.filter(user=request.user)
queryset3 = Files.objects.filter(user=request.user)
queryset4 = Agreement.objects.filter(user=request.user)
return render(request, 'projects/welcome.html', {'project': queryset, 'invoice': queryset2, 'files': queryset3, 'agreement': queryset4})
else:
return render(request, 'projects/welcome.html')
Admin has user_detail.html page, and there are all files and projects and agreements for this user.
class UserDetailView(DetailView):
model = User
template_name = 'projects/user_detail.html'
context_object_name = 'user'
def get_context_data(self, **kwargs):
context_data = super().get_context_data(**kwargs)
context_data['invoice'] = Invoice.objects.all()
context_data['project'] = Project.objects.all()
context_data['files'] = Files.objects.all()
context_data['agreement'] = Agreement.objects.all()
return context_data
Here is a part of my template.
<div class="block bg-white rounded shadow-2xl text-indigo-800 m-2 p-4 w-full h-full">
<p class="text-3xl text-left mb-2 pb-2 border-b">Pliki</p>
{% for files in files.all %}
{% if files.user == user %}
<div class="flex justify-between mb-2 pb-2 border-b pr-32">
{{files.name}}
<p class="text-xl font-thin text-indigo-800 hover:text-indigo-600 text-left mb-2">{{files.project}}</p>
</div>
{% endif %}
{% endfor %}
</div>
Unfortunetly when I tried (as admin) edit any of file I've got an error:
Exception Type: MultipleObjectsReturned
Exception Value:
get() returned more than one Files -- it returned 8!
So to each project you can assign file and agreement. I have problem with my database. On my local environment everything is fine. On local SQlite3 every file object has unique ID, unfortunetly on my producton, on phpMyAdmin every object has the same ID = 0. Where I can find error? I tried working with my models and database, unfortunetly I can't find what is going on. So now I cannot update file for my user even by my Django Admin Dashboard, because I've got an error.
Hi you have a problem in your template you use files in files.all so when you do files.project you get more than one
{% for files in files.all %}
you need to do :
{% for file in files.all %}
....
{{file.project}}</p>

Django: path doesn't find the right primary key in url path

I'm using django2 and I get an error when I access this url:
http://127.0.0.1:8000/hotes/12/access/7/update
I get an error 404 "None access object was found"
To make a long story short:
I want to update an object linked to another. To do so, I have to send through the link, both primary keys (12 and 7 in the url). Also, I use the generic view "UpdateView" given by Django.
This is the path concerned in my project.urls:
urlpatterns = [
path('hotes/<int:pk>/access/<int:access_pk>/update/',views.AccessUpdateView.as_view(), name='access_update'),
path('hotes/add',views.host_add, name='host_add'),
path('hotes/<int:pk>/', include([
path('edit',views.HostUpdateView.as_view(), name='host_update'),
path('delete',views.host_delete, name='host_delete'),
])),
path('hotes/<int:pk>/add/', include([
path('access',views.access_add, name='access_add'),
path('oncall',views.onCall_add, name='onCall_add'),
path('network',views.network_add, name='network_add'),
])),
path('hotes/<int:pk>/',views.host_view, name='host_view'),
path('hotes/',views.hosts_view, name='hosts_view'),
path('', views.home, name='home'),
path('admin/', admin.site.urls),
]
I want the second primary key to be used in my view "AccessUpdateView".
This is a part of my models.py:
class Host(models.Model):
name = models.CharField(max_length=30, unique=True)
usage = models.CharField(max_length=30, blank=True)
function = models.CharField(max_length=30, blank=True)
production = models.NullBooleanField(blank=True, null=True)
place = models.CharField(max_length=30, blank=True)
type = models.CharField(max_length=30, blank=True)
processor = models.DecimalField(max_digits=3, decimal_places=2, null=True, blank=True)
storage = models.CharField(max_length=10, blank=True)
memory = models.CharField(max_length=10, blank=True)
dns_inner = models.CharField(max_length=50, blank=True)
dns_extern = models.CharField(max_length=50, blank=True)
os = models.ForeignKey(Os, null=True, related_name='hosts', on_delete=models.SET_NULL, blank=True)
class Access(models.Model):
service = models.CharField(max_length=20)
client_access = models.NullBooleanField(blank=True, null=True)
ip = models.GenericIPAddressField()
login = models.CharField(max_length=30, blank=True)
password = models.CharField(max_length=50, blank=True)
host = models.ForeignKey(Host, related_name='access', on_delete=models.CASCADE)
As you can see on host can have multiple access but an access in linked to only one host.
This is the view concerned:
class AccessUpdateView(UpdateView):
model = Access
fields = ('service','client_access','ip','login','password', )
template_name = 'access_update.html'
pk_url_kwarg = 'access_pk'
context_object_name = 'access'
def form_valid(self, form):
access = form.save(commit=False)
host_id = self.kwargs['pk']
access.host_id = host_id
access.save()
return redirect('host_view', pk=host_id)
EDIT: new error when I try to access the url:
NoReverseMatch at /hotes/12/access/7/update/
Reverse for 'host_view' with arguments '('',)' not found. 1 pattern(s) tried: ['hotes\/(?P[0-9]+)\/$']
EDIT:
The error was coming from "access_update.html"
I removed the href in the Hote link which contained {% url host.pk %}
{% extends 'base.html' %}
{% load widget_tweaks %}
{% block title %}Modifier Acces{% endblock %}
{% block breadcrumb %}
<li class="breadcrumb-item">Hotes</li>
<li class="breadcrumb-item">Hote</li>
<li class="breadcrumb-item active">Modification Acces</li>
{% endblock %}
{% block contenu %}
<form method="post" novalidate>
{% csrf_token %}
{% include 'includes/form.html' %}
<button type="submit" class="btn btn-success">Modifier</button>
</form>
{% endblock %}
The question is what is the right way to write the pk of the host in the url?
(host_id doesn't work)
If you want to use access_pk, then you should set pk_url_kwarg = 'access_pk' in the view.
In your form_valid method, you are using host without defining it. If pk from the URL is the host id, then you can access it with self.kwargs['pk'].
def form_valid(self, form):
access = form.save(commit=False)
host_id = self.kwargs['pk']
access.host_id = host_id
access.save()
return redirect('host_view', pk=host_id)
Inside the template for the AccessUpdateView, you have access to access since that is the object that is being updated. If you want to use the host or its id, you should access it via access.
{% url 'host_view' access.host_id %}

Django - filtering by user

I want to render data from the Route model that belongs to the Driver in their 'accounts' page - so displaying the leave_from, destination etc data they have saved in the database so far.
Models.py:
class Driver(models.Model):
user = models.OneToOneField(User, default=1)
first_name = models.CharField(max_length=120, blank=True, null=True)
last_name = models.CharField(max_length=120, blank=True, null=True)
tel = models.CharField(max_length=120, blank=True, null=True)
slug = models.SlugField(max_length=120, unique=True)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now_add=False, auto_now=True)
def __str__(self):
return self.user.username
def get_absolute_url(self):
return reverse("account", kwargs={"slug": self.slug})
def save(self, *args, **kwargs):
self.slug = slugify(self.first_name)
super(Driver, self).save(*args, **kwargs)
class Route(models.Model):
leave_from = models.CharField(max_length=120, blank=True, null=True)
destination = models.CharField(max_length=120, blank=True, null=True)
date = models.DateField(auto_now_add=False, auto_now=False)
time = models.TimeField(auto_now_add=False, auto_now=False)
driver = models.ForeignKey(Driver, on_delete=models.CASCADE)
def __str__(self):
return self.leave_from
I've played with various querysets and the below is the closest to getting there (I think... I'm new to coding and Django).
Views.py:
def route(request, slug):
routedetails = Driver.objects.filter(route=request.user.driver.route_set.all())
context = {
"routedetails": routedetails,
}
return render(request, "route.html", context)
With that I am able to get user to display the same number of instances of data in Route for that Driver.
Template:
{% for route in routedetails %}
<p>{{ route.user }}</p>
{% endfor %}
I've tried all different variations but I feel this has got me the closest as it is at least returning the user the same number of times there is data in Route for this user. In this case there are 2 routes saved in Route and so the username is returned twice. I have tested on other users and it always matches.
I've looked everywhere and this is as far as I've been able to get so appreciate any help.
If you want Route details it is best to query the Route model directly:
routedetails = Route.objects.filter(driver__user=request.user)
You can then iterate through the Route objects in your template:
{% for route in routedetails %}
<p>{{ route.leave_from }}</p>
<p>{{ route.destination }}</p>
...
{% endfor %}
Pocket Kings' solution is great and should be accepted. This is an example if you want to show routes for multiple drivers (admin page?) in order to avoid N+1 queries. This pre-fetches all the routes associated to the drivers and adds an attribute routes to each driver with their specific routes, so that it would eliminate the unneeded SQL queries later.
from django.db.models import Prefetch
drivers = Driver.objects.all()
queryset = drivers.prefetch_related(Prefetch('route_set', queryset=Route.objects.filter(driver_id__in=drivers), to_attr='routes'))
Template
{% for driver in drivers %}
{% for route in driver.routes %}
<p>{{ route.leave_from }}</p>
<p>{{ route.destination }}</p>
...
{% endfor %}
{% endfor %}
To get logged in driver's routes, the simplest approach is.
views.py
routes = request.user.driver.route_set.all()
template
{% for route in routes %}
{{ route.leave_from }}
{{ route.destination }}
{% endfor %}

Display data from models in website

I am new to Django. I want to display latest data entered from models to the website.
models.py
class Service(models.Model):
service_name = models.CharField(max_length=200)
service_code = models.IntegerField(default=0, unique=True)
views.py
def Latest(return):
latest_services = Service.objects.order_by('service_name')
index.html
{{ service_name }}
Latest Services Goes here
When I run the code nothing is displayed!
You need to iterate over the queryset:
<ul>
{% for service in latest_services %}
<li>{{ service.service_name }}</li>
{% endfor %}
</ul>
Anyway, if you want to display the latest entries, you should add a new field to your model with the date. For example:
class Service(models.Model):
created_on = models.DateTimeField(auto_now=True)
service_name = models.CharField(max_length=200)
service_code = models.IntegerField(default=0, unique=True)
And then in your query:
latest_services = Service.objects.order_by('created_on')

Extra "row-level" data in ListView django

I'm writing my first django app and can't seem to pass "row-level" data to the template through ListView. Specifically I'm trying to show all Polls and their corresponding Vote information using a PollListView.
Currently I am only able to pass all votes to the template, but would like to pass only the votes that belong to the specific poll.
models.py
class Poll(models.Model):
user = models.ForeignKey(User, unique=False, blank=False, db_index=True)
title = models.CharField(max_length=80)
class Vote(models.Model):
poll = models.ForeignKey(Poll, unique=False, blank=False, db_index=True)
user = models.ForeignKey(User, unique=False, blank=True, null=True, db_index=True)
vote = models.CharField(max_length=30, blank=False, default='unset', choices=choices)
views.py
class PollListView(ListView):
model = Poll
template_name = 'homepage.html'
context_object_name="poll_list"
def get_context_data(self, **kwargs):
context = super(PollListView, self).get_context_data(**kwargs)
context['vote_list'] = Vote.objects.all()
return context
urls.py
urlpatterns = patterns('',
...
url(r'^$', PollListView.as_view(), name="poll-list"),
}
homepage.html
{% for poll in poll_list %}
{{ poll.title }}
{% for vote in vote_list %}
{{ vote.id }} {{ vote.vote }}
{% endfor %}
{% endfor %}
Seems like an easy task, but I can't seem to figure out how to do this using class-based views. Should I be using mixins or extra_context? Overwrite queryset? Or should I just used function-based views to solve this.
Any help would be greatly appreciated.
I'm not sure if it's gonna work, but you can try the following:
models.py (Vote class)
poll = models.ForeignKey(Poll, related_name="votes", unique=False, blank=False, db_index=True)
views.py
class PollListView(ListView):
queryset = Poll.objects.all().prefetch_related('votes')
with that you can access related votes:
template
{% for poll in poll_list %}
{{ poll.title }}
{% for vote in poll.votes.all %}
{{ vote.id }} {{ vote.vote }}
{% endfor %}
{% endfor %}

Categories