error I have exactly the same structure for updating forum's posts, so they do work, but the article's ones don't. My article_update_form template simple does not receive any data from the view and therefore the slug is empty.
model
class ArticlePost(models.Model):
title = models.CharField(max_length=400)
slug = models.CharField(max_length=400, unique=True, blank=True)
article_users = models.ForeignKey(Author, on_delete=models.CASCADE, related_name="article_users")
content = models.TextField()
categories = models.ManyToManyField(ArticleCategory)
date = models.DateTimeField(auto_now_add=True)
approved = models.BooleanField(default=False)
hit_count_generic = GenericRelation(HitCount, object_id_field="object_pk",
related_query_name="hit_count_generic_relation")
article_tags = TaggableManager(related_name="article_tags")
article_image = models.ImageField(null=True, blank=True, upload_to="article_images/")
def __str__(self) -> str:
return self.title
@property
def length(self) -> int:
return len(self.content)
@property
def get_category(self):
return [v for v in self.categories.all()]
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
super(ArticlePost, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse("article_details", kwargs={
"slug": self.slug
})
My UpdateView
class ArticlePostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = ArticlePost
template_name = 'articles/article_form_update.html'
form_class = ArticlePostForm
def form_valid(self, form):
form.instance.author = self.request.user
messages.success(self.request, 'The article has been updated')
return super().form_valid(form)
def test_func(self):
post = self.get_object()
if self.request.user.id == post.article_users.user.id:
return True
return False
urls:
urlpatterns = [
path("posts/<slug>/", articles, name="articles"),
path('<int:page_id>', pages.views.articles, name='page'),
path("detail/<slug>/", detail, name="article_details"),
path("new_article", new_article, name="new_article"),
path("new_article/create_post", login_required(ArticlePostCreateView.as_view()), name="create_article"),
path("post/<slug:slug>/update/", ArticlePostUpdateView.as_view(), name="update_post_article"),
path('categories_list', categories_list, name="categories_list"),
path("search_article_post", search_article_post, name="search_article_post"),
path("category/<slug>/", category_articles, name="category_articles"),
path("sort_by/<str:typesort>", articles_sort, name="articles_sort"),
]
forms:
class ArticlePostForm(forms.ModelForm):
class Meta:
model = ArticlePost
fields = ("title", "categories", "content", "article_tags", 'article_image')
exclude = ["article_users"]
widget = {
'title': forms.TextInput(attrs={'class': 'form-control'}),
'content': forms.TextInput(attrs={'class': 'form-control'}),
'categories': forms.Select(attrs={'class': 'form-control'}),
'article_tags': forms.Select(attrs={'class': 'form-control'}),
'article_image': forms.Select(attrs={'class': 'form-control'}),
}
def __setitem__(self, i, elem):
self.list[i] = elem
form template:
<div class="form-group">
<form method="POST" action="{% url 'update_post_article' slug=post.slug %}">
{% csrf_token %}
<div class="centered_create_post">
{% render_field form.title placeholder="Enter title" class+="form-control each_post_create" %}
{% render_field form.content placeholder="Enter content" class+="form-control each_post_create pst_create_categories " %}
{% render_field form.categories class+="form-control each_post_create pst_create_categories " %}
{% render_field form.article_image class+="form-control each_post_create" %}
<div class="pull-left"><button type="submit" class="btn_create_post">Update Post</button></div>
</div>
<div class="clearfix"></div>
</div>
<div class="clearfix"></div>
</div>
</form>
</div>
When I tried to use get_context_data, I could send the post manually to the form template but the form does not render any of the widgets from the forms.py.
You should change:
To: