Can anyone help me to create update view in django? - python

views.py
class DreamHeroView(CreateView):
template_name = 'dream_hero.html'
model = Character
form_class = DreamHeroForm
def get(self, *args, **kwargs):
form = DreamHeroForm()
return render(self.request, 'dream_hero.html', {'form': form})
def post(self, *args, **kwargs):
form = DreamHeroForm(self.request.POST, self.request.FILES or None)
if form.is_valid():
title = form.cleaned_data['title']
description = form.cleaned_data['description']
strenght = form.cleaned_data['strenght']
power = form.cleaned_data['power']
weapon = form.cleaned_data['weapon']
hero_image = form.cleaned_data['hero_image']
slug = form.cleaned_data['slug']
post = Character(
title=title,
description=description,
strenght=strenght,
power=power,
weapon=weapon,
hero_image=hero_image,
slug=slug,
user=self.request.user,
)
post.save()
return redirect('character-post')
return render(self.request, 'dream_hero.html')
views.py
class StoryDetailView(FormMixin, DetailView):
model = Character
template_name = 'story.html'
context_object_name = 'comment_set'
form_class = CharCommentForm
def get_context_data(self, **kwargs):
context = super(StoryDetailView, self).get_context_data(**kwargs)
context['commenting'] = self.object.charactercomment_set.all()
context['pro_pic'] = get_object_or_404(Author, user=self.request.user)
context['charform'] = CharCommentForm()
return context
def get_success_url(self):
return reverse('story-post', kwargs={
'slug': self.object.slug
})
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
form.instance.user = self.request.user
form.instance.post = self.get_object()
form.save()
return super().form_valid(form)
form.py
class DreamHeroForm(forms.Form):
title = forms.CharField(widget=forms.TextInput(attrs={
'class': 'form-control',
'placeholder': 'Name of your hero'
}))
description = forms.CharField(widget=forms.Textarea(attrs={
'class': 'form-control',
'placeholder': 'Story of your Hero'
}))
slug = forms.SlugField()
hero_image = forms.ImageField()
strenght = forms.IntegerField()
power = forms.IntegerField()
weapon = forms.IntegerField()

Django has an UpdateView built in.
from django.views.generic.edit import UpdateView
class MyUpdateView(UpdateView):
model = MyModel
fields = ["field_1", "field_2"] # or use form_class = MyForm
template_name = "myapp/mymodel_update.html"
You'll need a PK in your url for the update view so it can look up the model instance correctly (you can override this by setting lookup_url_kwarg in the class IIRC)
Docs:
https://docs.djangoproject.com/en/3.0/ref/class-based-views/generic-editing/#updateview

Related

How to add comments without authentification required

i just done comments on my website,and i want to do non-authorized comments,and dont know how to.My models looks like this
class Comment(models.Model):
article = models.ForeignKey(Product, on_delete = models.CASCADE, verbose_name='Page', blank = True, null = True,related_name='comments' )
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete = models.CASCADE, verbose_name='Comment author', blank = True, null = True )
create_date = models.DateTimeField(auto_now=True)
text = models.TextField(verbose_name='Comment text', max_length=500)
status = models.BooleanField(verbose_name='Visible', default=False)
and views.py like this
def post(self, request, *args, **kwargs):
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.article = self.get_object()
self.object.author = self.request.user
self.object.save()
return super().form_valid(form)
def post(self, request, *args, **kwargs):
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.article = self.get_object()
if self.request.user.is_authenticated:
self.object.author = self.request.user
else:
self.object.author = None
self.object.save()
return super().form_valid(form)
note: remove else block if you get an error

The view admin panel.views.create category didn't return an HttpResponse object. It returned None instead

