Create an instance from TextInput in CreateView

Viewed 100

I have a model.py file that has classes Author and Article. Article has a foreign key referencing Author. I have created a view,blogCreate, using a form ,ArticleForm, in my forms.py file. Since author in class Article is a foreign key, it means that author will be chosen from the Author queryset. This means that the select tag will automatically used by the form, instead I want to use the <input type="text" > tag so that I can create an instance of Author using the input and not select from the queryset.

forms.py

from django import forms
from .models import Article


class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        fields = ('title', 'content', 'aurthor')
        widgets = {
            'title': forms.TextInput(attrs={
                'class': 'title'}),
            'content': forms.Textarea(attrs={
                'class': 'text_input',
                'name': 'article_content'}),
            # Changed to TextInput so it can use <input type="text" >
            'aurthor': forms.TextInput(attrs={
                'class': 'text_input',
                'name': 'aurthor_name'})
        }

models.py

from django.db import models
from ckeditor.fields import RichTextField


class Aurthor(models.Model):
    name = models.CharField("Author Name", max_length=100)
    def __str__(self):
        return self.name


class Article(models.Model):
    title = models.CharField("Title", max_length=100)
    content = RichTextField(blank=True, null=True)
    pub_date = models.DateTimeField("Publish Date", auto_now_add = True)
    aurthor = models.ForeignKey(Aurthor, on_delete=models.CASCADE)
    def __str__(self):
        return self.title

views.py


from .models import Article, Aurthor
from django.views.generic import CreateView
from .forms import ArticleForm


class blogCreate(CreateView):
    model = Article
    form_class = ArticleForm
    template_name = 'BlogHandler/blog.html'

blog.html

 <form action="" method="post">
        {% csrf_token %}
        {{form.as_p}}
        <button type="submit">Post</button>
    </form>
1 Answers

I finally found a way to do exactly what I wanted, I don't if how efficient it is but it works. Let me know if there is a better way.

forms.py

from django import forms
from .models import Article, Author


class ArticleForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(ArticleForm, self).__init__(*args, **kwargs)
        self.fields['author'] = forms.CharField(max_length=100, required=True)# author is required
    class Meta:
        model = Article
        fields = ('title', 'content', )

In the question, I stated that I'd changed the widget for author to TextInput so that I could enter text not an instance of Author.This didn't work out the way I wanted, so instead I removed author from fields and made a custom field author that is not a field in my model. This way I still get the text input to create my Author instance.

models.py

class Article(models.Model):
    title = models.CharField("Title", max_length=100, null=False)
    content = RichTextField(blank=True, null=False)
    pub_date = models.DateTimeField("Publish Date", auto_now_add = True)
    author = models.ForeignKey(Author, on_delete=models.CASCADE, null=True)

I made author nullable in my models.py file but it is okay because I made the custom auhtor field in forms.py required so that all Articles made using the site have an Author. I was getting some error before this change

views.py

class articleCreate(CreateView):
    model = Article
    form_class = ArticleForm

    def form_valid(self, form):
        rt = super().form_valid(form)
        article = form.save(commit=False)
        author_name = self.request.POST['author'].title()
        author, created = Author.objects.get_or_create(name=author_name)
        article.author = author
        article.save()
        return rt

Here I first pause the save so that I can create an Author using the text input from the custom field author, which is simple text, if the Author instance already exists it gets else it creates it. Then I save and I'm done.

Related