django user fields shown empty in template - django

cannot access fields in templates
model.py:
class DSS(models.Model):
title = models.CharField(max_length=255, null=True, blank=True, verbose_name='عنوان')
usr = models.ForeignKey(User, related_name='owner', verbose_name='کاربر')
view.py:
def state(request):
result = DSS.objects.values('usr').order_by('usr').annotate(count=Count('usr'))
context = {'result': result,}
return render(request, 'state.html', context)
my template:
<tr>
<td>{{ item.usr }}{{ item.usr.get_username}}{{ item.usr.username}}{{ item.usr.get_full_name}}</td>
<td>{% with item.usr.get_username as usrnm %}
{{ item.usr.get_full_name|default:usrnm }}
{% endwith %}</td>
<td>{{ item.usr.first_name }} {{ item.usr.lastname }}</td>
<td>{{ item.owner.first_name }}</td>
<td>{{ item.count }}</td>
</tr>
{{ item.count }} work well and {{ item.usr }} just show user id, but I need to display username however none of this tries worked!

Instead of values(), try to send the actual queryset. And to reduce DB hits, you can use select_related(). For example:
result = DSS.objects.select_related('usr').order_by('usr')
Also .annotate(count=Count('usr')) will not work properly. It will show 1 for each item of queryset. Instead, try aggregating.
def state(request):
result = DSS.objects.select_related('usr').order_by('usr')
user_count = result.aggregate(u_count=Count('usr')).get('u_count')
context = {'result': result, 'user_count': user_count}
return render(request, 'state.html', context)
And render it in template:
{{ user_count }}

Instead of
result = DSS.objects.values('usr').order_by('usr').annotate(count=Count('usr'))
Try
result = DSS.objects.values('usr', 'usr__username').order_by('usr').annotate(count=Count('usr'))
And in html
{{ item.usr__username }}

Try to add the __str__ method in the user model.
def __str__(self):
return self.first_name + " " + self.last_name
# use the fields you have in your user model, mine was first_name and last_name

Related

For loop in template django with prefetch_related

I got an issue when trying to access values from other models by using prefetch_related
My model:
class testimport(models.Model):
id=models.AutoField(primary_key=True)
so_hd=models.CharField( max_length=50, unique=True)
ten_kh=models.CharField( max_length=500)
tien_dong=models.IntegerField(blank=True, null=True)
created_at=models.DateTimeField(auto_now_add=True)
objects=models.Manager()
def get_absolute_url(self):
return "/chi_tiet_hop_dong/%s/" % self.so_hd
class report(models.Model):
id=models.AutoField(primary_key=True)
so_hd=models.ForeignKey(testimport, on_delete=models.DO_NOTHING, to_field="so_hd")
nhan_vien=models.ForeignKey(Callers, on_delete=models.DO_NOTHING, null=True, blank= True, to_field="admin_id")
noi_dung=models.TextField()
My views:
....
get_contract_detail=testimport.objects.filter(so_hd__in=get_user).order_by("id").prefetch_related().values()
contract=get_contract_detail.filter(so_hd=so_hd).all()
return render(request, "caller_template/contract_detail.html", {"contract":contract,"the_next":the_next,"the_prev":the_prev, "so_hd":so_hd,"form":form,"form1":form1})
If I try to print out the content by values, it is ok:
print(get_contract_detail.filter(so_hd=so_hd).values("so_hd","report__noi_dung"))
In my template:
{% for report in contract %}
{% for content in report.so_hd.all%}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{content.noi_dung}}</td>
</tr>
{% endfor %}
{% endfor %}
There is no content in cells. How can I show the content
Please help
The reason this does not work is because of the use of .values(…) [Django-doc]. Furthermore you did not specify a related_name=… parameter [Django-doc], so that means that you access the reports with .report_set.all():
contract = testimport.objects.filter(
so_hd__in=get_user, so_hd=so_hd
).order_by('id').prefetch_related() # no .values()
context = {
'contract': contract,
'the_next': the_next,
'the_prev': the_prev,
'so_hd': so_hd,
'form': form,
'form1':form1
}
return render(request, 'caller_template/contract_detail.html', context)
and in the template render with .report_set.all:
{% for report in contract %}
{% for content in report.report_set.all %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ content.noi_dung }}</td>
</tr>
{% endfor %}
{% endfor %}

Display number of views for a specific post for specific user in a table using django