I dont know why i am getting this error I am trying build an admin panel.So I am trying to make create category functionality after coding all the functionalities i got stuck in this error
Here is my view.py
def createcategory(request):
if request.method == 'POST':
createcat = CategoryForm(request.POST, request.FILES)
if createcat.is_valid():
cat_name = createcat.cleaned_data['category_name']
cat_image = createcat.cleaned_data['category_image']
insert_cat = CategoryModel(
category_name=cat_name, category_image=cat_image)
insert_cat.save()
create2 = CategoryForm()
return render(request, 'createcat.html', {'create2': createcat})
else:
createcat = CategoryForm()
all_categories = CategoryModel.object.all()
return render(request, 'index.html')
Here is my models.py
class CategoryModel(models.Model):
category_id = models.AutoField(primary_key=True)
category_name = models.CharField(max_length=100)
category_image = models.ImageField(upload_to='images/')
I am giving the category model I created in the code example below as an example. Which model category you create is very important.
You also need to save the model you created in admin.py.
models.py
class Category(models.Model):
title = models.CharField(max_length=150)
slug = models.SlugField(editable=False)
def __str__(self):
return self.title
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Category, self).save(*args, **kwargs)
def task_count(self):
return self.task.count()
class Task(models.Model):
user = models.ForeignKey("auth.User", on_delete=models.CASCADE, verbose_name='TaskUser') # user
title = models.CharField(max_length=150, verbose_name='Task Title')
content = RichTextField()
created_date = models.DateTimeField(auto_now_add=True, verbose_name='Task Date')
slug = models.SlugField(editable=False)
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name="task")
def __str__(self):
return self.title
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Task, self).save(*args, **kwargs)
As you can see I add a category field in the task model.
views.py
class IndexView(ListView):
template_name = 'task/index.html'
model = Task
context_object_name = 'task'
# paginate_by = 7
def get_context_data(self, *, object_list=None, **kwargs):
context = super(IndexView, self).get_context_data(**kwargs)
return context
class CategoryDetail(ListView):
model = Task
template_name = 'category/category_detail.html'
context_object_name = 'task'
# paginate_by = 3
def get_queryset(self):
self.category = get_object_or_404(Category,
pk=self.kwargs['pk'])
return Task.objects.filter(category=self.category).order_by('-id')
def get_context_data(self, *, object_list=None, **kwargs):
context = super(CategoryDetail, self).get_context_data(**kwargs)
self.category = get_object_or_404(Category, pk=self.kwargs['pk'])
# context['category'] = self.category
return context
Finally, I am registering in admin.py.
admin.py
admin.site.register(Task)
admin.site.register(Category)
I hope it helped.
You only return at one condition, if it's at POST, else you don't. so please add a default return at the end.
just like:
if `POST`:
...
return render(request, 'createcat.html', {'create2': createcat})
else:
return render(request, 'default.html')
PS: using the below code format indention:
def createcategory(request):
if request.method == 'POST':
createcat = CategoryForm(request.POST, request.FILES)
if createcat.is_valid():
cat_name = createcat.cleaned_data['category_name']
cat_image = createcat.cleaned_data['category_image']
insert_cat = CategoryModel(
category_name=cat_name, category_image=cat_image)
insert_cat.save()
create2 = CategoryForm()
return render(request, 'createcat.html', {'create2': createcat})
else:
createcat = CategoryForm()
all_categories = CategoryModel.object.all()
return render(request, 'index.html')
# print("test")
PS2: Want to show form.
def createcategory(request):
createcat = CategoryForm(request.POST, request.FILES) # put your form here
if request.method == 'POST':
if createcat.is_valid():
cat_name = createcat.cleaned_data['category_name']
cat_image = createcat.cleaned_data['category_image']
insert_cat = CategoryModel(
category_name=cat_name, category_image=cat_image)
insert_cat.save()
create2 = CategoryForm()
return render(request, 'createcat.html', {'create2': createcat})
all_categories = CategoryModel.object.all() # make sure you know this line.
return render(request, 'index.html', createcat) # put your empty form here

How can I convert my class-based view to function-based views? - Django

