This is the model I've defined:
class Post(models.Model):
user = models.ForeignKey(MSUser)
upvote_count = models.IntegerField()
post_status = models.IntegerField(choices = POST_STATUS)
title = models.CharField(max_length=200,null = True,blank = True)
content = models.CharField(max_length=1000,null = False,blank = False)
created_at = models.DateTimeField(auto_now_add=True, null=True)
updated_at = models.DateTimeField(auto_now=True, null=True)
def __unicode__(self):
return self.content
def get_user(self):
return self.user.__unicode__()
def save(self, **kwargs):
super(Post, self).save(**kwargs)
Here is the view:
class Post (View):
#method_decorator(csrf_exempt) # To be removed
def dispatch(self, request, *args, **kwargs):
# Placeholder for fine grained permission system to prevent unwarranted GET/POST/PUTS
# Check request.user properties (like group etc) and request.method
# return HttpResponseForbidden()
return super(Post, self).dispatch(request, *args, **kwargs)
def get(request):
pass
def post(self, request):
responseMessage = {}
user = request.user
if user.is_authenticated():
title = request.POST.get('title', None)
content = request.POST.get('content', None)
if title is None or content is None:
responseMessage['status'] = 'failure'
responseMessage['message'] = 'Mandatory data is missing.'
return HttpResponse(json.dumps(responseMessage))
else:
newPost = Post(user = user,
title = title,
content = content,
post_status = PS_CREATED,
upvote_count = 0)
newPost.save()
responseMessage['status'] = 'success'
responseMessage['message'] = 'Post created successfully'
responseMessage['server_id'] = newPost.id
return HttpResponse(json.dumps(responseMessage))
When sending a request from Postman I keep getting the following error:
AttributeError: 'Post' object has no attribute 'save'
What am I doing wrong?
Your view class and the model class have the same name i.e. Post.
So, when you do Post(user=..) in your view, it tries to create the Post view object and then call .save() on it whereas it should have created the Post model object and saved it.
To solve your problem, you need to change your view class name to something else.
Try changing
class Post(View):
to something like
class PostView(View):
You have duplicated objects named Post which you got mixed. It looks like you are trying to save the View object instead of the Model object.
Related
I have a form for creating the object, and it works fine. When I use that form for editing the object, it doesn't work. I did debugging the post method,and it also works fine, the form is valid, the redirect work, the success message appear, but not update the object. The form instance is also work correctly. It just don't update
# models.py
class Item(models.Model):
status_choices = (
('rent','Rent'),
('give', 'Give'),
('share','Share'),
)
item_types = (
('book','Book'),
('movie','Movie',),
('data','Data'),
('other','Other'),
)
title = models.CharField(max_length=200, db_index=True)
slug = models.SlugField(max_length=200, db_index=True, blank=True,unique=True)
owner = models.ForeignKey(settings.AUTH_USER_MODEL)
cover = models.ImageField(upload_to='items/%Y/%m/%d',blank=True)
link = models.URLField(blank=True)
description = models.TextField(max_length=500, blank=True)
status = models.CharField(max_length=10,choices=status_choices,default='Share')
item = models.CharField(max_length=10, choices=item_types,default='Data', verbose_name='Item Type')
publish = models.DateTimeField(auto_now=True,null=True)
class Meta:
ordering = ('-publish',)
index_together = (('id', 'slug'),)
def __str__(self):
return '{} : <{}> for {}'.format(self.title,self.item,self.status)
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Item, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse('item_edit', kwargs={'slug':self.slug})
#forms.py
class ItemShareForm(forms.ModelForm):
class Meta:
model = Item
fields = ('title', 'cover', 'link', 'description', 'status', 'item')
widgets = {
'description' : forms.Textarea(),
}
#views.py
#login_required
def item_edit(request,slug):
instance = get_object_or_404(Item,slug=slug)
if request.method == 'POST': #check the request method
edit_form = ItemShareForm(request.POST ,instance=instance)
if edit_form.is_valid(): # check the form validation
update_item = edit_form.save(commit=False)
update_item.owner = request.user #assign the owner
update_item.save() # update the instance
messages.success(request,'Your item has been updated successfully') # writing the message to user
return redirect('/')
else:
messages.error(request,'Error updating your item...')
else:
edit_form = ItemShareForm(instance=instance)
return render(request, 'account/share.html',{'itemform':edit_form})*
You have overridden you model save method like so:
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Item, self).save(*args, **kwargs)
This means that the object will only ever get saved if the slug is empty - i.e., it will only ever get saved once. Any future calls to save will not execute that if block, and nothing will happen.
You probably mean to do this instead - note indentation of the last line:
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(Item, self).save(*args, **kwargs)
In my django app I have a Myuser(User) class. It inherits the User class.
When a new user is created the Myuser table is poplulated.
myusers.py
class Myuser(User):
address = models.CharField(max_length=40)
pobox = models.CharField(max_length=40)
models.py
class Someclass(models.Model):
objectid = models.IntegerField()
objecttype = models.CharField(max_length=200)
created = models.DateTimeField(default=timezone.now)
modified = models.DateTimeField(auto_now=True)
class Someotherclass(Someclass):
status = models.IntegerField(default=0,)
name = models.CharField(max_length=200)
created = models.DateTimeField(default=timezone.now)
modified = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User)
forms.py
class SomeotherclassForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request")
self.user = kwargs.pop('user')
self.app = kwargs.pop('app')
self.table = kwargs.pop('table')
self.mytype = kwargs.pop('mytype')
initial = kwargs.get('initial', {})
super(SomeotherclassForm, self).__init__(*args, **kwargs)
create.py
class DataCreate(CreateView):
#method_decorator(login_required)
def dispatch(self, *args, **kwargs):
#some code here not relevant at all
def get_form_kwargs(self):
kwargs = super(DataCreate, self).get_form_kwargs()
objectid = self.request.GET.get('objectid',None)
objecttype = self.request.GET.get('objecttype',None)
kwargs.update({'mytype': objecttype})
kwargs.update({'request': self.request})
kwargs.update({'user': self.request.user})
kwargs.update({'app': self.app})
kwargs.update({'table': self.kwargs['table'].lower()})
return kwargs
def form_valid(self, form):
obj = form.save(commit=False)
group = ''
if not self.request.user.is_superuser:
group = MyUser.objects.get(user_ptr_id=self.request.user.pk)
else:
groups = self.request.user.groups.all()
if self.kwargs['table'] == 'Myprotocol':
obj = form.save(commit=False)
table = eval(self.request.GET.get('objecttype',None).title()).objects.get(pk=int(self.request.GET.get('objectid',None)))
obj.objectid = table.pk
obj.objecttype = table.__class__.__name__.lower()
obj.user_id = self.request.user.pk
obj.save()
else:
obj = form.save()
if self.request.POST.get('is_popup'):
check = int(self.kwargs['is_list'])
if self.kwargs['table'] == 'Someclass':
popup = 1
a = checkPopup2(obj,check,popup,obj.pk)
else:
a = checkPopup(obj,check)
return a
else:
return super(DataCreate, self).form_valid(form)
When I have logged in as a regular user ,everything works fine.
When I log in as a superuser, I get form error that objecttype,objectid and user are not filled.
In my attempts to troubleshoot it , I realized that when I am logged in as a superuser ,it dowsn't reach the form_valid() function.
I can't figure out why that is happening.
Any suggestions or advice on how to troubleshoot it?
I have trouble getting the current instance's fields on my UpdateView. How do I get the specific instance based on its id?
views.py
class ShowUpdate(UpdateView):
model = Show
fields = ['description', 'season', 'episode']
def post(self, request, **kwargs):
request.POST = request.POST.copy()
request.POST['description'] = "how to get instance description?" # problem here
request.POST['season'] = 2
return super(ShowUpdate, self).post(request, **kwargs)
models.py
class Show(models.Model):
owner = models.ForeignKey(User, null=True, default=True, related_name='o')
title = models.CharField(max_length=100)
description = models.TextField(default='N/A', blank=True, max_length=250)
season = models.IntegerField(default=0)
episode = models.IntegerField(default=0)
def get_absolute_url(self):
return reverse('show:index')
def __str__(self):
return self.title
Look to the UpdateView docs
This View has method get_object(self, queryset=None)
In you case just need to call it in POST method something like this:
class ShowUpdate(UpdateView):
model = Show
fields = ['description', 'season', 'episode']
def post(self, request, **kwargs):
self.object = self.get_object()
request.POST = request.POST.copy()
request.POST['description'] = self.object.description
request.POST['season'] = 2
return super(ShowUpdate, self).post(request, **kwargs)
I hava an Article model ,contains a title column,which can be stored mix with white space,what i want is that ,every time i query an article,space in title content could be repaced with dash,for url friendly.
models.py:
class Article(models.Model):
STATUS = (
(0,'on'),
(1,'off')
)
#id = models.IntegerField(primary_key=True,help_text='primary key',auto_created=True)
category = models.ForeignKey(Category,related_name='articles', help_text='foreigner key reference Category')
#author = models.ForeignKey(myadmin.User, help_text='foreigner key reference myadmin User')
title = models.CharField(max_length=100, help_text='article title')
description = models.TextField(help_text='article brief description')
content = models.TextField(help_text='article content')
like = models.IntegerField(default=0,help_text='like numbers')
secretcode = models.CharField(max_length=512,help_text='who has the code can scan')
status = models.IntegerField(choices=STATUS,help_text='status of the article')
createtime = models.DateTimeField(auto_now_add=True,help_text='time that first created')
modifytime = models.DateTimeField(auto_now=True,help_text='time when modified')
articles = models.Manager()
def __str__(self):
return self.title
class Meta:
db_table = 'article'
my view.py:
def get(self,request):
offset = int(request.GET.get('offset', 0))
category = request.GET.get('category')
end = offset+10
articlecatalogs = Article.articles.filter(category__name=category)[offset:end]
i was thinking creating a custom Manager and define a method to transform the data,but the query conditions needed are from request,in here,i don't know how to do it ?can someone help me?
I think you have to use slug filed as well and overwrite your save method for save slug something like this :
class Article(models.Model):
slug = models.SlugField("slug")
category = models.ForeignKey(Category,related_name='articles', help_text='foreigner key reference Category')
-- more fields --
def __str__(self):
return self.title
def get_absolute_url(self):
return self.slug
def save(self, *args, **kwargs):
if not self.slug:
self.slug = self.title.strip(" ").replace(' ','-')
super(Article, self).save(self, *args, **kwargs)
#property
def get_title(self):
""" write python code for remove extra spaces so can can dispay your tile in html and call this method with instance when you want to print title """
return new_title_without_extra_spaces
for details page you can use slug value for get a instance. Hope this would be helpful to you.
I am trying to log the activities during save operation to track all the changes to user model. my approach is as follows.
class User(AbstractUser):
undergrad_college = models.CharField(max_length=20, choices=COLLEGE_CHOICES)
undergrad_degree = models.CharField(max_length=20, choices=COLLEGE_DEGREES)
postgrad_college = models.CharField(max_length=20, choices=COLLEGE_CHOICES)
postgrad_degree = models.CharField(max_length=20, choices=COLLEGE_DEGREES)
currently_working_on = models.TextField()
previous_work_experience = models.TextField()
previous_internship_experience = models.TextField()
def __str__(self):
return self.username
def save(self, *args, **kwargs):
Log(user=User, actions="Updated profile",
extra={"undergrad_college": self.undergrad_college,
"undergrad_degree": self.undergrad_degree,
"postgrad_college": self.postgrad_college,
"postgrad_degree": self.postgrad_degree,
"currently_working_on": self.currently_working_on,
"previous_work_experience": self.previous_work_experience,
"previous_internship_experience": self.previous_internship_experience
})
super(User, self).save(args, **kwargs)
my views are like this for handling the logging.
class ActivityMixin(LoginRequiredMixin):
def get_context_data(self, **kwargs):
context = super(ActivityMixin, self).get_context_data(**kwargs)
context['activities'] = Log.objects.filter(user=self.request.user)
return context
class IndexListView(ActivityMixin, ListView):
template_name = 'pages/home.html'
model = User
I get this error while performing the update action.
Cannot assign "<class 'users.models.User'>": "Log.user" must be a "User" instance.
Update view is as follows
class UserUpdateView(LoginRequiredMixin, UpdateView):
form_class = UserForm
# we already imported User in the view code above, remember?
model = User
# send the user back to their own page after a successful update
def get_success_url(self):
return reverse("users:detail",
kwargs={"username": self.request.user.username})
def get_object(self, **kwargs):
# Only get the User record for the user making the request
return User.objects.get(username=self.request.user.username)
How to assign the User model instance to the Log function. I cant get this working. I am Django newbie.
Looks like pretty straightforward, replace User with self:
Log(user=User, ...
Log(user=self, ...