Please I need help, I dont know where the problem is coming from, please see the code below
#api_view(['GET'])
#permission_classes([IsAuthenticated])
def post_feed_view(request, *args, **kwargs):
user = request.user
profiles = user.follow_user.all()
followed_users_id = []
if profiles.exists():
followed_users_id = [x.user.id for x in profiles]
followed_users_id.append(user.id)
queryset = Post.objects.filter(user__id__in=followed_users_id).order_by("-date_posted")
serializer = PostSerializer(queryset, many=True)
return Response(serializer.data, status=200)
I keep getting this error: Cannot resolve keyword 'user' into field. Choices are: author, author_id,
although, in my models, I dont have "User" what I have is "Author".
But I dont know where exactly to put in author. I think my problem is that i dont fully understand "request.user".
Please help!.
===========
This is the Profile and Follow models:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.CharField(max_length=245, null=True)
image = models.ImageField(default='default.png', upload_to='profile_pics')
interests = models.ManyToManyField(Category, related_name='interests_user')
stripe_customer_id = models.CharField(max_length=50, blank=True, null=True)
one_click_purchasing = models.BooleanField(default=False)
is_vendor = models.BooleanField(default=False)
# vendor
bvn = models.CharField(max_length=10, null=True, blank=True)
description = models.TextField(null=True, blank=True)
address = models.CharField(max_length=200, null=True, blank=True)
company = models.CharField(max_length=100, null=True, blank=True)
# follow_user = models.ManyToManyField('users.Follow')
def __str__(self):
return f'{self.user.username} Profile'
#property
def followers(self):
return Follow.objects.filter(follow_user=self.user).count()
#property
def following(self):
return Follow.objects.filter(user=self.user).count()
def save(self, force_insert=False, force_update=False, using=None,
update_fields=None):
super().save()
img = Image.open(self.image.path)
if img.height > 300 or img.width > 300:
output_size = (300, 300)
img.thumbnail(output_size)
img.save(self.image.path)
class Follow(models.Model):
user = models.ForeignKey(User, related_name='user', on_delete=models.CASCADE)
follow_user = models.ForeignKey(User, related_name='follow_user', on_delete=models.CASCADE)
date = models.DateTimeField(auto_now_add=True)
old_instance = models.ForeignKey('Follow', blank=True, null=True, on_delete=models.CASCADE, editable=False)
def save(self, *args, **kwargs):
if self.pk is not None:
self.old_instance = Follow.objects.get(pk=self.pk)
super().save(*args,**kwargs)
def __str__(self):
return f"For: {self.user} // id: {self.id}"
class FollowerRelation(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
profile = models.ForeignKey("Profile", on_delete=models.CASCADE)
timestamp = models.DateTimeField(auto_now_add=True)
Your Post model apparently has no user field, but an author field, so you can filter with:
queryset = Post.objects.filter(
author_id__in=followed_users_id
).order_by('-date_posted')
But that being said, you should not filter like that. Given your models you can do this in a single query and thus avoiding the N+1 problem. You can simply filter with:
#api_view(['GET'])
#permission_classes([IsAuthenticated])
def post_feed_view(request, *args, **kwargs):
queryset = Post.objects.filter(
author__follow_user__user=request.user
).order_by('-date_posted')
serializer = PostSerializer(queryset, many=True)
return Response(serializer.data, status=200)
Related
I would like to list out the comments on my Post Detail page and wanted to see how I can connect a view to the specific comments for a given post?
Models.py
class Post(models.Model):
owner = models.ForeignKey(
Profile, null=True, blank=True, on_delete=models.SET_NULL)
title = models.CharField(max_length=200)
body = models.TextField()
Post_image = models.ImageField(
null=True, blank=True, default='default.jpeg')
create_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post', kwargs={'pk': self.pk})
class Meta:
ordering = ['-create_date']
class Comment(models.Model):
owner = models.ForeignKey(Profile, on_delete=models.CASCADE, null=True)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
text = models.TextField()
create_date = models.DateTimeField(auto_now_add=True)
Views.py
class PostDetailView(DetailView):
model = Post
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['comment_list'] = Post.comment_set.all()
return context
You can access the detail object of the DetailView with self.object:
class PostDetailView(DetailView):
model = Post
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['comment_list'] = self.object.comment_set.order_by('create_date')
return context
I am new to django and am creating a question answer app
I am getting the following error:
The QuerySet value for an exact lookup must be limited to one result using slicing.
models.py:
from django.db import models
from django.contrib.auth.models import User
from django.utils.text import slugify
from django.contrib.auth.models import User
class Log(models.Model):
title = models.CharField(blank=False, max_length=500)
content = models.TextField(blank=False)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
slug = models.SlugField(max_length=50, null=False)
created_by = models.CharField(null=True, max_length=500)
avatar = models.ImageField(
upload_to='images', blank=True)
def save(self, *args, **kwargs):
self.slug = self.slug or slugify(self.title)
super().save(*args, **kwargs)
class Meta:
verbose_name = ("Log")
verbose_name_plural = ("Logs")
def __str__(self):
return f"{self.title}"
class Solutions(models.Model):
log = models.ForeignKey(
Log, on_delete=models.CASCADE, blank=True, null=True)
solution = models.TextField(null=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
slug = models.SlugField(max_length=50, null=False, blank=True)
def save(self, *args, **kwargs):
self.slug = self.slug or slugify(self.title)
super().save(*args, **kwargs)
class Meta:
verbose_name = ("Solution")
verbose_name_plural = ("Solutions")
def __str__(self):
return f" {self.log.title} {self.solution} "
class Like(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
log = models.ForeignKey(Log, on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"like by {self.user.username} for {self.log.title}"
class Comments(models.Model):
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
log = models.ForeignKey(
Solutions, on_delete=models.CASCADE, null=True, blank=True)
comment = models.TextField(null=True, blank=True)
created_by = models.CharField(null=True, max_length=500)
class Meta:
verbose_name = ("Comment")
verbose_name_plural = ("Comments")
def __str__(self):
return f"{self.comment}"
The error that I am getting is in getting the comments of a particular solution.
The function for that in views.py:
def solution(request, id, question):
solution = Solutions.objects.filter(id=id)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
solution = Solutions.objects.filter(id=id)
com = form.cleaned_data['comment']
c = Comments()
c.comment = com
c.created_by = request.user.username
c.log = solution
print(c)
c.save()
message = messages.add_message(request, 25,
'Comment added successfully')
return HttpResponseRedirect(f'/solution/{id}/{solution.slug}')
else:
message = messages.add_message(request, 30,
'Error')
else:
form = CommentForm()
message = ''
try:
solution = Solutions.objects.filter(id=id)
print(solution)
comment = Comments.objects.filter(log=solution)
except Solutions.DoesNotExist:
comment = ''
solution = ''
context = {
'comments': comment,
'forms': form,
'message': message,
'solution': solution,
}
return render(request, 'solution.html', context=context)
The error is in the line solution = Solutions.objects.filter(id=id)
When I print the solution, it gives me a an empty query set.. Can anyone tell me the right way to do it?
I have a question (log as per in database) and solution to that question.. And the solutions have comments
Thanks
solution = Solutions.objects.get(id=id)
filter returns a QuerySet while get returns an object.
Solution.objects.filter(id=id) returns a QuerySet and it could be emplty if the Solution with such id does not exist. In this case you cannot get an exception you want. Use Solution.objects.get(id=id), then you will get a single instance or the Solutions.DoesNotExist exception.
BTW, id is a bad naming for variable in python, because id is a standard python function.
class Source(models.Model):
Name = models.CharField(max_length=150)`enter code here`
Address = models.CharField(max_length=150)
Office_Phone = PhoneField(blank=True, help_text='Office phone number')
Main_Contact = models.CharField(max_length=150, blank=True, null=True)
Contact_Email = models.EmailField(max_length=254, blank=True, null=True)
Contact_Phone = PhoneField(blank=True, help_text='Main Contact phone number')
Billing_Contact = models.CharField(max_length=150, blank=True, null=True)
Billing_Email = models.EmailField(max_length=254, blank=True, null=True)
Billing_Phone = PhoneField(blank=True, help_text='Billing Contact phone number')
Notes = models.CharField(max_length=250, blank=True, null=True)
def __str__(self):
return self.Name
def get_absolute_url(self):
return reverse('sources-detail', kwargs={'pk': self.pk})
class Rate(models.Model):
Source = models.ForeignKey(Source, on_delete=models.CASCADE)
Report_Type = models.ForeignKey(ReportType, on_delete=models.CASCADE)
Amount = models.DecimalField(max_digits=6, decimal_places=2, blank=True, null=True)
class SourceDetailView(DetailView):
model = Source
template_name = 'intake/source_detail.html'
context_object_name = 'source'
def get_context_data(self, *args, **kwargs):
context = super(SourceDetailView, self).get_context_data(*args, **kwargs)
context['rates'] = Rate.objects.all.filter(***not sure what to put here***)
return context
Would it be better to filter it in the Template or do it in the View? I am able to get results if I don't filter it and just use Rate.objects.all(), and then I filter it in my template. Just think there is a better way to do this.
You can just fetch the relation in reverse:
class SourceDetailView(DetailView):
model = Source
template_name = 'intake/source_detail.html'
context_object_name = 'source'
def get_context_data(self, *args, **kwargs):
context = super(SourceDetailView, self).get_context_data(*args, **kwargs)
context['rates'] = self.object.rate_set.all()
return context
That being said, here it does not make much difference to make the query in the template, since there is only one object here, so there is no N+1 problem.
I'm trying to change the field values of my objects in my database.
I'm using the following commands
I dont know why it isn't saving the changes from false to true.
Please help.
is_approved and is_superuser are attributs of User u.
Thanks
EDIT:
Code for User model
class User(AbstractUser):
TRAINEE = 1
MENTOR = 2
MODERATOR = 3
SUBMENTOR = 4
USER_TYPES = (
(TRAINEE, 'Trainee'),
(MENTOR, 'Industry Expert'),
(MODERATOR, 'Moderator'),
(SUBMENTOR,'SubMentor')
)
user_type = models.PositiveSmallIntegerField(choices=USER_TYPES, null=True, blank=True)
is_approved = models.BooleanField(default=False)
has_paid_subscription = models.BooleanField(default=False)
date_of_birth = models.DateField(null=True, blank=True)
bio = models.CharField(max_length=2000, validators=[MinLengthValidator(100)], blank=True, null=True)
profile_picture = models.ImageField(upload_to=profile_media_path, default='default_profile_pic.jpg', blank=True, null=True)
profile_tags = models.ManyToManyField(Tag, blank=True, related_name='profiles')
signup_completed = models.BooleanField(default=False)
referral_code = models.CharField(max_length=100,null=True,blank=True)
def __str__(self):
return self.username
def save(self, *args, **kwargs):
super(User, self).save(*args, **kwargs)
if self.bio:
self.profile_tags.clear()
lda_model = lda.LDA([self.bio])
tags = lda_model.generate_tags()
for tag in tags:
name = str(tag).capitalize()
try:
tag_object = Tag.objects.get(tag_name=name)
except Tag.DoesNotExist:
tag_object = Tag(tag_name=name)
tag_object.save()
self.profile_tags.add(tag_object)
tag_object.save()
#receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
Token.objects.create(user=instance)
EDIT 2: Tried u[0].refresh_from_db() it didnt work
Declare the model you are editing.
user = u[0]
user.is_superuser=True
user.save()
There is something funky going on with accessing the user from the queryset that is preventing it from saving. Not clear on the details of why but you can get around it by following the above pattern.
I'm trying to update other table after successful delete of of data. Below is my
views.py
class AttendeeDeleteView(DeleteView):
model = Attendee
success_url = reverse_lazy('index')
def get_form_kwargs(self):
id = self.kwargs['id'] # get value of enr
Payment.objects.filter(pk=id).update(registered=0)
In my urls.py
url(r'^delete/(?P<pk>\d+)$', AttendeeDeleteView.as_view(template_name="includes/attendee_delete.html"), name='attendee_delete',),
My Current code successfully delete the item but failed to update the other table.
my model
class Payment(models.Model):
id = models.AutoField(primary_key=True)
payee = models.CharField(max_length=200, blank=True, null=True)
contact = models.CharField(max_length=200,blank=True, null=True)
batch = models.CharField(max_length=200, null=True, blank=True)
ticketNumber = models.CharField(max_length=200)
ticketType = models.CharField(max_length=200, choices=TICKET_CHOICES, default='paid')
date = models.DateField('Date Paid (MM/DD/YYYY)', max_length=200, null=True, blank=True)
remarks = models.CharField(max_length=200 ,blank=True, null=True)
registered = models.BooleanField(default=False)
def __str__(self):
return self.payee
class Attendee(models.Model):
id = models.AutoField(primary_key=True)
payment = models.OneToOneField(Payment, on_delete=models.CASCADE, null=True, blank=True)
name = models.CharField(max_length=200)
batch = models.CharField(max_length=200, blank=True, null=True)
department = models.CharField(max_length=200, choices=DEPT_CHOICES, default='')
remarks = models.CharField(max_length=200, blank=True, null=True)
UPDATE 1:
I followed this came up with
def get(self, request, *args, **kwargs):
id = kwargs['pk'] # get value of enr
context = Payment.objects.filter(pk=id).update(registered=0)
return self.render_to_response(context)
but it returned context must be a dict rather than int.
I think def get_form_kwargs(self): doesn't executed, because it used for FormMixin. But, you can also handle it inside get() function.
def get(self, request, *args, **kwargs):
attendee = self.get_object()
Payment.objects.filter(pk=attendee.payment.pk).update(registered=0)
context = self.get_context_data(object=attendee)
return self.render_to_response(context)
See this https://ccbv.co.uk/projects/Django/1.11/django.views.generic.edit/DeleteView/ for more..
Edit:
This solution below if still getting a problem when using get() method.
from django.http import HttpResponseRedirect
....
def delete(self, request, *args, **kwargs):
"""
Calls the delete() method on the fetched object and then
redirects to the success URL.
"""
self.object = self.get_object()
success_url = self.get_success_url()
Payment.objects.filter(pk=self.object.payment.pk).update(registered=0)
self.object.delete()
return HttpResponseRedirect(success_url)