I am trying to change all my class-based views to function-based views and I am having difficulty converting the following class:
class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, SuccessMessageMixin, UpdateView):
model = Post
fields = ['image', 'title', 'category', status', 'description']
template_name = 'blog/post-form.html'
success_message = 'Your post has been updated.'
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
return False
def get_context_data(self, **kwargs):
context = super(PostUpdateView, self).get_context_data(**kwargs)
context['title'] = 'Update post'
context['submit'] = 'Update'
return context
def get_success_url(self):
author = self.object.author
return reverse_lazy( 'profile', kwargs={'author': author.username})
The function and form should do exactly what this class-based view does, so if anyone can help me out, please let me know.
You can specify a .form_class attribute [Django-doc] in an UpdateView (as well as in a CreateView). So we can create a form like:
# app/forms.py
from django import forms
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['image', 'title', 'category', 'status', 'description']
widgets = {
'image': …
}
Where you replace … with the widget you want to use for the image field.
Then you can plug in that form:
# app/views.py
from app.forms import PostForm
class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, SuccessMessageMixin, UpdateView):
model = Post
form_class = PostForm
template_name = 'blog/post-form.html'
success_message = 'Your post has been updated.'
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
return False
def get_context_data(self, **kwargs):
context = super(PostUpdateView, self).get_context_data(**kwargs)
context['title'] = 'Update post'
context['submit'] = 'Update'
return context
def get_success_url(self):
author = self.object.author
return reverse_lazy( 'profile', kwargs={'author': author.username})
Behind the curtains, if you do not specify a form_class, Django will simply make one for you with the modelform_factory [Django-doc], so by using another ModelForm, we do not change the logic of using the form.

Post comment inside Django DetailView

I need to add comments in article page. Post request receives data but not saves it.
In models.py:
class TemporaryComment(models.Model):
article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='temporary_comment')
email = models.EmailField()
message = models.TextField(max_length=1500)
timestamp = models.DateTimeField(auto_now_add=True)
is_approved = models.BooleanField(default=True)
In forms.py:
class CommentModelForm(forms.ModelForm):
class Meta:
model = TemporaryComment
fields = [
'article',
'email',
'message',
]
in views.py:
class ArticleDetailView(FormMixin, DetailView):
model = Article
template_name = 'article.html'
form_class = CommentModelForm
def get_success_url(self):
return reverse_lazy('main:article', kwargs={'pk': self.object.pk})
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['last_articles'] = Article.objects.filter(is_active=True).order_by('-timestamp')[:10]
context['comments'] = self.object.temporary_comment.filter(is_approved=True)
context['form'] = self.get_form()
return context
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
form.save()
return super().form_valid(form)
If i comment out article field in forms.py, i got this error:
null value in column "article_id" violates not-null
constraint. DETAIL: Failing row
contains (18, username#email.com, check message, 2019-01-20 18:35:36.615955+00, t, null).
Help will be gladly accepted. Thanks for your time.
You should comment it out, and set it in form_valid.
def form_valid(self, form):
form.instance.article = self.object
form.save()
return super().form_valid(form)

formset validation in CBV

I have an Order form where I used formsets because I want the user to dynamically add more products and their quantity.
The user enters the name of the order, and it is validated not to be empty.
How do I validate the formset itself? to check that the product/quantity is not empty
views.py
class OrderCreateView(CreateView):
model = Order
template_name = "orderform.html"
fields = ['name', ]
def get_context_data(self, **kwargs):
data = super(OrderCreateView, self).get_context_data(**kwargs)
if self.request.POST:
data['productmetas'] = InlineOrderFormSet(self.request.POST)
return data
def form_valid(self, form):
context = self.get_context_data()
productmetas = context['productmetas']
self.object = form.save(commit=False)
self.object.save()
if productmetas.is_valid():
productmetas.instance = self.object
productmetas.save()
return super(OrderCreateView, self).form_valid(form)
models.py
class ProductMeta(models.Model):
order = models.ForeignKey(Order)
product = models.ForeignKey(Product)
quantity = models.FloatField()
forms.py
InlineOrderFormSet = inlineformset_factory(Order, ProductMeta,
form=OrderAutoCompleteForm,
extra=1)
For anyone interested in the working solution for the question above
adapted from the answer by #neverwalkaloner
def form_valid(self, form):
context = self.get_context_data()
productmetas = context['productmetas']
with transaction.atomic():
self.object = form.save()
if form.is_valid():
if productmetas.is_valid():
productmetas.instance = self.object
productmetas.save()
else:
return super(OrderCreateView, self).form_invalid(form)
return super(OrderCreateView, self).form_valid(form)

Categories