The problem is, when i'm trying to compare two properties which are the same when we check them in shell, but the condition is not complete and i have no idea why. I mean this condition: {% if c.author = member.name %}
views:
cvs = Cv.objects.all()
cv = Cv.objects.filter(author = request.user)
per = Person.objects.all()
gr = Group.objects.filter(members__name=request.user)
for c in cvs:
print c.author
mem = Membership.objects.all()
form = GroupForm()
context = {
'gr': gr,
'per':per,
'mem':mem,
'form': form,
'cvs':cvs,
'cv':cv,
}
return render(request, 'groups.html', context)
models.py:
class Cv(models.Model):
author = models.ForeignKey('auth.User')
name = models.CharField(max_length=25, null = True)
surname = models.CharField(max_length=25, null = True)
address = models.CharField(max_length=100, blank=True)
telephone = models.IntegerField()
birth_date = models.DateField(blank=True, null=True)
email = models.EmailField(max_length=50, null=True)
skills = models.TextField(null=True)
specialization = models.CharField(max_length=30, blank=True, null=True)
interests = models.TextField(blank=True, null=True)
summary = models.TextField(blank=True, null=True)
thumbnail = models.FileField(upload_to=get_upload_file_name, blank=True)
#property
def age(self):
return int((datetime.datetime.now().date() - self.birth_date).days / 365.25 )
def zapisz(self):
self.save()
def __str__(self):
return self.surname
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self): # __unicode__ on Python 2
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
def __str__(self): # __unicode__ on Python 2
return self.name
class Membership(models.Model):
person = models.ForeignKey(Person)
leader = models.BooleanField(default=False)
group = models.ForeignKey(Group)
groups.html:
{% block profile %}
{% for g in gr %}
<div class="jumbotron">
<p><b>GROUP:</b> {{g.name}}</p>
{% for c in cvs %}
{% for member in g.members.all %}
{% if c.author = member.name %}
{{member.name}}
{% endif %}
{% endfor %}
{% endfor %}
</div>
{% endfor %}
{% endblock %}
Thanks for answer!
Firstly, please give your variables descriptive names. "c" and "gr" are impossible to understand.
Secondly, you are not comparing the right things at all. c.author is an instance of User; member is an instance of Person and member.name is a string. Comparing a User instance with a string will always fail.
Finally, this whole thing is horribly inefficient - and probably totally unnecessary. Three nested for loops means a huge number of iterations. If you could explain what the output needs to be, then we can almost certainly come up with a better way of doing it.
To test for equality in a Django template you need to use the equality operator == as follows:
{% if c.author == member.name %}
{{member.name}}
{% endif %}
You should compare c.name with member.name or c.author.first_name with member.name. So both of the variable to be strings.
Related
Noob at coding and need help. I am trying to render the view article by filtering through the model Spots. I have an intermediate table ArticleSpots to link the 2 tables Spots and Articles. In the views article I want to show only the spots that are linked to that specific article. My problem is that Spots.objects.filter(id__in=articleSpots) only shows the first one value and not all of the spots that are linked. What am I doing wrong here?
views.py
def article(request, slug):
articles = get_object_or_404(Articles, slug=slug)
article_id = articles.id
articleSpots = ArticleSpots.objects.filter(article__id=article_id)
spots = Spots.objects.filter(id__in=articleSpots)
context = {"spots": spots, "articles": articles}
template_name = "articletemplate.html"
return render(request, template_name, context)
models.py
class ArticleSpots(models.Model):
article = models.ForeignKey('Articles', models.DO_NOTHING)
spot = models.ForeignKey('Spots', models.DO_NOTHING)
class Meta:
managed = True
db_table = 'article_spots'
verbose_name_plural = 'ArticleSpots'
def __str__(self):
return str(self.article) + ": " + str(self.spot)
class Articles(models.Model):
title = models.CharField(max_length=155)
metatitle = models.CharField(max_length=155)
slug = models.SlugField(unique=True, max_length=155)
summary = models.TextField(blank=True, null=True)
field_created = models.DateTimeField(db_column='_created', blank=True, null=True)
field_updated = models.DateTimeField(db_column='_updated', blank=True, null=True)
cover = models.ImageField(upload_to="cover", blank=True, default='logo-00-06.png')
class Meta:
managed = True
db_table = 'articles'
verbose_name_plural = 'Articles'
def __str__(self):
return str(self.id) + ": " + str(self.title)
class Spots(models.Model):
title = models.CharField(max_length=155)
metatitle = models.CharField(max_length=155)
slug = models.SlugField(unique=True, max_length=155)
author = models.ForeignKey(Authors, models.DO_NOTHING)
field_created = models.DateTimeField(db_column='_created', blank=True, null=True)
field_updated = models.DateTimeField(db_column='_updated', blank=True, null=True)
cover = models.ImageField(upload_to="cover", blank=True, default='logo-00-06.png')
summary = models.TextField(blank=True, null=True)
content1 = models.TextField(blank=True, null=True)
content2 = models.TextField(blank=True, null=True)
class Meta:
managed = True
db_table = 'spots'
verbose_name_plural = 'Spots'
def __str__(self):
return str(self.id) + ": " + str(self.title)
html
<!-- START MAIN -->
<main class="page"></main>
<p>
{{ spots.title }} <br />
{{ spots.content1 }} <br />
{{ articles.title }}
</p>
{% for spots in spots %} {{ spots.title}} {% endfor %}
<!-- END MAIN -->
You are currently retrieving Spots that have the same primary key as the ArticleSpots object, but that does not make much sense: it is possible that this is the case, but even if that happens, the returned Spots does not per se is linked to a relevant ArticleSpots with the given article.
You can retrieve the relevant Spots with:
def article(request, slug):
article = get_object_or_404(Articles, slug=slug)
spots = Spots.objects.filter(articlespots__article=article)
context = {'spots': spots, 'article': article}
return render(request, 'articletemplate.html', context)
I would strongly advise to name you Article object article since it is a single Article, not a collection of Articles. spots on the other hand is a collection of spots.
It makes no sense to render {{ spots.content1 }} and {{ spots.title }}, since spots is a collection of Spots that can contain zero, one or more items.
The template thus should look like:
<p>
{{ article.title }}
</p>
{% for spot in spots %} {{ spot.title}} {% endfor %}
Note: normally a Django model is given a singular name, so Articles instead of Article.
I'm working on a questionnaire and I made a page where user have a list of which questionnaires to fill and which did he filled before but I have stucked.
I like to check if the user filled a form/questionnaire before and if he didn't show him the questionnaire link.
My solutions doesn't work because it checks the db just if the user filled the questionnaire but if he did not (no row for him in the db) it shows a blank cell in my table.
(I don't know if exists query could be a solution but I can't made it work)
main.html
{% for i in oke_vezetoi %}
{% if i.vezetoi_ok == True %}
<td><button class="btn btn-sm btn-outline-info"> Kitöltöm</button>
<td><i class="fas fa-running fa-2x text-dark"></i></td>
{% else %}
<td class="text-success text-uppercase">Kitöltötted</button>
<td><i class="fas fa-check fa-2x text-success"></i></td>
{% endif %}
{% endfor %}
views.py
def main(request):
oke_vezetoi = Vezetoi.objects.filter(user_name=request.user)
oke_stressz = Stressz_teszt.objects.filter(user_name=request.user)
context = {
'oke_vezetoi': oke_vezetoi,
'oke_stressz': oke_stressz,
}
return render(request, 'stressz/main.html', context)
models.py
class Vezetoi(models.Model):
def __str__(self):
return str(self.user_name)
user_name = models.ForeignKey(User, on_delete=models.CASCADE, default=1)
vezetoi_v01 = models.IntegerField( null=True)
vezetoi_v02 = models.IntegerField( null=True)
vezetoi_v03 = models.IntegerField( null=True)
vezetoi_v04 = models.IntegerField( null=True)
vezetoi_v05 = models.IntegerField( null=True)
vezetoi_v06 = models.IntegerField( null=True)
vezetoi_v07 = models.IntegerField( null=True)
vezetoi_v08 = models.IntegerField( null=True)
vezetoi_v09 = models.IntegerField( null=True)
vezetoi_v10 = models.IntegerField( null=True)
vezetoi_v11 = models.IntegerField( null=True)
vezetoi_v12 = models.IntegerField( null=True)
vezetoi_ok = models.BooleanField()
forms.py
class VezetoiForm(forms.ModelForm):
class Meta:
model = Vezetoi
fields = ['vezetoi_v01', 'vezetoi_v02', 'vezetoi_v03', 'vezetoi_v04', 'vezetoi_v05', 'vezetoi_v06', 'vezetoi_v07', 'vezetoi_v08', 'vezetoi_v09', 'vezetoi_v10', 'vezetoi_v11', 'vezetoi_v12', 'vezetoi_ok' ]
I'm not sure if I'm interpreting your question correctly, but it seems like there are a few things that you could optimise.
It sounds like there should only be one entry per user in the Vezetoi model.
If this is true, you should enforce ForeignKey(unique=True), and you don't need a for loop and you can use Vezetoi.objects.get() in your views.py
If this is not true, and there are multiple Vezetoi integers per user, you might want to have one Vezetoi object for each integer.
If the user hasn't submitted a questionnaire, then the Vezetoi model object will not exist.
Since the object doesn't exist, it won't appear in the oke_vezetoi queryset, so the object attribute i.vezetoi_ok will not be found in your loop (this is why your table row is blank).
Assuming the field vezetoi_ok is only intended to check for the existence of the questionnaire, it can only ever be True, so you can remove it from the model definition.
If these are not true, I'll need to amend the answer and I'll ask you to provide more information about what these models are tracking, the content of the Stressz_teszt model and urls.py as well as how the VezetoiForm is implemented.
So in the case that I've described, I'd do it like this with a class based view and the get_context_data method.
models.py
class Vezetoi(models.Model):
def __str__(self):
return str(self.user_name)
user_name = models.ForeignKey(User, on_delete=models.CASCADE, unique=True)
vezetoi_v01 = models.IntegerField(null=True)
...
# vezetoi_ok = models.BooleanField()
forms.py
class VezetoiForm(forms.ModelForm):
class Meta:
model = Vezetoi
fields = '__all__'
views.py
class MainView(TemplateView):
template_name = 'main.html'
def get_context_data(self, **kwargs):
context = super().get_context_data()
context['oke_vezetoi'] = Vezetoi.objects.get(user_name=request.user)
context['oke_stressz'] = Stressz_teszt.objects.get(user_name=request.user)
return context
main.html
{% extends 'base.html' %}
{% if oke_vezetoi %}
{# do not display link #}
{% else %}
{# display link #}
{% endif %}
When I enter my user profile page, I want it to see the total number of orders until today. i tried aggregate and annonate but it's not work. I hope so i use filter method but i don't know how to do it.
Orders count = adet in model
I added ""if siparis.bayi_id == user.id"" so that the user entering can take action on his orders.
Temp Html
{% for siparis in siparis %}
{% if siparis.bayi_id == user.id %}
<strong>{{ a }}</strong><br><small>Siparişler Toplamı</small>
{% endif %}
{% endfor %}
Model Siparis means order
class Siparis(models.Model):
bayi = models.ForeignKey('auth.User', verbose_name='bayi', on_delete=models.CASCADE, related_name='bayi',limit_choices_to={'groups__name': "BayiGrubu"})
urun = models.ForeignKey(Urun, on_delete=models.CASCADE)
adet = models.IntegerField()
tarih = models.DateTimeField()
status = models.BooleanField()
#property
def miktar(self):
return (self.adet * self.urun.fiyat)
#property
def fiyat(self):
return self.urun.fiyat
class Meta:
verbose_name = 'Bayi Sipariş'
verbose_name_plural = 'Bayi Siparişleri'
views
def bayi_bayidetay(request):
siparis = Siparis.objects.all()
urunler = Urun.objects.all()
bayiler = bayi_bilgi.objects.all()
a = Siparis.objects.aggregate(Sum("adet"))
return render(request,'bayi/bayi_detay.html',{'bayiler':bayiler,'siparis':siparis,'urunler':urunler, 'a': a})
Thank you
You can try add filter after a, like this:
a = Siparis.objects.filter(bayi=request.user).aggregate(Sum("adet"))
I have a following models.py for my Django blog, I made a following views.py to pass the value of the slug for my URL parameter.
However I am struggling to create a model in views to get other data(person & description) from Category class.
I have tried some patterns by myself but can not pass them to HTML. (always Error or not showing)
Can you please give me some idea of how to solve this.
models.py
class Category(models.Model):
person = models.CharField(max_length=20)
description = models.TextField()
slug = models.SlugField()
def __str__(self):
return self.person
views.py
def blog_category(request, category):
posts = Post.objects.filter(categories__slug__contains=category).order_by("-created_on").distinct()
context = {"category": category, "posts": posts}
return render(request, "blog_category.html", context)
HTML(Localhost:8000/slug)
{{ person }}
{{ description }}
this is full code of my models.py
class Category(models.Model):
person = models.CharField(max_length=20)
description = models.TextField()
slug = models.SlugField()
def __str__(self):
return self.person
class Recommender(models.Model):
recommender_name = models.CharField(max_length=20)
slug = models.SlugField()
def __str__(self):
return self.recommender_name
class Post(models.Model):
book_title = models.CharField(max_length=255)
author = models.CharField(max_length=255)
book_link = models.CharField(max_length=255)
recommenders = models.ForeignKey("Recommender", on_delete=models.CASCADE,)
source = models.TextField()
source_link = models.CharField(max_length=255)
created_on = models.DateTimeField(auto_now_add=True)
last_modified = models.DateTimeField(auto_now=True)
categories = models.ManyToManyField("Category", related_name="posts")
slug = models.SlugField()
def __str__(self):
return self.book_title
posts = Post.objects.filter(categories__slug__contains=category).order_by("-created_on").distinct()
Is going to return a queryset. It can have more than one instance of the model class (since you are using filter). In your context you are sending this queryset as posts to your templates.
So in your HTML you can use something like this. You need to use a for loop since there can be more than one item in posts.
{% for post in posts %}
{% for category in post.categories.all %}
{{ category.person }}
{{ category.description }}
{% endfor %}
{% endfor %}
I would look at this example.
Namely, if you render the template like it is shown in the example, you should be able to do
{{ category.person }} {{ category.description }}
My models:
class customer(models.Model):
cstid = models.AutoField(primary_key=True, unique=True)
insurance_number = models.CharField(max_length=100, blank=True, null=True)
name = models.CharField(max_length=35)
ageyrs = models.IntegerField(blank=True)
class Admission(models.Model):
id = models.AutoField(primary_key=True, unique=True)
clinic = models.ForeignKey(Clinic, on_delete=models.CASCADE)
customer = models.ForeignKey(customer, on_delete=models.CASCADE)
diagnosis = models.CharField(max_length=2000, default='', blank=True)
date_admission = models.DateTimeField(default=timezone.now)
ward = models.ForeignKey(Ward, on_delete=models.CASCADE)
bed = models.ForeignKey(Bed, on_delete=models.CASCADE)
discharged = models.BooleanField(default=False)
ip_number = models.IntegerField(blank=True)
ip_prefix = models.CharField(max_length=20, default='', blank=True)
My objective: Set a variable to a query filter, adding a property, 'is_admitted' to the queryset, so that I can pass this query set to the template and use the property while displaying data.
Code:
def is_admitted(cust):
admission = Admission.objects.filter(customer=cust, discharged=False)
admission_results = len(admission)
if admission_results > 0:
return True
return False
my_q = or_q_if_truthfull(
cstid=HospitalID,
name__lower__contains=name.lower() if name else None,
ageyrs=ageyrs if ageyrs.isdigit() else None,
agemnths=agemnths if agemnths.isdigit() else None,
mobile__contains=mobile if mobile else None,
alternate__contains=alternate if alternate else None,
email__lower__contains=email.lower() if email else None,
address__lower__contains=address.lower() if address else None,
city__lower__contains=city.lower() if city else None
)
ORSearchResult = customer.objects.filter(my_q, linkedclinic=clinicobj)
cust_set = []
cust_admission_status = []
for cust in ORSearchResult:
cust_set.append(cust)
cust_admission_status.append(is_admitted(cust))
print(f"Customer name: {cust.name} Admission status: {is_admitted(cust)}")
cust_templ_set = zip(cust_set, cust_admission_status)
And in template, I will do:
{% for cust, status in cust_templ_set %}
{{ cust.name }} {{ status }}
{% endfor %}
I want to understand how I can convert my above code by generating an aggregate over the queryset, so that I can use a property of the query, and change the template code to the following, and avoid the loop in the view, and the zip. So that the template code becomes:
{% for cust in customers %}
{{ cust.name }} {{ cust.is_admitted }}
{% endfor %}
I am not sure whether I am making complete sense, and can explain further.
I'm not sure I understood you right, perhaps you might want this:
cust = customer.objects.filter(my_q, linkedclinic=clinicobj)
is_admitted_sub_q = Admission.objects.filter(customer=OuterRef('pk'), discharged=False)
cust_templ_set = cust.annotate(is_admitted=Exists(is_admitted_sub_q), )
this will return a list of customers with additional field is_admitted which will be True if there exists at least one linked (to this customer) record in Admission.
OuterRef, Exists
One option could be to use conditional-expressions together with annotate(). It could look like this:
from django.db import models
qs = Customer.objects.filter(...) # your filter conditions go here
# now add a field to the resulting queryset
qs = qs.annotate(
active_admissions=models.Count(
models.Case(
models.When(admission__discharged=False, then=1),
output_field=models.IntegerField())))
Now each object in the queryset will have an additional attribute called active_admissions which will contain the number of active admissions.
This could be used in the template like this:
{% for cust in qs %}
{{ cust.name }} {{ cust.active_admissions }}
{% endfor %}
Maybe you need to modify the subquery to fit your specific needs. Does that help?