使用createview和modelform在django中自动将登录用户设置为作者 [英] Automatically set logged-in user as the author in django using createview and modelform
问题描述
我正在构建一个前端表单,该表单允许某人无需访问管理员即可发布文章。
I am building a frontend form that allows someone to post an article without accessing the admin.
用户登录后,我希望他/她才能写一篇文章。保存后,我希望该用户自动设置为该文章的作者。
When the user is logged in, I would like for him/her to be able to write an article. Upon saving, I would like that user to automatically be set as the author of the article.
我陷入了僵局。
models.py
models.py
from django.db import models
from django.urls import reverse
from django.contrib.auth.models import User
from django.utils import timezone
class Article(models.Model):
author = models.ForeignKey(User)
title = models.CharField(max_length=65)
text = HTMLField()
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.title
class ArticleImage(models.Model):
image = CloudinaryField('image')
image_name = models.CharField(max_length=55,
default='')
article = models.ForeignKey(Article)
def __str__(self):
return self.image_name
class ArticleTag(models.Model):
slug = models.SlugField(max_length=50,
unique=True)
article = models.ForeignKey(Article)
def __str__(self):
return self.slug
class ArticleCategory(models.Model):
slug = models.SlugField(max_length=20,
unique=True)
article = models.ForeignKey(Article)
def __str__(self):
return self.slug
forms.py
class ArticleCreationForm(ModelForm):
class Meta:
model = Article
fields = ['title', 'text']
widgets = {
'title': forms.TextInput(attrs={'placeholder': 'Please add a title. Max: 65 characters'}),
'text': forms.Textarea(attrs={'cols': 80, 'rows': 40, 'placeholder': 'Starting typing your article...'})
}
ArticleImageFormSet = inlineformset_factory(Article, ArticleImage,
fields=('image', 'image_name',),
extra=1,
max_num=1,
widgets={'image_name':
forms.TextInput(attrs={'placeholder': 'Image name'})})
ArticleTagFormSet = inlineformset_factory(Article, ArticleTag,
fields=('slug',),
extra=1,
max_num=1)
ArticleCategoryFormSet = inlineformset_factory(Article, ArticleCategory,
fields=('slug',),
extra=1,
max_num=1)
views.py
class CreateArticle(CreateView):
model = Article
form_class = ArticleCreationForm
template_name_suffix = '_add_form'
def get_success_url(self):
return reverse('accounts:detail', kwargs={'pk': self.object.pk})
def get(self, request, *args, **kwargs):
"""
Handles GET requests and instantiates blank versions of the form
and its inline formsets.
"""
self.object = None
form_class = self.get_form_class()
form = self.get_form(form_class)
articleimage_form = ArticleImageFormSet()
articletag_form = ArticleTagFormSet()
articlecategory_form = ArticleCategoryFormSet()
return self.render_to_response(
self.get_context_data(form=form,
articleimage_form=articleimage_form,
articletag_form=articletag_form,
articlecategory_form=articlecategory_form))
def post(self, request, *args, **kwargs):
"""
Handles POST requests, instantiating a form instance and its inline
formsets with the passed POST variables and then checking them for
validity.
"""
self.object = None
form_class = self.get_form_class()
form = self.get_form(form_class)
articleimage_form = ArticleImageFormSet(self.request.POST)
articletag_form = ArticleTagFormSet(self.request.POST)
articlecategory_form = ArticleCategoryFormSet(self.request.POST)
if (form.is_valid() and articleimage_form.is_valid() and
articletag_form.is_valid() and articlecategory_form.is_valid()):
return self.form_valid(form, articleimage_form, articletag_form,
articlecategory_form)
else:
return self.form_invalid(form, articleimage_form, articletag_form,
articlecategory_form)
def form_valid(self, form, articleimage_form, articletag_form,
articlecategory_form):
"""
Called if all forms are valid. Creates a Recipe instance along with
associated Ingredients and Instructions and then redirects to a
success page.
"""
self.object = form.save()
obj.author = request.user.username
articleimage_form.instance = self.object
articleimage_form.save()
articletag_form.instance = self.object
articletag_form.save()
articlecategory_form.instance = self.object
articlecategory_form.save()
return HttpResponseRedirect(self.get_success_url())
def form_invalid(self, form, articleimage_form, articletag_form,
articlecategory_form):
"""
Called if a form is invalid. Re-renders the context data with the
data-filled forms and errors.
"""
return self.render_to_response(
self.get_context_data(form=form,
articleimage_form=articleimage_form,
articletag_form=articletag_form,
articlecategory_form=articlecategory_form))
template.html
template.html
<form enctype="multipart/form-data" action="" method="post">
{% csrf_token %}
<div class="row">
<div class="medium-9 columns">
{{ form.non_field_errors }}
<h2 class="article-identifier">Add a new article</h2>
<div class="fieldWrapper">
{{ form.title.errors }}
{{ form.title }}
<div id="title_feedback" class="text-right"></div>
</div>
<div class="fieldWrapper">
{{ form.text.errors }}
{{ form.text }}
</div>
</div>
<div class="medium-3 columns">
<div class="button-wrapper">
<input class="button" type="submit" value="Publish">
</div>
<fieldset class="image_upload">
<h2>Add an Image</h2>
{{ articleimage_form.management_form }}
{{ articleimage_form.non_form_errors }}
{% for form in articleimage_form %}
{{ form.id }}
<div class="inline {{ articleimage_form.prefix }}">
{{ form.image.errors }}
{{ form.image.label_tag }}
{{ form.image }}
{{ form.image_name.errors }}
{{ form.image_name.label_tag }}
{{ form.image_name }}
</div>
{% endfor %}
</fieldset>
<fieldset>
<h2>Add a Category</h2>
{{ articlecategory_form.management_form }}
{{ articlecategory_form.non_form_errors }}
{% for form in articlecategory_form %}
{{ form.id }}
<div class="inline {{ articlecategory_form.prefix }}">
{{ form.slug.errors }}
{{ form.slug.label_tag }}
{{ form.slug }}
</div>
{% endfor %}
</fieldset>
<hr />
<fieldset>
<h2>Add a Tag</h2>
{{ articletag_form.management_form }}
{{ articletag_form.non_form_errors }}
{% for form in articletag_form %}
{{ form.id }}
<div class="inline {{ articletag_form.prefix }}">
{{ form.slug.errors }}
{{ form.slug.label_tag }}
{{ form.slug }}
</div>
{% endfor %}
</fieldset>
</div>
</div>
</form>
推荐答案
使用 commit保存表单= False
,在对象上设置用户,然后保存对象。在 form_valid
方法内,您可以使用 self.request.user
访问该用户。您应该分配用户实例,而不是像当前代码那样分配用户名。
Save the form with commit=False
, set the user on the object, then save the object. Inside the form_valid
method, you can access the user with self.request.user
. You should assign the user instance, not the username as your code currently does.
obj = form.save(commit=False)
obj.author = self.request.user
...
obj.save
还应该将视图限制为登录用户。您可以为此使用 LoginRequiredMixin
。
You should also restrict the view to logged in users. You can use the LoginRequiredMixin
for this.
from django.contrib.auth.mixins import LoginRequiredMixin
class CreateArticle(LoginRequiredMixin, CreateView):
这篇关于使用createview和modelform在django中自动将登录用户设置为作者的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!