Cannot assign "<SimpleLazyObject: <User: XXX>>": "Comment.user" must be a "MyProfile" instance - python

Hello I know I have two problems here. one is a SimpleLazyObject issue which I can fix it in a kinda hackish way. The other is "Comment.user" must be a "MyProfile" instance which I don't know how to fix. I think somewhere in the way, things got mixed up.
def post(request, slug):
user = get_object_or_404(User,username__iexact=request.user)
try:
profile = MyProfile.objects.get(user_id=request.user.id)
# if it's a OneToOne field, you can do:
# profile = request.user.myprofile
except MyProfile.DoesNotExist:
profile = None
post = get_object_or_404(Post, slug=slug)
post.views += 1 # increment the number of views
post.save() # and save it
comments = post.comment_set.all()
comment_form = CommentForm(request.POST or None)
if comment_form.is_valid():
post_instance = comment_form.save(commit=False)
post_instance.user = request.user #this is where error is occuring, if I put request.user.id simpleLazyObject dissapears.
post_instance.path = request.get_full_path()
post_instance.post = post
post_instance.save()
context_dict = {
'post' :post,
'profile' :profile,
'comments':comments,
'comment_form': comment_form
}
return render(request, 'main/post.html', context_dict)
I'm not sure what it means by Comment.user must be MyProfile instance.
In my comments app, models.py I have
class Comment(models.Model):
user = models.ForeignKey(MyProfile)
and in my accounts app, models.py I have
class MyProfile(UserenaBaseProfile):
user = models.OneToOneField(User, unique=True, verbose_name=_('user'), related_name='my_profile')
I'm not sure how to fix this problem, any help will be highly appreciated.

Comment has ForeignKey to MyProfile, yet in the line that triggers the error you provide a User model.
The correct way would be:
my_p = MyProfile.objects.get(user=request.user)
post_instance.user = my_p
Note that you use:
MyProfile.objects.get(user=request.user)
And not the id field. Although behind the scenes django does use the id field as the real foreign key in the database, in your code you use the object. A relational field is a descriptor where django does the magic to run a relational query.

Related

Django 2.1.5: Storing the current username in a blog entry

I am very new to Django and try to build a little app for my family with some basic features, one of which is a blog app. In this now I want to store the author of a blog entry in the article model to save it in the database. In the end in the blog entry I want a header that displays the author and the datetime.
I found several approaches to that but some how none of them worked for me so far. The last thing I did now was to try and grab the username in the view with requests.user.get_username() and then populate the field in my form with this string as initial value. Somehow it just doesn't come through, I always get the "field is required" error message...
Here is my blog-create-view.py:
def blog_create_view(request):
user = request.user.get_username()
data = {'author': user}
form = BlogForm(request.POST, data)
if form.is_valid():
form.save()
return HttpResponseRedirect('/blog/blog-create/thanks')
else:
print(form.errors)
form = BlogForm()
context = {
'articleform' : form,
}
return render(request, "blog-create.html", context)
this is the form:
class BlogForm(forms.ModelForm):
title = forms.CharField(label='',
widget=forms.TextInput(attrs={"placeholder":"Titelfeld"}))
text = forms.CharField(
label='',
widget=forms.Textarea(
)
)
author = forms.CharField(widget=forms.HiddenInput())
class Meta:
model = Article
fields = [
'title',
'text',
]
and this is the model:
class Article(models.Model):
title = models.CharField(blank=False,max_length=1000)
text = models.CharField(blank=False, default='Text', max_length=10000)
datetime = models.DateTimeField(auto_now=True)
featured = models.BooleanField(default='False')
author = models.CharField(max_length=1000)
Help is much appreciated! I am getting really frustrated trying to figure this out
if you want to add the author name as current logged in users username you can do it as follows. And remove author in the form
if form.is_valid():
instance = form.save(commit=False)
instance.author = request.user.username
instance.save()
Being said that, it will be better to change the author to foreignkey from django.contrib.auth.models import User and assign to the request.user rather than to the username, so that you can filter the articles by Article.objects.filter(author=request.user)

Changing the Userprofile

Hello i have UserSettings and the user as the possibility to use a ProfilePicture. The Problem is the User cannot change any of his profile Settings. since i get the Error Unique Constraint failed or (thats what i get right now) 'int' object has no attribute '_committed'
I think the problem is in the view but i dont know how to change it.
My model:
class UserSettings(models.Model):
profileimage = models.ImageField(verbose_name=_(u"Change Your Profilepicture"),upload_to=upload_location,
default=1,
blank=True,
)
Info = models.CharField(verbose_name=_(u"Tell us about yourself"),max_length=500,default="I'm a Human")
status =
City = models.CharField(verbose_name=_(u"Where are you from"),max_length=500,default='Earth')
user = models.OneToOneField(User, default=1)
objects = models.Manager()
class Meta:
ordering =['-user']
def __unicode__(self):
return self.user.username
My View:
#login_required
def userprofiletwo(request):
user = request.user
form = UserSettingsForm(request.POST or None, request.FILES or None)
if form.is_valid():
user = request.user
form.save()
messages.success(request, 'Your personal Settings are Updated')
return redirect('userprofiletwo')
context = {
'form':form,
}
return render(request, 'userprofile/userprofiletwo.html', context)
I tried to change the OnetoOne field on the model to FeoreignKey or ManytoMany but this made new userprofiles instead of replacing the old information with new information.
Thanks in advise.
You need to pass in the current profile into the form.
form = UserSettingsForm(request.POST or None, request.FILES or None, instance=request.user.profile)

Like functionality in Django

