Django boolean filter elements in template - python

I have a Django template where I do queries like this:
{% for post in user.post_auctions_set.all %}
The point for me now is that I only want to display post elements that don't have the Boolean prime = True.
I came across template tags but never really worked with them.
Can smb. give me a hint on how I could setup a filter like?
views.py
def pae(request, pk=None):
if pk:
user = get_user_model().objects.get(pk=pk)
else:
user = request.user
args = {'user': user}
return render(request, 'App/pae.html', args)
models.py
class Post_Auctions(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
author = models.ForeignKey(User, on_delete=models.CASCADE)
...
prime = models.BooleanField(verbose_name="Prime", default=False, editable=True)
Thanks in advance

You could use the if clause form the built-in django template tag set:
{% for post in user.post_auctions_set.all %}
{% if post.prime %}
...
Note: this might not be the best solution, but the only I could think of right know, as I am not too familiar with Django right now. At least, what I've read of somewhere somewhen, is to avoid such template logic whenever possible.

Related

Comparing two django variable in a django if block

I am having a tough time with following code.
{% if object.author == user.username %}
That code is not working neither giving error.
So I have articles app inside my django project. I want to make sure that if a user goes to their own post, then only they should be able to see delete and edit links (I will be placing them inside if block).
The Article model is as follows:
class Article(models.Model):
title = models.CharField(max_length=255)
body = models.TextField()
date = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('article_detail', args=[str(self.id)])
Here
{{user.username}}
{{object.author}}
both are valid django variables.
{{user.username}}
specifies username of current logged in user
{{object.author}}
specifies author of that particular post.
Please help me out to implement with comparison logic of both variables. I am using python 3.6, django 2.1 and django template language.
Your question would be easier to answer if you posted your models (and formatted your text correctly).
I presume that object.author is actually a ForeignKey to the User model. Therefore, you should compare directly with the user, not with the username attribute of the user:
{% if object.author == user %}

Django Template syntax/tag to filter and check if a related data exists in that model

I'm working on a project with python-3.6.4 and django-2.0.2. For simplicity, I'm explaining the situation in short. Suppose, there are three apps:- "problems", "solve_activities" and "profiles" having three models(mentioned below) inside them. I have a "DetailView" page for each problem. I want to show if the logged in user has solved the problem or not.
The django template tag that I wanted to do use was something like this:
{% if user.is_authenticated and problem.solved.all.filter(solver={{user.username}}) %}
Here are the above mentioned files:
"problems/models.py":
class Problem(models.Model):
name = models.CharField(max_length=20)
slug = models.SlugField(allow_unicode=True, max_length=100, unique=True)
def __str__(self):
return self.name
def get_absoulte_url(self):
return reverse('problems')
return reverse('problems:problem_detail', kwargs={'slug':self.slug})
I've used the urlpatterns in 'problems/urls.py' as "path('/', views.ProblemDetail.as_view(), name='problem_detail')".
"profiles/models.py"(inherited from auth.models.User):
class User(auth.models.User, auth.models.PermissionsMixin):
def __str__(self):
return self.username
"solve_activities/models.py":
class Solve(models.Model):
problem = models.ForeignKey(Problem, on_delete=models.CASCADE, related_name="solved")
solver = models.ForeignKey(User, on_delete=models.CASCADE, related_name="solved")
I'm only creating this object when the user solves a problem.
Now, my ProblemDetail view on problems/views.py:
class ProblemDetail(generic.DetailView):
model = Problem
template_name = 'problems/problem_detail.html'
And the "problems/problem_detail.html" file where I'm facing the complexity basically:
<h1>{{problem}}</h1>
<h4>Solve Status: {% if user.is_authenticated and problem.solved.all.filter(solver={{user.username}}) %}Solved{% else %}Unsolved{% endif %}</h4>
Again,
{% if user.is_authenticated and problem.solved.all.filter(solver={{user.username}}) %}
is what I want to do, but I couldn't find any useful resource on how to do it correctly.
The error it's raising is:
TemplateSyntaxError at /problems/timus-1000/
Could not parse the remainder: '(solver={{user}})' from 'problem.solved.all.filter(solver={{user}})'
Dont do logic in templates, thats what views are for. Add it to the context and use it in the template.
class ProblemDetail(generic.DetailView):
...
def get_context_data(self, *args, **kwargs):
context = super(ProblemDetail, self).get_context_data()
context["solve_status"] = self.request.user.is_authenticated and context["object"].solved.filter(solver=self.request.user).exists()
return context
then in the template use
{% if solve_status %} ..

Passing objects primary key from its view to its ManyToMany-relationship object view

I don't know if the title is clear. It's quite difficult for me to explain it in simple way because the problem is not that simple and I'm not a very good English speaker. Every suggestion for improving a title are welcome.
So, let's go to the actual problem... In my application people can join different groups. Currently, I'm creating invitation system for this purpose, so user can send an invitation to another user. In a group view, I have a list of users which are not connected with this group, which allowing group members to invite those people. So, when I'm going to the group view, I am passing it's Primary Key. To create database cell about the invitation I need a group's PK and users PK as well (I want to do it using another view, but I'm not sure it's the best solution).
My question is: How can I pass those two PKs to the new view where I will create group-user relation cell in a database?
models.py:
class Group(models.Model):
name = models.CharField(max_length=500)
members = models.ManyToManyField(User, blank=True, related_name="member")
invitations = models.ManyToManyField(User, blank=True, related_name="invitations")
views.py:
def not_yet_members_list_view(request, pk):
group = Group.objects.get(pk=pk)
not_yet_members = User.objects.all() #doesn't matter
args = {'group': group, 'not_yet_members': not_yet_members}
return render(request, 'groups/show_members.html', args)
# Here is my problem (this code is a simplified version of what I want to achieve)
def invite_user_view(request, group_pk, user_pk):
invite_user(group_pk, user_pk)
return render(request, 'groups/show_members.html')
urls.py:
url(r'^not_yet_members_list/(?P<pk>\d+)/$', views.not_yet_members_list, name='not_yet_members_list'),
template.html:
{% for user in not_yet_members %}
<!-- ??? -->{{ user }}Invite
{% endfor %}
in the view from where you need to pass the group and user
request.session['group_pk'] = group_pk
request.session['user_pk']= user_pk
in the view where you need to access the data
group_pk = request.session['group_pk']
user_pk = request.session['user_pk']
then
invite_user(group_pk, user_pk)
after successful sending invitation
del request.session['group_pk']
del request.session['user_pk']
request.session.modified = True

Django Apply Model Foreign Key Default Value to Existing Record

Thank you very much for taking your time.
Previously, I posted this question, How to Get Unread Posts for Users.
The problem was: I cannot filter out which article one user has not read while this article has already been read by another user.
I figured out why I cannot do that---- because I have data that I wrote into the database without using Django although I set the reading default for each post to False---- there is simply no record.
Then, I manually set one article to unread to a user in the Admin, everything works, because now in the database there is one record stating that this certain article has not been read by this user.
The problem now is:
How do I set "unread" for every existing article that I have in the database for all existing users?
And how can articles stay unread for every new user unless the new user actually read it?
For your convenience, I copied the codes to here.
My model:
class Posts(models.Model):
title = models.CharField(max_length=255)
content_url = models.URLField(unique=True)
content = models.CharField(max_length=255)
post_date = models.DateField(default="2999-12-12")
Another
class readstatus(models.Model):
reading_status = models.BooleanField(default=False)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
article = models.ForeignKey(Posts, on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True)
My View:
class DailyReading(ListView):
template_name = 'reading.html'
context_object_name = "data"
paginate_by = 20
def get_queryset(self):
if self.kwargs['status'] == "read":
queryset = piaoyou.objects.filter(readstatus__reading_status=True,readstatus__user=self.request.user)
return queryset
else:
queryset= Posts.objects.filter(readstatus__reading_status=False,readstatus__user=self.request.user)
return queryset
My Template:
{% for info in data %}
<quoteblock>
<ul>
<li><a href="{{ info.get_absolute_url }}">{{ info.title }}
<footnote></footnote>
</a>{{ info.post_date }}</li>
<footnote>{{ info.get_abstract_content }}</footnote>
</ul>
</quoteblock>
{% endfor %}
OMG, I just figured out how to do this.
For an article that has been read by the requesting user, we can just pass queryset = Post.objects.filter(readstatus__reading_status=True, readstatus__user=self.request.user)
For an article that has not been read by the requesting user yet, we can pass Posts.objects.all() into the template.
Then in the template:
We need {% if instance.readstatus_set.all %} this line to make things work. Assume there is no data about whether this requesting user has read the article, the instance should not have readstatus_set.all, which means the user has not read the article yet. Once checking this if condition, we can carry out to check other conditions in the loop.

Django Model Form: show query form and handle post request for OneToMany fields

I am a newbie to Django and could not find similar questions after searching on google/SO.
I've a model named Questions, which has multiple(2-4) choices and defined as below:
class Question(models.Model):
name = models.CharField(max_length=128)
class Choice(models.Model):
name = models.CharField(max_length=256)
is_correct = models.BooleanField(default=False)
question = models.ForeignKey(Question, on_delete=models.CASCADE)
Of the multiple choices only one is correct.
What I want to do: In just one page, user could submit a question together with multiple choices, here is a draft of UI:
My first question: I've defined ModelForm but don't know how to add "choices" field to QuestionForm:
class QuestionForm(ModelForm):
name = forms.CharField(max_length=128)
description = forms.CharField(max_length=256)
class Meta:
model = Question
fields = ['name', 'description']
class ChoiceForm(ModelForm):
name = forms.CharField(max_length=256)
is_correct = forms.BooleanField()
class Meta:
model = Choice
fields = ['name', 'is_correct']
Is it possible to use ModelForm the render the above HTML page besides writing it manually?
My second question: If use clicks "Submit" button, I use AJAX to send json data to backend server, here is an example of form data:
name:question1
choices[][name]:choice1
choices[][is_correct]:1
choices[][name]:choice2
choices[][is_correct]:0
And this is my code handling the request:
form = QuestionForm(request.POST)
if form.is_valid():
question = form.save()
How to parse choices from the request?
How could I parse data of multiple choices part from the POST request?
Again, I'm a newbie to Django and any answers/suggestions is highly appreciated.
To create forms for models which have a OneToMany relation I would recommend you to use Django's inline formsets: https://docs.djangoproject.com/en/1.8/topics/forms/modelforms/#inline-formsets
It's a really simple and elegant way to create forms for related models.
To parse the choices, the user entered you could just override the clean method of your form. In this the user content is usually checked and prepared for storing it to the database. https://docs.djangoproject.com/en/1.8/ref/forms/validation/#form-field-default-cleaning
So cleaning could look like this:
class QuestionForm(ModelForm):
...
def clean(self):
cleaned_data = super(QuestionForm, self).clean()
if cleaned_data['choice_name'].startswith('Something'):
raise forms.ValidationError(
"Choice names cannot start with 'Something'!"
)
You models seems to be correct, in order to be able to add mutiple choices in your template you need a formset. In addition you can put a formset and a form inside the same html form in a template and have them be validated individually. Each one only cares about the POST data relevant to them. Something like:
template.html
<form method="post" action="">
{% csrf_token %}
{{ choices_formset.management_form }} <!-- used by django to manage formsets -->
{{ question_form.as_p }}
{% for form in choices_formset %}
{{ form.as_p }}
{% endfor %}
<button type='submit'>Submit</button>
</form>
views.py
from django.db import IntegrityError, transaction
from django.shortcuts import redirect
from django.forms.formsets import formset_factory
from django.core.urlresolvers import reverse
def new_question(request):
ChoicesFormset = formset_factory(ChoicesForm)
if request.method == 'POST':
question_form = QuestionForm(request.POST)
choices_formset = ChoicesFormset(request.POST)
if question_form.is_valid():
question = Question(**question_form.cleaned_data)
if choices_formset.is_valid():
question.save()
new_choice_list = list()
append_choice = new_choice_list.append
for form in choices_formset:
form.cleaned_data.update({'question': question})
append_choice(Choice(**form.cleaned_data))
try:
with transaction.atomic():
Choice.objects.bulk_create(new_choice_list)
except IntegrityError as e:
raise IntegrityError
return redirect(reverse('question-detail-view', kwargs={'id': question.id}))
def question_detail(request, id):
question_list = Question.objects.get(id=id)
return render(request, 'question_detail.html', {'question_list': question_list})
urls.py
url(r'^question/$', new_question, name='new-question-view'),
url(r'^question/(?P<id>\d+)/$', question_detail, name='question-detail-view'),
If you want to use rather Ajax submission rather than django form sumbission check this tutoriel.

Categories

Resources