I'm using Django and I'm getting the error AttributeError at /admin/network/post/
'Post' object has no attribute 'user'
The strange thing is this error happens when I'm looking at the admin section, and clicking 'Posts.' I only have models for users and posts. Not sure how to fix this error because so far I've never gotten an error like this when clicking it in the admin section of the site: http://127.0.0.1:8000/admin/
I think the issue is in my model because the view for creating a post works totally fine.
models.py
class User(AbstractUser):
pass
class Post(models.Model):
text = models.TextField(max_length=500, blank=True, null=True)
username = models.ForeignKey('User', on_delete=models.CASCADE,
related_name='author',
null=True, blank=True)
timestamp = models.DateTimeField(auto_now_add=True)
like = models.ManyToManyField(
User, blank=True, related_name="liked_user")
def __str__(self):
return self.user.username
class Follow(models.Model):
target = models.ForeignKey('User', on_delete=models.CASCADE,
related_name='followers')
follower = models.ForeignKey('User', on_delete=models.CASCADE,
related_name='targets')
views.py
def make_post(request):
if request.method == "GET":
form_for_post = {'form': PostForm()}
return render(request, "network/make_post.html", form_for_post)
else:
form = PostForm(request.POST)
if form.is_valid():
text = form.cleaned_data['text']
new_post = Post.objects.create(
text=text,
username=request.user,
)
return render(request, "network/make_post.html", {
"new_post": new_post,
})
You defined the field that refs to a User in the Post model to be username, not user, although user should be a better idea.
You thus should implement the __str__ method as:
class Post(models.Model):
# …
username = models.ForeignKey('User', on_delete=models.CASCADE, related_name='author', null=True, blank=True)
# …
def __str__(self):
return self.username.username
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
Related
I'm trying to save a user post data through a modelform in django. Unfortunately, I stumbled to NOT NULL constraint failed:statussaver_post.user_id. Here's my post model.
class post(models.Model):
content=models.TextField(null=True,blank=True)
title = models.CharField(max_length=200,null=True,blank=True)
vedio = models.FileField(upload_to='vedios', blank=True, null=True)
img = models.ImageField(upload_to='images', null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('-created',)
def __str__(self):
return self.title
I handle the request in views.py as shown below.
def userpost(request):
if request.method=='POST':
form=uploadform(request.POST,request.FILES)
if form.is_valid():
form.save()
return redirect('home')
else:
form=uploadform()
return render(request,'statussaver/u.html',{'form':form,})
The form in the code above is called from forms.py as presented below.
from django import forms
from .models import post
class uploadform(forms.ModelForm):
class Meta:
model=post
fields= '__all__'
What should I do to fix this error ?
I tried to solve the problem and got stuck. The problem is that I have a post that I can follow. My problem is that I don't know how to add a tracking button. Should this be done by url, with a view? Or should it be rather as a method in the model?
My problem is also whether it is properly written in terms of models - using the intermediate model Follower?
Here is Post model and I would like to add followers here. I mean, everybody who is interested, can follow this post.
class Post(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='posts')
title = models.CharField(max_length=255, unique=True)
description = models.TextField(max_length=1024)
followers = models.ManyToManyField(settings.AUTH_USER_MODEL, through='Follower', blank=True)
is_visible = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('posts:post_detail', kwargs={'pk': self.pk})
def number_of_followers(self):
return self.followers.count()
Here is my manager for follower model:
class FollowerManager(models.Manager):
use_for_related_fields = True
def follow(self, user, pk):
post_object = get_object_or_404(Post, pk=pk)
if user.is_authenticated():
if user in post_object.followers.all():
Follower.objects.filter(post=post_object, user=user).delete()
else:
Follower.objects.create(post=post_object, user=user)
Here is Follower model:
class Follower(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
objects = FollowerManager()
Interactions between a user's browser and the database can only be done via a URL and a view. That view might call a model method, but there is no possible way for the browser to call that method directly.
(Also I don't understand what you're doing in the manager. Why are you deleting followers if the user is authenticated? Note that will always be true, so the followers will always be deleted.)
I want to display all the reservations created by the currently logged-in user.
Django model: Filtering by user, always
Documentation: Many-to-one relationships
are some of the links I checked but still haven't been able to solve the problem.
Model.py
class Reservation(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE)
pickup_date = models.DateField()
pickup_time = models.TimeField(blank=True, null=True)
drop_date = models.DateField()
drop_time = models.TimeField(blank=True, null=True)
drop_location = models.CharField(blank=False, max_length=250, choices=LOCATIONS_CHOICES)
reserved_on = models.DateTimeField(auto_now_add=True)
edited_on = models.DateTimeField(auto_now=True)
views.py
class ReservationList(LoginRequiredMixin,ListView):
model = Reservation
context_object_name = 'reservations'
queryset= Reservation.objects.filter(user=request.user)
urls.py
url(r'^reservations/$', ReservationList.as_view(), name='reservations_list'),
I get this error when I run the server
AttributeError: 'module' object has no attribute 'user'
How do I display only reservations created by the currently logged in user. Any guidance is appreciated.
You should override the get_queryset method of ListView, you can't do it by setting a static property (queryset) on the class. Here's how to do it:
class ReservationListView(LoginRequiredMixin, ListView):
model = Reservation
context_object_name = 'reservations'
def get_queryset(self):
return Reservation.objects.filter(user=self.request.user)
What a want to do: When a user is logged in, and he or she makes a post, the name of that user should automatically be assigned in my database posts.
What it's doing: It's not adding a user automatically, but i am able to assign a user manually, so I'm accessing the user database, and seeing whom i can attach to a newly made post.
My question is then, how can i get this process done automatically?
Here is my code from the model.py in the posts app:
from __future__ import unicode_literals
from django.conf import settings
from django.core.urlresolvers import reverse
from django.db import models
from django.contrib.auth.models import User
User = settings.AUTH_USER_MODEL
class Post(models.Model):
title = models.CharField(max_length=120)
content = models.TextField()
#email = models.EmailField(null=True, blank=True, default=None)
user = models.ForeignKey(User, null=True,)
#upload = models.FileField(null=True, blank=True, default=None)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=True, auto_now_add=False)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("posts:detail", kwargs={"id":self.id})
class Meta:
ordering = ["-timestamp", "-updated"]
I am getting the user class via User = settings.AUTH_USER_MODEL and the AUTH_USER_MODEL is referring in settings.py to a class called MyUser in another models.py who originates from an app called accounts.
here is the code from that class:
class MyUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
is_admin = models.BooleanField(_('staff status'), default=False,
help_text=_('Designates whether the user can log into this admin site.'))
is_active = models.BooleanField(_('active'), default=True,
help_text=_('Designates whether this user should be treated as '
'active. Unselect this instead of deleting accounts.'))
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
USERNAME_FIELD = 'email'
Here is the code from views.py in the posts app:
def post_create(request):
form = PostForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
# Message succes
messages.success(request, "Succesfully Created ")
return HttpResponseRedirect(instance.get_absolute_url())
else:
messages.error(request, "Not Succesfully created")
context = {
'form': form,
}
return render(request, app_name+"/post_form.html", context)
Here is the forms.py in the posts app:
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = {
"title",
"content",
"user",
#"email",
#"upload",
}
Here are two pictures to illustrate my problem:
The post create site
The django administration
Let me now if any more code is needed, appreciate any feedback as well.
I don't have a lot of rep on stack overflow so please let me know if this is poorly explained, and i shall re right it.
Simply change:
instance = form.save(commit=False)
instance.save()
to
instance = form.save(commit=False)
if request.user.is_authenticated():
instance.user = request.user
instance.save()
If user is logged in, i think the Combobox should not
appear, so you can do that on forms.py
forms.py
class PostForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super(PostForm, self).__init__(*args, **kwargs)
if not self.user.is_authenticated():
self.fields['user'] = forms.ModelChoiceField(
required=True,
queryset=User.objects.all())
class Meta:
model = Post
fields = {
"title",
"content",
# "user",
#"email",
#"upload",
}
on views.py
def post_create(request):
form = PostForm(request.POST or None, user = request.user)
if form.is_valid():
if request.user.is_authenticated():
form.instance.user = request.user
form.save()
...
return render(request, app_name+"/post_form.html", context)
If you want the Combobox has selected with the user logged in, you can pass initial data on views.py, like this:
def post_create(request):
if request.method == 'GET':
form = PostForm(initial = {'user' : request.user})
I have the following custom SignupForm (simplified, works perfectly without my_file):
class SignupForm(forms.Form):
home_phone = forms.CharField(validators=[phone_regex], max_length=15)
my_file = forms.FileField()
def signup(self, request, user):
new_user = ReqInfo(
user=user,
home_phone=self.cleaned_data['home_phone'],
my_file=my_file,
)
new_user.save()
In models.py:
class ReqInfo(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, blank=True, null=True)
home_phone = models.CharField(
validators=[phone_regex], max_length=15)
my_file = models.FileField(upload_to='uploads/directory/', validators=[resume_file_validator], blank=True, null=True)
My issue:
When I add a a user in myurl/accounts/signup it tells me that the my_file field is Required, even though I select a file.
The signup.html template allauth uses did not have
enctype="multipart/form-data"
After adding it, it works like a charm.