I'm developing a social platform and currently coding the like functionality for user posts. However, I can't seem to make it work. These are my Models.py:
class Post(models.Model):
user = models.ForeignKey(User)
posted = models.DateTimeField(auto_now_add=True)
content = models.CharField(max_length=150)
picturefile = models.ImageField(upload_to="post_content", blank=True)
class Like(models.Model):
user = models.ForeignKey(User, null=True)
post = models.ForeignKey(Post, null=True)
I pass the post ID through my url as 'post_id', and then in my views:
def liking(request, post_id):
newlike = Like.objects.create()
newlike.post = post_id
newlike.user = request.user
newlike.save()
return redirect(reverse('dashboard'))
However, it returns the following error:
Cannot assign "'47'": "Like.post" must be a "Post" instance.
Does anyone knows what I'm missing or doing wrong?
You are passing newlike.post a number (integer field) while it is expecting a Post instance.
This sould work:
from django.http.shortcuts import get_object_or_404
def liking(request, post_id):
post = get_object_or_404(Post, id=post_id)
newlike = Like.objects.create(user=request.user, post=post)
return redirect(reverse('dashboard'))
Note 1: Better use the handy shortcut get_object_or_404 in order to raise a 404 error when the specific Post does not exist.
Note 2: By calling objects.create will automatically save into the db and return an instance!
newlike.post should be a Post object, not an int.
You need to find post by id first:
post = Post.objects.get(pk=post_id)
newlike.post = post
or, if you don't want to do this lookup:
newlike.post_id = post_id

Validating a field in Create Profile Form

I am trying to build a Create Profile Form after registration and my codes are below.Its already working only for a slight problem,that is,if the name field of Profile model matches one in database,django brings an error message column slug is not unique .I see that slug field is clashing with another,how am I going to edit the below codes to raise a validation error message if name submitted is similiar to one in db?
models.py
from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
name= models.CharField(max_length=10)
description=models.TextField()
slug=models.SlugField(unique=True)
user = models.OneToOneField(User, blank=True, null=True)
def __str__(self):
return self.name
views.py
def create_profile(request):
form_class = ProfileForm
if request.method == 'POST':
form = form_class(request.POST)
if form.is_valid():
profile = form.save(commit=False)
profile.user = request.user
profile.slug = slugify(profile.name)
profile.save()
slug = slugify(profile.name)
return redirect('profile_details', slug=profile.slug)
else:
form = form_class()
return render(request, 'profile/create_profile.html', {'form': form,})
urls.py
urlpatterns=[url(r'^accounts/create_profile/$',views.create_profile,name='registration_create_profile'),]
Thanks
ModelForms actually validate uniqueness as part of the is_valid() checks.
The problem in your case is that you are manually setting the slug after running is_valid(). Because of this you will have to manually validate uniqueness after setting the slug. Something like this would work:
if form.is_valid():
profile = form.save(commit=False)
profile.user = request.user
profile.slug = slug = slugify(profile.name)
# Check slug uniqueness, keep appending a digit until it fits
n = 1
while Profile.objects.filter(slug=profile.slug).exists():
# Need to find a new slug.
profile.slug = '%s-%d' % (slug, n)
n += 1
profile.save()
return redirect('profile_details', slug=profile.slug)
Note that it is probably better to perform this uniqueness check inside the model's save() method instead of in the view - this just illustrates the logic.
Alternatively you could use a library like django-autoslug which performs this logic for you.

Django filter foreignkey field

Short version:
I have a Django app used for recipes, and want to filter data to be sent to a template in my view. I basically want all recepies that are added by a specific user to be sent as context. The following filtering returns an error message invalid literal for int() with base 10: my_username.
recipes = Recipe.objects.filter(added_by = uname)
The variable uname is passed from a template. On the other hand, filtering on request.user works fine, but is not what I want.
recipes = Recipe.objects.filter(added_by = request.user)
Details:
My models are given (relevant fields) as:
class Recipe (models.Model):
...
...
added_by = models.ForeignKey(User)
Where User is an existing Django user. When I call {{ recipe.added_by }} in my template, I get the username as wanted. This username is passed on to a view with href="/profile/{{recipe.added_by}}", where the view looks like the following:
def profile(request, uname):
print uname #Correct username printed
print request.user #Logged in user (not relevant, as userprofile should be visible for all)
recipes = Recipe.objects.filter(added_by = uname) #Does not work. Why?
#recipes = Recipe.objects.filter(added_by = request.user)
form = CommentForm(request.POST)
context = {
'uname': uname,
'recipes': recipes,
'form': form,
}
return render(request, '*app_name*/profile.html', context)
Not sure what I am missing, but from what I can tell, it seems to have something to do with the fact that added_by has a Foreign Key to a User. I also tried to change the filter argument to recipe__added_by__added_by = uname according to [1], but Django then returned an error saying "Cannot resolve keyword 'recipe' into field", which seems obvious. My url is:
url(r'^profile/([a-zA-Z0-9]+)/$', 'profile', name='*app_name*-profile'),
Thanks for any reply. Sorry if this should have been obvious.
[1] Django models filter by foreignkey
You can try like:
recipes = Recipe.objects.filter(added_by__username = uname)
And request.user works fine for Recipe.objects.filter(added_by = request.user) because request.user is an object. details: https://docs.djangoproject.com/en/dev/topics/db/queries/#lookups-that-span-relationships
When child class defined as
class Recipe (models.Model):
...
...
added_by = models.ForeignKey(User)
makemigration generates foreign key as added_by_id.
So, you have to use corresponding field name in filter.
Eg: recipes = Recipe.objects.filter(added_by_id = uname)

Categories