I am trying to get a query set which contains post based on usernames which are stored in model "FollowingProfiles". so models and corresponding views is as follows:-
from django.contrib.auth.models import User
class Profile(models.Model):
Follwers=models.IntegerField(default='0')
user=models.OneToOneField(User,on_delete=models.CASCADE,primary_key=True)
bio=models.TextField(max_length=120,blank=True)
location=models.CharField(max_length=30,blank=True)
birth_date=models.DateField(null=True,blank=True)
verified=models.BooleanField(default=False)
ProfilePic=models.ImageField(upload_to='UserAvatar',blank=True,null=True)
def __str__(self):
return self.user.username
#receiver(post_save,sender=User)
def update_user_profile(sender,instance,created,**kwargs):
if created:
Profile.objects.create(user=instance)
instance.profile.save()
class FollowingProfiles(models.Model):
Profile=models.ForeignKey(Profile,on_delete=models.CASCADE)
ProfileName=models.CharField(max_length=120,blank=True,null=True)
def __str__(self):
return self.ProfileName
class post(models.Model):
Profile=models.ForeignKey(Profile,on_delete=models.CASCADE)
Picture=models.ImageField(upload_to='PostMedia',blank=True,null=True)
DatePosted=models.DateTimeField(default=timezone.now)
Content=models.TextField(blank=True,null=True)
def __str__(self):
return self.Profile.user.username
views.py
def feed(request):
if request.user.is_authenticated:
userprofile=FollowingProfiles.objects.filter(Profile__user=request.user)
for p in userprofile:
postuser=post.objects.filter(Profile__user__username=p.ProfileName)
usrpost+=postuser
return render(request,'feed/feed.html',{'usrpost':usrpost})
else:
return redirect('signup')
It produces following error:-
function' object has no attribute 'objects'
C:\Users\G COMTECH SYSTEM\django-projects\saporaapp\sapora\views.py in feed, line 45
line 45 is
postuser=post.objects.filter(Profile__user__username=p.ProfileName)
Seems like your post model is conflicting with some post declared as function.
What I suggest is to follow PEP8 in naming your Classes, function, variables and so on in order to avoid such cases.
In your particular case I would rename post model into Post as it's better to name Classes in CamelCase style.
But for fields your are using CamelCase, but it's better to use underscore:
Like that:
class Post(models.Model):
profile = models.ForeignKey(Profile,on_delete=models.CASCADE)
picture = models.ImageField(upload_to='PostMedia',blank=True,null=True)
date_posted = models.DateTimeField(default=timezone.now)
content = models.TextField(blank=True,null=True)
If you want to make it work fast find where post can be declared as a function in view.py file and rename it. If it's something imported you can change from mymodule import post to be import mymodule and then call function as mymodule.post
Also usrpost is not declared and here is a better solution without for loop:
userprofile_names=FollowingProfiles.objects.filter(Profile__user=request.user).values_list('ProfileName', flat=True)
usrpost=post.objects.filter(Profile__user__username__in=userprofile_names)
return render(request,'feed/feed.html',{'usrpost':usrpost})
Related
I'm trying to create a view for resetting the password, But I'm trying to use the django.contrib.auth.forms.PasswordChangeForm to use the form on the view, But there's a problem!
In django.contrib.auth.forms.SetPasswordForm form's __init__ function a user is needed for the form to work, And I don't know how to implement or remove that.
Basically what I understood about this form was that it's a global url, But my urls follow this path: 'u/<slug:slug>/account/password/
I would like to know how to rewrite the __init__ function in a way that it doesn't mess up the parent(forms.Form)'s `init function or either provide the user to the form somehow.
Right now if I try to run the code I get the error:
SetPasswordForm.init() missing 1 required positional argument: 'user'
forms.py:
class UserPasswordChangeForm(PasswordChangeForm):
class Meta:
model = User #Not sure if this even does anything with PasswordChangeForm
fields = ('old_password', 'new_password1', 'new_password2')
views.py:
class UserPasswordChangeView(UpdateView):
model = User
form_class = UserPasswordChangeForm
template_name = 'auth/password.html'
urls.py:
path('u/<slug:slug>/account/password/', UserPasswordChangeView.as_view(), name='password'),
user model used(if needed):
class User(AbstractUser):
slug = models.SlugField(blank=False, null=False)
def get_absolute_url(self):
return reverse('profile', kwargs={'slug': self.slug})
I am using django-extensions.AutoSlugField and django.db.models.ImageField.
To customize image name uploaded for django.db.models.ImageField, what I did:
from django.utils.text import slugify
# idea is to make image name the same as the automatically generated slug, however don't work
def update_image_name(instance, filename):
# this debug instance, and instance.slug is empty string
print(instance.__dict__)
# I attempt to use slugify directly and see that it's not the same as the output generated by AutoSlugField
# E.g. If I create display_name "shawn" 2nd time, AutoSlugField will return "shawn-2", but slugify(display_name) return "shawn"
print(slugify(instance.display_name))
return f"images/{instance.slug}.jpg"
class Object(models.Model):
...
display_name = models.TextField()
...
# to customize uploaded image name
image = models.ImageField(blank=True, upload_to=update_image_name)
...
# create slug automatically from display_name
slug = AutoSlugField(blank=True, populate_from=["display_name"]
Based on what I debug, when I call instance inside update_image_name, slug is empty string.
If I understand correctly slug is only created at event save, so when I call ImageField instance, slug is not yet created, therefore empty string.
I think it might have something to do with event post save. However, I am not sure if that's the real reason or how to do that.
How can I get the automatically generated slug as my customized image name?
That's a tricky one because the order the fields are getting saved matters.
The brute-force attack I'm suggesting would be to override the save method of your model and manually call the create_slug method before everything else ensuring the slug is set:
from django.utils.encoding import force_str
[...]
class Object(models.Model):
[...]
def save(self, *args, **kwargs):
self.slug = force_str(self._meta.get_field('slug').create_slug(self, False))
super(Object, self).save(*args, **kwargs)
That's what AutoSlugField does, refer to the code here. self._meta.get_field('slug') get's the slug field definition and then we just call the create_slug method.
Tested under Python 3.7.9 & Django 3.1.5 like this:
from django.core.files.uploadedfile import SimpleUploadedFile
o = Object()
o.display_name = "foo bar"
o.image = SimpleUploadedFile(name='test_image.png', content=open('/path/to/test/image.png', 'rb').read(), content_type='image/png')
o.save()
Then I see update_image_name return images/foo-bar.jpg.
This is my view:
class viewbloglistview(LoginRequiredMixin,ListView):
model = Blog
paginate_by = 6
def get_template_names(self):
if True:
return ['blog/view_blogs.html']
else:
return ['blog/blog_list.html']
def get_queryset(self):
return Blog.objects.all().order_by('-blog_views')[:20]
def get_context_data(self, **kwargs):
context = super(viewbloglistview, self).get_context_data(**kwargs)
context['categories_list'] = categories.objects.all()
return context
This is my function in models.py file:
def categories_count(self):
categories_count = categories.objects.annotate(blog_count=Count('blogs')).values_list('Title','blog_count')
return categories_count
I want call the function in my views with a context name to render the activity in my template..
Can anyone please help me out to solve this problem??
Thank you
This is a python problem, your question is unclear but based on what you said:
Case the function in in your model.py alone:
from . import model.py
// code
categories_count()
Case the function is a method in a class as it is shown on you code with the self parameter in it:
from . import model.py
// code
classname.categories_count()
Assuming that you have named your class as 'categories' (which should have been named as Category in the first place),
categories_count should have been in a manager as you are querying in a class level. Say you don't want a manager and want to keep the code inside the model, then you can use it as a class method.
#classmethod
def categories_count(cls):
return cls.objects.annotate(blog_count=Count('blogs')).values_list('Title','blog_count')
and in the views use it as
categories.categories_count()
Just remember that the regular methods with the 'self' argument like the one you have, should only be used when you are dealing with a single instance, not when you are accessing the class itself.
How can I set success_url based on a parameter?
I really want to go back to where I came from, not some static place. In pseudo code:
url(r'^entry/(?P<pk>\d+)/edit/(?P<category>\d+)',
UpdateView.as_view(model=Entry,
template_name='generic_form_popup.html',
success_url='/category/%(category)')),
Which would mean: edit entry pk and then return to 'category'. Here an entry can be part of multiple categories.
Create a class MyUpdateView inheritted from UpdateView and override get_success_url method:
class MyUpdateView(UpdateView):
def get_success_url(self):
pass #return the appropriate success url
Also i like to pass such parameters like template_name and model inside of inheritted class view, but not in .as_view() in urls.py
Had the same issue. Was able to get the paramater from self.kwargs as Dima mentioned:
def get_success_url(self):
if 'slug' in self.kwargs:
slug = self.kwargs['slug']
else:
slug = 'demo'
return reverse('app_upload', kwargs={'pk': self._id, 'slug': slug})
I found a way which is useful and very simple. Check it out.
class EmployerUpdateView(UpdateView):
model = Employer
#other stuff.... to be specified
def get_success_url(self):
pk = self.kwargs["pk"]
return reverse("view-employer", kwargs={"pk": pk})
Define get_absolute_url(self) on your model. Example
class Poll(models.Model):
question = models.CharField(max_length=100)
slug = models.SlugField(max_length=50)
# etc ...
def get_absolute_url(self):
return reverse('poll', args=[self.slug])
If your PollUpdateView(UpdateView) loads an instance of that model as object, it will by default look for a get_absolute_url() method to figure out where to redirect to after the POST. Then
url(r'^polls/(?P<slug>\w+)/, UpdateView.as_view(
model=Poll, template_name='generic_form_popup.html'),
should do.
Why don't you add a 'next' parameter to your form (template) and catch it in your view. It's common practice to achieve redirecting this way.
I use a snippet in http://www.djangosnippets.org/snippets/1034/ for my Model inheritance. It works fine at the first. However, after I delete some elements in database, the code works wrong.
As I debug, I found that the problem is reside in the method: as_leaf_class.
In the following code:
if (model == Meal):
return self
return model.objects.get(id=self.id)
the last line will raise exception when the element is deleted.
Anyone could give a solution for this?
Model inheritance with content type and inheritance-aware manager
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.db.models.query import QuerySet
class SubclassingQuerySet(QuerySet):
def __getitem__(self, k):
result = super(SubclassingQuerySet, self).__getitem__(k)
if isinstance(result, models.Model) :
return result.as_leaf_class()
else :
return result
def __iter__(self):
for item in super(SubclassingQuerySet, self).__iter__():
yield item.as_leaf_class()
class MealManager(models.Manager):
def get_query_set(self):
return SubclassingQuerySet(self.model)
class Meal (models.Model) :
name = models.TextField(max_length=100)
content_type = models.ForeignKey(ContentType,editable=False,null=True)
objects = MealManager()
def save(self, *args, **kwargs):
if(not self.content_type):
self.content_type = ContentType.objects.get_for_model(self.__class__)
super(Meal, self).save(*args, **kwargs)
def as_leaf_class(self):
content_type = self.content_type
model = content_type.model_class()
if (model == Meal):
return self
return model.objects.get(id=self.id)
class Salad (Meal) :
too_leafy = models.BooleanField(default=False)
objects = MealManager()
I don't know if that snippet is still relevant now that you can use abstract base classes.
This lets you declare a model that is not a db table but that other models can inherit from.
First answer: Why are you trying to call as_leaf_class on a deleted object? If it hurts when you do that, don't do it.
The second answer is that you could wrap the failing line with try...except Meal.DoesNotExist, and return None or self or something.