i want to display number of views in a table for a specific post. I already have the data stored in db. it seems that print statement print('count', context['count_view']) is working inside get_context_data method but it is not working as expected in the template. Don't worry about the data inside the image, its actually dummy data. Anyone helpenter image description here
models.py
class ObjectViewed(models.Model):
user = models.ForeignKey(User, blank=True, null=True, on_delete=models.CASCADE)
ip_address = models.CharField(max_length=220, blank=True, null=True)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) # User, Blog, or any other models
object_id = models.PositiveIntegerField() # User id, Blog id, or any other models id
content_object = GenericForeignKey('content_type', 'object_id')
timestamp = models.DateTimeField(auto_now_add=True)
views.py
class PostListView(ListView):
model = Post
template_name = 'edmin/post/postList.html'
context_object_name = 'posts'
ordering_by = ['-created']
def get_queryset(self):
post=Post.objects.filter(author=self.request.user)
return post
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
post=Post.objects.filter(author=self.request.user)
c_type = ContentType.objects.get_for_model(Post)
for p in post:
context['count_view'] = ObjectViewed.objects.filter(content_type=c_type, object_id=p.id).count()
print('count',context['count_view'])
return context
postList.html
{% for post in posts %}
{% if post.status == 'Draft' %}
{% else %}
<tr>
<th scope="row">{{ forloop.counter }}</th>
<td><a style="color:blue" href="{% url 'edmin:post_detail_view' pk=post.pk %}">{{ post.title }}</a></td>
<td>{{ post.banner_title }}</td>
<td>{{ post.created }}</td>
<td>{{ count_view }}</td>
<td>{{ post.status }}</td>
<td>Edit</td>
<td>Delete</td>
</tr>
{% endif %}
{% endfor %}
Since context allows 'dict', you can pass all of your views through context.

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})

Display a form and the output on the same page

This code will display the form. I can input data, submit the data and the data then displays along with the previous input data from the mySQL DB table where the dat is written, but when the data displays the input form goes away (all expect the submit button that is). I've come across this subject here, but could never quite find the answer that worked for me.
**`models.py`**
class UnitPool(models.Model):
# rack = models.ForeignKey(Rack)
# platform = models.ForeignKey(Group)
location = models.CharField(max_length=10, choices=LAB, default='Choose', blank=False)
rack = models.CharField(max_length=10, choices=RACKS, default='Choose', blank=False)
platform = models.CharField(max_length=10, choices = PLATFORM, default='Choose',blank=False)
unit_HW_Serial = models.CharField(max_length=20, blank=False, null=False)
unit_SW_Serial = models.CharField(max_length=20, blank=False, null=False)
unit_SKU = models.CharField(max_length=20, blank=False, null=False)
comments = models.CharField(max_length=64, blank=True, null=True, default='')
def __unicode__(self): # __unicode__ on Python 2
return '%s %s %s %s %s %s' % (self.rack,
self.platform,
self.unit_HW_Serial,
self.unit_SW_Serial,
self.unit_SKU,
self.comments)
class UUTForm(ModelForm):
class Meta:
model = UnitPool
widgets = {
'comments': TextInput(attrs={'size': 10}),
}
fields = ['location','rack', 'platform','unit_HW_Serial','unit_SW_Serial','unit_SKU','comments']
**forms.html**
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="container">
<div class='row'>
<div class='col-md-2'>
{% if title %}
<h1 class='{% if title_align_center %}text-align-center{% endif %}'>{{ title }}</h1>
{% endif %}
<form method='POST' action=''>{% csrf_token %}
{{ form|crispy }}
<input class='btn btn-primary' type='submit' value='Add Unit' />
</form>
</div>
</div>
</div>
{% if queryset %}
{% if rack != '' %}
<div class="container">
<div class="row">
<div class='col-md-8 col-md-offset-3'>
<h1>Unit Data Entered</h1>
<table class='table'>
<td><b>Item</b></td>
<td><b>Location</b></td>
<td><b>Rack#</b></td>
<td><b>Platform</b></td>
<td><b>HW SN</b></td>
<td><b>SW SN</b></td>
<td><b>SKU</b></td>
<td><b>Comment</b></td>
{% for instance in queryset %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ instance.location }}</td>
<td>{{ instance.rack }}</td>
<td>{{ instance.platform }}</td>
<td>{{ instance.unit_HW_Serial }}</td>
<td>{{ instance.unit_SW_Serial }}</td>
<td>{{ instance.unit_SKU }}</td>
<td>{{ instance.comments }}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
</div>
{% endif %}
{% endif %}
{% endblock %}
**views.py**
from django.conf import settings
from django.shortcuts import render
from .models import UnitPool, UUTForm
def labunits(request):
title = 'Enter Info'
form = UUTForm(request.POST or None)
context = {
"title": title,
"form": form
}
if form.is_valid():
instance = form.save(commit=False)
instance.save()
queryset = UnitPool.objects.all().order_by('rack','platform')
context = {
"queryset": queryset
}
return render(request, "labunits/forms.html", context)
You need to pass the form in the context after calling .is_valid() as #Daniel also mentioned.
Since you are not passing the form in the context again after calling the .is_valid() function, the form does not get displayed again in the template.
So, when you are resetting the context, you need to pass the form also.
def labunits(request):
title = 'Enter Info'
form = UUTForm(request.POST or None)
context = {
"title": title,
"form": form
}
if form.is_valid():
instance = form.save(commit=False)
instance.save()
queryset = UnitPool.objects.all().order_by('rack','platform')
context = {
"queryset": queryset,
"form" : form # pass the form in the context
}
return render(request, "labunits/forms.html", context)

