Desired outcome: When I render a Poller and its associated comments
I would like to also render the Vote a user selected for the Poller along with his comment (Note: A user can only comment if he voted on that poller).
Side note: A user can make one vote to a Poller and post one comment to a Poller. He can only comment if he voted beforehand.
# Models
class Poller(models.Model):
poller_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
created_on = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(Account, on_delete=models.CASCADE)
poller_text = models.CharField(max_length=333)
poller_choice_one = models.CharField(max_length=20)
poller_choice_two = models.CharField(max_length=20)
class Vote(models.Model):
poller = models.ForeignKey(Poller, on_delete=models.CASCADE, related_name='vote')
user = models.ForeignKey(Account, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now_add=True)
poller_choice_one_vote = models.BooleanField(default=False)
poller_choice_two_vote = models.BooleanField(default=False)
def __str__(self):
return f'Vote by {self.user}'
class Comment(models.Model):
poller = models.ForeignKey(Poller, on_delete=models.CASCADE, related_name='PollerComment')
user = models.ForeignKey(Account, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now_add=True)
comment = models.TextField(max_length=350)
flag_count = models.IntegerField(default=0)
upvote_count = models.IntegerField(default=0)
downvote_count = models.IntegerField(default=0)
# View
#require_GET
def render_single_poller(request, poller_id):
# Retrieve comments associated to the Poller
comments_qs = PollerComment.objects.filter(poller_id=poller_id)
context = {
'comments_qs': comments_qs,
}
return render(request, 'pollboard/single_poller.html', context)
I tried to do it via a template filter like so:
# pollboard_tags.py
#register.filter(name='get_vote')
def get_voted(self):
self.vote_made = 'Test'
print(self.vote.poller_choice_one_vote)
if self.vote.poller_choice_one_vote:
self.vote_made = 'One'
else:
self.vote_made = 'Two'
return self.vote_made
# template
<div class="commentors-poller-choice">{{ comment|get_vote }}</div>
throws
RelatedObjectDoesNotExist at /poller/68c725eb-277e-4b5b-a61b-b4a02bf5e854/
PollerComment has no vote.
I fear that I'm already overcomplicating things here. I hope there is a more straightforward solution to this like idk expanding the comments queryset by the required information for rendering?
If a user can vote on a poller only once, you can filter with:
#register.filter(name='get_vote')
def get_voted(self):
vote = Vote.objects.get(poller=self.poller, user=self.user)
return 'One' if vote.poller_choice_one_vote else 'Two'
Related
I have a Blog Post Model and I have defined a function to calculate the no of likes.
The Model is as follows ->
class Post(models.Model):
user = models.ForeignKey(User, on_delete=models.PROTECT)
title = models.CharField(max_length=255)
description = models.CharField(max_length=1000,null=True)
Tags = models.CharField(max_length = 255,null=True,blank=True)
Created_date = models.DateTimeField(auto_now_add=True)
Updated_date = models.DateTimeField(auto_now=True)
category = models.ForeignKey(Category, on_delete=models.PROTECT)
Likes = models.ManyToManyField(to=User, related_name='Post_likes')
def __str__(self):
return self.title
def likesCount(self):
return self.Likes.count()
Now I am querying the Post Model from the DB to get all the Posts as follows ->
posts = Post.objects.select_related().prefetch_related('images_set','comments_post').annotate(Count('comments_post')).all()
Here when I loop over the posts I can call the likesCount function and it gives me the correct result as well but I want to return the No of likes to the template.
How can I do that?
in your template, try this:
{{ post.likes_set.count }}
and please make the field names lowercase, they are not Classes
I'm lost in django formsets. I tried many variations and none works as I need. Maybe it is a little bit confusing what my models are :)
What do I want to do? I need to create a view that displays all AssessParameters related to KapTSI and my problem is editing fields [assessment_requirements, value, finding]. Maximum what is was able to solve by using formset was editing those fields but how to display only the assessment_requirements those are related to edited parameter and to all parameters? And the bonus if there is a way with using CBV?
Models.py
class AssessParameter(models.Model):
application = models.ForeignKey(Application, on_delete=models.CASCADE, blank=True, null=True)
parameter = models.ForeignKey(Parameter, on_delete=models.DO_NOTHING)
requirement = models.TextField(blank=True)
assessment_requirements = models.ManyToManyField(Requirement, related_name="assessments", blank=True)
value = models.TextField(blank=True, null=True)
finding = models.ForeignKey(Finding, on_delete=models.DO_NOTHING)
note = models.TextField(blank=True)
documents = models.CharField(max_length=1, blank=True)
class KapTsi(models.Model):
title = models.CharField(max_length=150)
number = models.CharField(max_length=20)
tsi = models.ManyToManyField(Standard, related_name="tsis")
def __str__(self):
return f"{self.number} | {self.title}"
class ParameterGroup(models.Model):
title = models.CharField(max_length=150)
kap_tsi = models.ForeignKey(KapTsi, models.DO_NOTHING)
def __str__(self):
return f"{self.kap_tsi} {self.title}"
class Parameter(models.Model):
parameter_group = models.ForeignKey(ParameterGroup, on_delete=models.DO_NOTHING)
title = models.CharField(max_length=255)
standards = models.ManyToManyField(Standard, through="Specification", blank=True)
description = models.TextField(blank=True)
active = models.BooleanField(default=True)
def __str__(self):
return self.title
foms.py
class AssessParameterForm(forms.ModelForm):
class Meta:
model = AssessParameter
exclude = ['parameter', 'requirement', 'application']
AssessmentParameterFormSet = modelformset_factory(AssessParameter, form=AssessParameterForm, extra=0)
last try: views.py
def assessment_group(request, pk, slug, group):
application = Application.objects.get(id=pk)
group = ParameterGroup.objects.get(id=group)
assessments = AssessParameter.objects.filter(application=application).filter(parameter__parameter_group=group)
parameter = Requirement.objects.filter(parameter__parameter_group=group)
formset = AssessmentParameterFormSet(instance=assessments)
# for form in formset:
# form.fields['assessment_requirements'].queryset = parameter
context = {
'application': application,
'formset': formset,
}
return render(request, 'assessment/assessment-group.html', context)
this is my model
class ArtWork(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT)
title = models.CharField(max_length=40)
desc = models.TextField(max_length=100)
image = models.ImageField(upload_to=get_post_filename, null=True, blank=True)
category = models.ForeignKey('Category', null=True, blank=True, on_delete=models.SET_NULL)
album = models.OneToOneField('PostImages', related_name='model',
blank=True, null=True, on_delete=models.PROTECT)
# identifier
private_unique_id = models.CharField(max_length=200, blank=True, unique=True, default=uuid.uuid4)
public_unique_id = models.CharField(max_length=200, blank=True, unique=True, default=uuid.uuid4)
def __str__(self):
return self.title
def get_ratings(self):
like = Vote.objects.filter(artwork=self, like=True, nope=False).count()
nope = Vote.objects.filter(artwork=self, nope=True, like=False).count()
return like, nope
I'd like to get the ArtWork model function "get_ratings" in views with "values" filter
in views.py
if request.is_ajax():
posts = ArtWork.objects.filter(active=True)
data = serializers.serialize("json", posts, fields=('image', 'title', 'desc','get_ratings'))
return JsonResponse(data, content_type='application/json', safe=False)
posts = ArtWork.objects.filter(active=True).only('get_ratings').values('image', 'title', 'desc',)
return render(request, 'Home.html', {'posts': posts[:3]})
what I want to do is basically return for ajax request in views a list of objects including the results of the function
any help is appreciated, thanks in advance.
If you are trying to create new Artwork object, I'd do it like this:
class ArtWork(models.Model):
title = models.CharField(max_length=40)
...
#classmethod
def get_ratings(cls, field1):
like = Vote.objects.filter(artwork=self, like=True, nope=False).count()
nope = Vote.objects.filter(artwork=self, nope=True, like=False).count()
return like, nope
then, import it in your view:
from <app_name>.models import ArtWork
.....
ArtWork.get_rating()
This works for me, hope this help you too.
You should use custom managers to apply methods to QuerySets.
class ArtWorkManager(models.Manager):
def get_ratings(self):
like = Vote.objects.filter(artwork=self, like=True, nope=False).count()
nope = Vote.objects.filter(artwork=self, nope=True, like=False).count()
return like, nope
also, you should add the below line to Artwork model:
objects = ArtWorkManager()
Check this link for custom managers.
I'm using django-models-utils in order to obtain all the children of a class. I've succeeded in that but now I don't seem to be able to obtain a view with just the parent class now.
This is the main class, the other classes are for reviews:
class Post(models.Model):
author = models.ForeignKey(User, null=True, blank=True)
title = models.CharField(max_length=200)
slug = models.SlugField(max_length=200, unique=True, blank=True)
text = models.TextField()
notable = models.BooleanField(default=False)
created = models.DateTimeField(editable=False, auto_now_add=True)
published = models.DateTimeField(null=True, blank=True)
modified = models.DateTimeField(editable=False, auto_now=True)
tags = models.ManyToManyField(Tag, blank=True)
objects = InheritanceManager()
This is the view for all posts (including the children), which is working:
def all_posts(request):
posts = Post.objects.order_by('published').filter(published__lte=timezone.now()).select_subclasses()
return render(request, 'blog/post_list.html', {'posts': posts})
This is the view for just the posts (which are not reviews, not children), but this isn't working as I'm getting all posts:
class RamblingList(ListView):
context_object_name = 'ramblings'
queryset = Post.objects.filter(published__lte=timezone.now()).order_by('published')
template_name = 'blog/rambling_list.html'
Can anyone tell me please what I'm doing wrong?
The InheritanceManager is not supposed to do that. If you call any filter without calling select_subclasses(), it will return all objects without the subclass cast.
It is clear in the documentation: http://django-model-utils.readthedocs.org/en/latest/managers.html#inheritancemanager
But when you iterate over nearby_places, you’ll get only Place instances back, even for objects that are “really” Restaurant or Bar
You could do something like this to achieve the desired effect:
queryset = Post.objects.filter(
published__lte=timezone.now()
).order_by('published').select_subclasses()
queryset = [x for x in queryset if type(x) == Post]
I have a bunch of message records that I would like to assign to different taskboxes.
#models.py
class TaskBox(models.Model):
name = models.CharField(max_length=64, blank=False)
def __str__(self):
return u'%s' % (self.name)
class Admin:
pass
class InboxEntry(models.Model):
job_number = models.CharField(max_length=14, unique=False, blank=False, null=False)
job_name = models.CharField(max_length=64, unique=False, blank=False, null=False)
request = models.CharField(max_length=64, choices=PRINT_CHOICES, blank=True, null=True)
date_due = models.DateTimeField(("Due"),auto_now=False)
note = models.TextField(max_length=1000, unique=False, blank=True, null=True)
assigned_by = models.ForeignKey(UserProfile, blank=False, null=False)
box = models.ForeignKey(TaskBox)
assigned_to = models.ManyToManyField(UserProfile, related_name='name', blank=True)
status = models.CharField(max_length=30, choices=STATUS_CHOICES, default="Awaiting Action")
def __str__(self):
return u'%s %s' % (self.job_number, self.job_name)
class Admin:
pass
class Meta:
ordering = ['status']
The idea is for the template to have some generic tags like {{ for taskbox in taskboxes }} to create a separate div for each taskbox that will hold a table for that box's records. My problem is constructing the view function...
#views.py
def display_prdInboxEntry(request, id):
if request.method == 'POST':
form = PrdInboxForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('taskmanager/display/'+ id +'/')
else:
form = PrdInboxForm(request.POST)
return HttpResponseRedirect('taskmanager/display/'+ id +'/')
else:
form = PrdInboxForm()
user = request.user
**taskboxes = TaskBox.objects.all()
records_1 = InboxEntry.objects.filter(taskboxes[id]=1)
records_2 = InboxEntry.objects.filter(taskboxes[id]=2)
records_3 = InboxEntry.objects.filter(taskboxes[id]=3)
..... **
return render_to_response('taskmanager/taskmanager_view.html', {'form': form, 'taskboxes': taskboxes, 'records_1' : records_1, 'records_2' : records_2, 'records_3' : records_3, 'user': user}, context_instance=RequestContext(request))
The InboxEntry model has a field called "box" that's just a reference to the TaskBox model. I need a way to map say... TaskBox id 1 with all of the InboxEntry objects with "box = 1" so that I can populate the templates appropriately. Can I construct the function to accommodate this, or am I going about it the wrong way entirely?
It sounds like you're looking for the automatically-generated attribute for reverse lookups. You can get a QuerySet of all InboxEntries associated with a TaskBox like this:
TaskBox.objects.filter(id=1).inboxentry_set.all()
See the documentation on related objects.