I am new in Django and Stackoverflow, so please accept my apology if my codes is not standard.
I try to create a blogging website. Users can create and update posts and each post can have one or more categories or no category. I use form for Post and Formset for Category. However, in Updateview for some reason I couldnt save the formset!!!!
models.py
class Post(models.Model):
title = models.CharField(max_length=128)
text = models.TextField(blank=True)
author = models.ForeignKey(User, on_delete=models.CASCADE)
created_date = models.DateTimeField(auto_now_add=True)
modified_date = models.DateTimeField(auto_now=True)
published_date = models.DateTimeField(blank=True, null=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
class Category(models.Model):
name = models.CharField(max_length=128, unique=True)
description = models.TextField(blank=True)
posts = models.ManyToManyField(Post,
blank=True,related_name='categories')
class Meta:
verbose_name_plural = 'Categories'
def __str__(self):
return self.name
forms.py
from django import forms
from blogging.models import Post, Category
class PostUpdateForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'text', 'published_date']
CATEGORY_CHOICES = [('', 'Choose from the list')]
for c in Category.objects.all():
CATEGORY_CHOICES.append((c, c))
class CategoryUpdateForm(forms.ModelForm):
class Meta:
model = Category
fields = ['name']
labels = {'name': 'Category'}
help_texts = {'name': 'Choose category for your post'}
widgets = {
'name': forms.Select(choices=CATEGORY_CHOICES)
}
CategoryFormset = forms.modelformset_factory(Category,
form=CategoryUpdateForm, extra=1,
max_num=3, can_delete=True)
views.py
from blogging.models import Post, Category
from blogging.forms import PostUpdateForm, CategoryFormset
class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Post
template_name = 'blogging/post_update.html'
form_class = PostUpdateForm
formset_class = CategoryFormset
def form_valid(self, form):
form.instance.author = self.request.user
context = self.get_context_data()
formset = context['formset']
if formset.is_valid():
category_form = formset.save(commit=False)
category_form.posts.add(self.get_object())
category_form.save()
formset.save()
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().get_context_data(**kwargs)
post = self.get_object()
if self.request.POST:
context['formset'] = self.formset_class(self.request.POST)
else:
context['formset'] =
self.formset_class(queryset=post.categories.all())
return context
template
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Profile Info</legend>
{{ u_form | crispy }}
{{ p_form | crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info"
type="submit">Update</button>
</div>
</form>
I could find the answer. By using extra-view package and use the CreateInlineView, and UpdateInlineView all can be solved. https://django-extra-views.readthedocs.io/en/latest/
Related
I have two models with foreign key relation
models.py
from django.db import models
# Create your models here.
class Project(models.Model):
STATUSES = (
('Ongoing', 'Ongoing'),
('Completed', 'Completed')
)
YEARS = (
(2019, 2019),
(2020, 2020),
(2021, 2021),
(2022, 2022)
)
name = models.CharField(max_length=200)
client = models.CharField(max_length=100)
year = models.SmallIntegerField(choices=YEARS)
status = models.CharField(max_length=10, choices=STATUSES)
picture = models.ImageField(blank=True, null=True)
description = models.TextField(blank=True, null=True)
def __str__(self):
return self.name
class Photo(models.Model):
project = models.ForeignKey("Project", on_delete=models.CASCADE, related_name="images", blank=True, null=True)
image = models.ImageField()
description = models.CharField(max_length=100, blank=True, null=True)
slide = models.BooleanField(default=False)
I want photos and project to be created on the same form so I've used inline_formset_factory
forms.py
from django.forms import inlineformset_factory
from projects.models import Photo, Project
from django.forms import ModelForm
class ProjectModelForm(ModelForm):
class Meta:
model = Project
fields = (
'name',
'client',
'year',
'picture',
'status',
'description',
)
class PhotoModelForm(ModelForm):
class Meta:
model = Photo
fields = (
'image',
'slide',
'description'
)
PhotoFormset = inlineformset_factory(Project, Photo, form=PhotoModelForm, extra=1)
I used the generic CreateView
views.py
from django.contrib.auth.mixins import LoginRequiredMixin
from projects.forms import PhotoFormset, ProjectModelForm
from django.shortcuts import redirect, reverse, render
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from .models import Photo, Project
# Create your views here.
class ProjectCreateView(LoginRequiredMixin, CreateView):
template_name = 'projects/project_create.html'
form_class = ProjectModelForm
def get_context_data(self, **kwargs):
context = super(ProjectCreateView, self).get_context_data(**kwargs)
context['photos_formset'] = PhotoFormset()
return context
def post(self, request, *args, **kwargs):
self.object = None
form_class = self.get_form_class()
form = self.get_form(form_class)
photo_formset = PhotoFormset(self.request.POST)
if form.is_valid() and photo_formset.is_valid():
return self.form_valid(form, photo_formset)
else:
return self.form_invalid(form, photo_formset)
def form_valid(self, form, photo_formset):
self.object = form.save(commit=False)
self.object.save()
print('valid')
photos = photo_formset.save(commit=False)
for photo in photos:
photo.project = self.object
photo.save()
return reverse('projects:projectspage')
def form_invalid(self, form, photo_formset):
if not photo_formset.is_valid():
print('invalid formset')
return self.render_to_response(
self.get_context_data(form=form, photos_formset=photo_formset)
)
def get_success_url(self):
return reverse('projects:projectspage')
this is the template
{% extends 'base.html' %}
{% load crispy_forms_filters %}
<!-- crispy_forms_tags -->
{% block content %}
<div class="container">
<h2>create new project</h2>
<form method="post">
{% csrf_token %}
{{ form|crispy }}
<h2 class="display-6 my-5">
Add photos
</h2>
{{ photos_formset.as_p }}
<input type="submit" value="Create" class="btn btn-primary">
</form>
</div>
{% endblock content %}
When I submit form_invalid is returned from the post method of the view
How do i get the inline_formset to validate or is there better way of doing it
I prefer to write those views as functions, seems more straightforward, try:
#login_required
def post_news(request):
if request.method == 'POST':
project_form = ProjectModelForm(request.POST, request.FILES)
photo_form = PhotoModelForm(request.POST, request.FILES)
picture = request.FILES['picture']
image = request.FILES['image']
if project_form.is_valid() and photo_form.is_valid():
project_instance = project_form.save(commit=False)
project_instance.picture = picture
project_instance.save()
photo_instance = project_form.save(commit=False)
photo_instance.project = project_instance
photo_instance.image = image
photo_instance.save()
return reverse('projects:projectspage')
else:
project_form = ProjectModelForm()
photo_form = PhotoModelForm()
return render(request, 'projects/project_create.html',
{'project_form': project_form, 'photo_form': photo_form})
You will have to account for a case when no picture for the project model is is provided I think. Just pop both forms into your template and this should work.
I want to create a DetailView page which displays the detail of a model but I want to add a Comment section in the DetailView page using ModelFormMixin.
This is my views.py code:
class PostDetailView(ModelFormMixin, DetailView):
model = UserPost
context_object_name='post_detail'
form_class = UserCommentForm
def get_context_data(self, *args, **kwargs):
context = super(PostDetailView, self).get_context_data(*args, **kwargs)
context['form'] = self.get_form()
return context
def get_absolute_url(self):
return reverse(request, 'basic_app:post_detail', kwargs={'pk':self.pk})
But when I hit the submit button it shows the following error:
Edited part:
This is my views.py file
model.py
forms.py
userpost_detail.html
browser image before clicking enter button
browser image after clicking enter button
django admin page
I'm sorry for not uploading the actual code because it was too difficult to upload that bulk of code.
I think the following code will help you. I code it a long time ago, but it seems to solve your problem (I didn't use taggit, so I created a PostTag model):
Models:
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils.timezone import localtime
from django.urls import reverse
class User(AbstractUser):
pass
class PublishedManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(status='published')
class PostTag(models.Model):
name = models.CharField(max_length=40)
slug = models.SlugField(max_length=40)
def __str__(self):
return self.name
class Post(models.Model):
POST_STATUS = (('draft', 'Draft'), ('published', 'Published'))
title = models.CharField(max_length=100)
body = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name='blog_posts')
created = models.DateTimeField(auto_now_add=True)
publish = models.DateTimeField(auto_now=True)
updated = models.DateTimeField(auto_now=True)
slug = models.SlugField(max_length=100, unique_for_date='publish')
status = models.CharField(max_length=10, choices=POST_STATUS, default='draft')
tags = models.ManyToManyField(PostTag, blank=True)
def get_absolute_url(self):
local_time = localtime(self.publish)
return reverse("blog:post_date_detail", args=[local_time.year, local_time.month, local_time.day, self.slug])
class Meta:
ordering = ('-publish',)
def __str__(self):
return self.title
objects = models.Manager() # The default manager.
published = PublishedManager() # Custom manager.
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
name = models.CharField(max_length=80)
email = models.EmailField()
body = models.TextField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=True)
def get_absolute_url(self):
local_time = localtime(self.post.publish)
return reverse("blog:post_date_detail", args=[local_time.year, local_time.month, local_time.day, self.post.slug])
class Meta:
ordering = ('created',)
def __str__(self):
return f'Comment by {self.name} on {self.post}'
Views:
from django.shortcuts import render, get_object_or_404, HttpResponseRedirect
from django.views.generic import ListView, DetailView, View
from django.views.generic.edit import FormView, SingleObjectMixin, CreateView
from django.views.generic.dates import YearArchiveView, MonthArchiveView, DateDetailView
from django.core.mail import send_mail
from django.db.models import Count
from .models import Post, User, Comment, PostTag
from .forms import EmailPostForm, CommentForm
class PostListView(ListView):
queryset = Post.published.all()
context_object_name = 'posts'
paginate_by = 4
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# si hay kwargs se actualiza el context
if self.kwargs:
context["tag"] = self.kwargs['tag_slug']
return context
def get_queryset(self):
tag = None
if self.kwargs:
tag_slug = self.kwargs['tag_slug']
tag = get_object_or_404(PostTag, slug=tag_slug)
posts = self.queryset.filter(tags__in=[tag])
return posts
return self.queryset
class PostYearArchiveView(YearArchiveView):
queryset = Post.published.all()
template_name = 'blog/post_list.html'
date_field = "publish"
context_object_name = 'posts'
make_object_list = True
paginate_by = 4
class PostMonthArchiveView(MonthArchiveView):
queryset = Post.published.all()
template_name = 'blog/post_list.html'
date_field = "publish"
context_object_name = 'posts'
month_format='%m'
paginate_by = 4
class PostDateDetailView(DateDetailView):
queryset = Post.published.all()
date_field = "publish"
month_format='%m'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
obj = self.get_object()
post_tags_pks = obj.tags.all().values_list('pk', flat=True)
related_posts = self.queryset.filter(tags__in=post_tags_pks).exclude(pk=obj.pk)
related_posts = related_posts.annotate(same_tags=Count('tags')).order_by('-same_tags','-publish')[:3]
context["related_posts"] = related_posts
comments = obj.comments.filter(active=True)
context["comments"] = comments
context['post_id'] = obj.pk
context['form'] = CommentForm()
return context
class NewComment(CreateView):
model = Comment
template_name = 'blog/post_detail.html'
form_class = CommentForm
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
post = context["form"].instance.post
context['post'] = post
post_tags_pks = post.tags.all().values_list('pk', flat=True)
related_posts = Post.published.filter(tags__in=post_tags_pks).exclude(pk=post.pk)
related_posts = related_posts.annotate(same_tags=Count('tags')).order_by('-same_tags','-publish')[:3]
context["related_posts"] = related_posts
comments = post.comments.filter(active=True)
context["comments"] = comments
return context
class PostDetail(View):
def get(self, request, *args, **kwargs):
view = PostDateDetailView.as_view()
return view(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
view = NewComment.as_view()
return view(request, *args, **kwargs)
class SharePostView(SingleObjectMixin, FormView):
form_class = EmailPostForm
template_name = 'blog/post_share.html'
success_url = '/blog'
context_object_name = 'posts'
queryset = Post.published.all()
def get(self, request, *args, **kwargs):
post = self.get_object()
context = {'post': post, 'form': self.form_class}
return render(request, self.template_name, context)
def form_valid(self, form):
post = self.get_object()
post_url = self.request.build_absolute_uri(post.get_absolute_url())
form.send_mail(post, post_url)
return super(SharePostView, self).form_valid(form)
Considerations: See get_context_data to add other data to the context: in this case tags, related_post, the form, etc...
I have used 3 views. DateDetailView (similar to your DetailView) to display the page (with the context needed).
CreateView to manage the POST method and save the comment into the DB. I have also added context to get the post information.
Finally a View with the intention of managing the same URL,but calling the appropiate view
when the request is GET or POST. See urls.py
URLS:
from django.urls import path
from blog import views
from blog.models import Post
app_name = 'blog'
urlpatterns = [
path("", views.PostListView.as_view(), name="post_list"),
path('tag/<slug:tag_slug>/', views.PostListView.as_view(), name='post_list_by_tag'),
path('<int:year>/', views.PostYearArchiveView.as_view(), name="post_year_archive"),
path('<int:year>/<int:month>/', views.PostMonthArchiveView.as_view(), name="post_month_numeric"),
path('<int:year>/<int:month>/<int:day>/<slug:slug>/', views.PostDetail.as_view(), name="post_date_detail"),
path('<int:pk>/share/', views.SharePostView.as_view(), name='post_share'),
]
Comment form:
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('name', 'email', 'body', 'post')
widgets = {
'name': forms.TextInput(attrs={'placeholder': 'Name'}),
'email': forms.EmailInput(attrs={'placeholder': 'E-mail'}),
'body': forms.Textarea(attrs={'placeholder': 'Write your message here'}),
'post' : forms.HiddenInput(),
}
form in template:
<form method="post" action="" novalidate>
{% csrf_token %}
<div class="input-group input-group-icon">
{{ form.name }}
<div class="input-icon"><i class="fas fa-user"></i></div>
{% if form.name.errors %}
{{form.name.errors}}
{% endif %}
</div>
<div class="input-group input-group-icon">
{{form.email }}
<div class="input-icon">
<i class="fas fa-envelope"></i>
</div>
{% if form.email.errors %}
{{form.email.errors}}
{% endif %}
</div>
<div class="msg">
<div class="input-group">{{form.body}}
{% if form.body.errors %}
{{form.body.errors}}
{% endif %}
</div>
</div>
<input type="hidden" name="post" value="{{ post.pk }}">
<div class="input-group send-reset">
<input type="submit" value="Enviar Comentario" />
</div>
</form>
Considerations: See the input type=hidden to get the post.pk. This is needed to save the comment.post field.
I think I covered all the issues you can have. Hope it helps!!
I'm trying to upload file in a specific folder and store its path in DB through forms(CBV), but it doesn't work!!
this is my code (forms, models, views, template).
I'm selecting the file through forms then I submit the form, but it doesn't submit.
#views.py
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
# fields = ['title', 'content']
success_url = reverse_lazy('blog/new_post.html')
template_name = 'blog/new_post.html'
form_class = PostCreateForm
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect(self.success_url)
else:
return render(request, self.template_name, {'form': form})
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
#model.py
class Post(models.Model):
title = models.CharField(max_length=1000)
content = models.TextField()
xml_file = models.FileField(null=True, upload_to='xml_files')
rate = models.FloatField(null=True, blank=True, default=None)
post_date = models.DateTimeField(default=timezone.now)
post_update = models.DateTimeField(auto_now=True)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
def get_absolute_url(self):
# return '/detail/{}'.format(self.pk)
return reverse('detail', args=[self.pk])
class Meta:
ordering = ('-post_date', )
#forms.py
class PostCreateForm(forms.ModelForm):
title = forms.CharField( max_length=1000)
content = forms.CharField(widget=forms.Textarea(
attrs={'rows': 15, 'placeholder': 'write here'}
), max_length=50000)
xml_file = forms.FileField(label='upload file')
class Meta:
model = Post
fields = ['title', 'content', 'xml_file', ]
#new_post.html
{% block content %}
{% load crispy_forms_tags %}
<div class="border p-4 mb-5">
<legend class="border-bottom pb-1 mb-3">new post</legend>
<form method="POST">
{% csrf_token %}
{{form|crispy}}
<input class="btn btn-secondary mt-4" type="submit" value="post">
</form>
</div>
{% endblock content %}
When you are uploading media like what you've got, it is necessary to add the following part to your <form>:
enctype=multipart/form-data
I want to show comments unique to the blog post on each blog post but when I click submit on the comment posting form it throws an error saying
IntegrityError at /post/6/comment/
NOT NULL constraint failed: blog_postcomment.Post_id
I add comments in the database manually but it doesn't show on my page.
HTML
{% block content %}
<div class="container">
<div class="row">
<div class="col-md-8 card mb-4 mt-3 left top">
<div class="card-body">
{% if comment_list %}
<h2 class="post-title">Comments</h2>
{% for comment in blog_postcomment.post %}
<p class=" text-muted">{{ comment.author }} | {{ comment.post_date }}</p>
<p class="card-text ">{{ comment.description | safe }}</p>
{% endfor %}
{% endif %}
</div>
</div>
</div>
</div>
{% block content %}
model
class PostAuthor(models.Model):
user = models.OneToOneField(User, on_delete=models.SET_NULL, null=True)
bio = models.TextField(max_length=400, help_text="Enter your bio details here.")
class Meta:
ordering = ["user", "bio"]
def get_absolute_url(self):
return reverse('post-by-author', args=[str(self.id)])
def __str__(self):
return self.user.username
class Post(models.Model):
title = models.CharField(max_length=200, unique=False)
slug = models.SlugField(max_length=200, null=True, blank=True)
author = models.ForeignKey(PostAuthor, on_delete=models.CASCADE, null=True, blank=True)
updated_on = models.DateTimeField(auto_now=True)
content = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=STATUS, default=0)
class Meta:
ordering = ['-created_on']
def get_absolute_url(self):
return reverse('post-detail', args=[str(self.id)])
def __str__(self):
return self.title
class PostComment(models.Model):
description = models.TextField(max_length=1000, help_text="Enter your comment here.")
author = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
post_date = models.DateTimeField(auto_now_add=True)
Post = models.ForeignKey(Post, on_delete=models.CASCADE)
class Meta:
ordering = ["post_date"]
def __str__(self):
len_title = 75
if len(self.description) > len_title:
titlestring = self.description[:len_title] + '...'
else:
titlestring = self.description
return titlestring
View
class PostListbyAuthorView(generic.ListView):
model = Post
template_name = 'blog/post_list_by_author.html'
def get_queryset(self):
id = self.kwargs['pk']
target_author = get_object_or_404(PostAuthor, pk=id)
return Post.objects.filter(author=target_author)
def get_context_data(self, **kwargs):
context = super(PostListbyAuthorView, self).get_context_data(**kwargs)
context['post'] = get_object_or_404(PostAuthor, pk=self.kwargs['pk'])
return context
class IndexPage(generic.ListView):
queryset = Post.objects.filter(status=1).order_by('-created_on')
template_name = 'blog/index.html'
class PostList(generic.ListView):
queryset = Post.objects.filter(status=1).order_by('-created_on')
template_name = 'blog/all_posts.html'
class PostDetail(generic.DetailView):
model = Post
template_name = 'blog/post_detail.html'
class PostCreate(CreateView):
model = Post
fields = '__all__'
template_name = 'blog/post_form.html'
class PostUpdate(UpdateView):
model = Post
fields = ['content', 'title']
template_name = 'blog/edit_post.html'
class PostComment(LoginRequiredMixin, CreateView):
model = PostComment
fields = ['description', ]
template_name = 'blog/comment_form.html'
def get_context_data(self, **kwargs):
context = super(PostComment, self).get_context_data(**kwargs)
context['post'] = get_object_or_404(Post, pk=self.kwargs['pk'])
return context
def form_valid(self, form):
form.instance.author = self.request.user
form.instance.post = get_object_or_404(Post, pk=self.kwargs['pk'])
return super(PostComment, self).form_valid(form)
def get_success_url(self):
return reverse('post-detail', kwargs={'pk': self.kwargs['pk'], })
urlpatterns = [
path('', views.IndexPage.as_view(), name='index'),
path('posts/', views.PostList.as_view(), name='all-posts'),
path('post/detail/<int:pk>', views.PostListbyAuthorView.as_view(), name='post-by-author'),
path('post/author/<int:pk>', views.PostDetail.as_view(), name='post-detail'),
path('post/create/', views.PostCreate.as_view(), name='post-create'),
path('post/<int:pk>/edit/', views.PostUpdate.as_view(), name='post-edit'),
path('post/<int:pk>/comment/', views.PostComment.as_view(), name='post-comment'),
path('accounts/', include('django.contrib.auth.urls')),
]
first problem:
different case of first letter in post
here: Post = models.ForeignKey(...)
and here: form.instance.post = get_object_or_404(...)
I am trying to build a sample website based on Django(GeoDjango) and OpenStreetMap. So far I have this simple scenario:
Models.py
class Parks(models.Model):
park_name_en = models.CharField(max_length=256)
description = models.TextField()
picture = models.ImageField()
geom = PolygonField()
#property
def picture_url(self):
return self.picture.url
def __unicode__(self):
return self.title
views.py
def park_insert(request):
form = ParkForm()
return render(request, 'addpark.html', {'form': form})
forms.py
class ParkForm(forms.ModelForm):
class Meta:
model = Parks
fields = ('park_name_en', 'description', 'picture',)
geom = forms.PolygonField()
and last but not least the template addpark.html
<html>
<head>
{{ form.media }}
</head>
<body>
<div id="map">
<form enctype="multipart/form-data" method="post" action="">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit"/>
</form>
</div>
</body></html>
When I open the template page all fields come up right, except the PolygonField() which comes up as a text. How can I display a map on the user form also (I got it working in the admin panel, but I want to create a form for inserting new parks)
You need to describe "forms " models.py.
Models.py
from django.contrib.gis import forms
class Parks(models.Model):
park_name_en = models.CharField(max_length=256)
description = models.TextField()
picture = models.ImageField()
geom = models.PointField(widget= forms.OSMWidget(attrs={'map_width': 800, 'map_height': 500}) )
#property
def picture_url(self):
return self.picture.url
def __unicode__(self):
return self.title
views.py
def park_insert(request):
form = ParkForm()
return render(request, 'addpark.html', {'form': form})
forms.py
class ParkForm(forms.ModelForm):
class Meta:
model = Parks
fields = ('park_name_en', 'description', 'picture',)
geom = forms.PolygonField()
Try it. And looked this
https://docs.djangoproject.com/en/2.2/ref/contrib/gis/forms-api/#widget-classes
I added widget in forms.py because adding this attribute in model causes exception.
forms.py
from django.contrib.gis import forms
from .models import Memory
class AddMemoryForm(forms.Form, forms.ModelForm):
class Meta:
model = Memory
fields = ['title', 'description', 'location']
widgets = {
'title': forms.TextInput(attrs={'class': 'form-input'}),
'description': forms.Textarea(attrs={'cols': 60, 'rows': 10}),
'location': forms.OSMWidget
}
views.py
class ShowMemory(LoginRequiredMixin, UpdateView):
template_name = 'world/detail_memory.html'
model = Memory
form_class = UpdateMemoryForm
def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = context['memory']
return context
def get_success_url(self):
return reverse_lazy('memory')
def form_valid(self, form):
form.instance.user = self.request.user
return super().form_valid(form)
UpdateMemoryForm is the similar to AddMemoryForm