Django Templates - Accessing a M2M attribute and value by name

I am trying to simply access a the values and names of a Many to Many Model in a template by name. Can someone show me what I'm doing wrong.
I have a model called IP. This model can have several attributes. I want to call the "value" of a a particular attribute.
For example:
I have an IP Block named Foo. Foo has an attribute "bar" with a value of "good luck".
How can I refer to the named attribute in a M2M and it's value from a template??
This works but YUCK!!
{% for attr in ip.attributes.all %}
{% ifequal attr.attribute.name 'vendor' %}
<td>{{ attr.value }}</td>
{% endifequal %}
{% endfor %}
Thanks so much!!
I have a models.py which looks similar to this.
models.py
VALID_IP_TYPES = (("hard", "Hard IP"),
("soft", "Soft IP"),
("verif", "Verification IP"))
class AttributeType(models.Model):
name = models.CharField(max_length = 32, primary_key = True)
ip_type = models.CharField(max_length = 16, choices = \
tuple(list(VALID_IP_TYPES) + [("all", "All IP")]))
def __unicode__(self):
return u'%s' % (self.name)
class Attribute(models.Model):
attribute = models.ForeignKey(AttributeType)
value = models.CharField(max_length = 255)
def __unicode__(self):
return u'%s : %s' % (self.attribute, self.value)
class IP(models.Model):
ip_type = models.CharField(max_length = 16, choices = \
tuple(list(VALID_IP_TYPES),
help_text = "Type of IP")
name = models.CharField(max_length = 32, help_text = "Generic Name")
attributes = models.ManyToManyField(Attribute)
def __unicode__(self):
return u'%s' % (self.name)
The relevant views.py
def search(request):
context = RequestContext(request)
if not request.POST:
form = { 'form' : IPSearch() }
return render_to_response('ip_catalog/search.html', form,
context_instance = context)
else:
form = IPSearch(request.POST)
if form.is_valid():
response_dict = {}
cd = form.cleaned_data
ips = ips.filter(**cd)
response_dict.update({'ips':ips})
response_dict.update({'success': True })
return render_to_response('ip_catalog/results.html', response_dict,
context_instance = context)
And finally the template snippet I am struggling with..
{% for ip in ips %}
<tr>
<td>{{ ip.name }}</td>
<td>{{ ip.release_id }}</td>
<td>{{ ip.release_date }}</td>
<!-- THIS WORKS BUT THERE MUST BE A BETTER WAY! -->
{% for attr in ip.attributes.all %}
{% ifequal attr.attribute.name 'vendor' %}
<td>{{ attr.value }}</td>
{% endifequal %}
{% endfor %}
<!-- THIS DOESN'T WORK! -->
<td>{{ ip.attributes.node.value }}</td>
<!-- OR THIS! -->
<td>{{ ip.attribute_id.foundry }}</td>
<!-- OR THIS.. ! -->
<td>{{ ip.attribute.process }}</td>
</tr>
{% endfor %}
Accessing a ManyToManyField in a model results in a manager, which you can use .filter() et alia on. Since most of these require at least one argument, you can't call them in a template. Create a template tag instead.
You can't do this well in templates. This is restricted by the design philosophy of Django.
The only way to do this is writing a custom template tag or helper function in model like get_vendor.
Checkout How do I perform query filtering in django templates