review article before publish

Hello!
I want to build review articles before publish. But that would happen if an author chose a journal, if he did not choose a journal when creating his article the article would simply be published on the site.
In this regard, I have two questions:

  1. How to build it in view? If I understand correctly, it can be built by BooleanField in models. But I don’t know how to build it in my views. I tried to build this, but It doesn’t work.
  2. Also it will be good opportunity if this article is accepted by publisher if they have a representative on the site, if not, the article would be sent to the database for inspection by the administration of the site (I have “editor” in journal models).
    I will be happy if you help me.

articles/models.py

class Article(models.Model, HitCountMixin):
    slug = models.SlugField(unique=True)
    title = models.CharField(max_length=255)
    author = models.ForeignKey(
        "users.CustomUser", on_delete=models.SET_NULL, null=True
    )
    abstract = models.TextField(blank=True, null=True)
    content = models.TextField(blank=True, null=True)
    journal = models.ForeignKey(
        "journals.Journal", on_delete=models.SET_NULL, null=True, blank=True
    )
    journalyear = models.ForeignKey(
        "JournalYear", on_delete=models.SET_NULL, null=True, blank=True
    )
    journalvolume = models.ForeignKey(
        "JournalVolume", on_delete=models.SET_NULL, null=True, blank=True
    )
    journal_pages = models.CharField(max_length=10, null=True, blank=True)
    article_type = models.ForeignKey(
        "Article_type", on_delete=models.SET_NULL, null=True, blank=True
    )
    created_date = models.DateTimeField(
        default=timezone.now, null=True, blank=True)
    published_date = models.DateTimeField(
        default=timezone.now, blank=True, null=True)
    submitted = models.BooleanField(default=False)

    def __str__(self):
        return self.title

    class Meta:
        ordering = ["-created_date"]

    def get_absolute_url(self):
        return reverse("article_detail", args=[self.slug])

journal/models.py


class Journal(models.Model):
    editor = models.ForeignKey(
        get_user_model(), on_delete=models.SET_NULL, null=True, blank=True
    )
    slug = models.SlugField(unique=True)
    name = models.CharField(max_length=100, blank=True, null=True)
    description = models.TextField(null=True, blank=True)

    def __str__(self):
        return self.name

    class Meta:
        ordering = ["-name"]

    def get_absolute_url(self):
        return reverse("journal_detail", args=[self.slug])

articles/views.py

class ArticleCreateView(LoginRequiredMixin, CreateView, SuccessMessageMixin):
    model = Article
    form_class = ArticleForm
    template_name = "articles/example.html"
    success_message = "%(title)s was created successfully"

    def form_valid(self, form):
        form.instance.author = self.request.user
        return super(ArticleCreateView, self).form_valid(form)

    def post(self, request, *args, **kwargs):
        article = Article.objects.all()
        form = self.get_form()
        if article.journal:
            article.submitted = False
            messages.add_message(self.request, messages.INFO,
                                 'Your Article pending for publisher approval')
             return self.form_valid(form)
        else:
            article.submitted = True
            return self.form_valid(form)

articles/forms.py

class ArticleForm(forms.ModelForm):
    title = forms.CharField(required=False)
    abstract = forms.CharField(required=False, widget=PagedownWidget())
    content = forms.CharField(required=False, widget=PagedownWidget())
    article_type = forms.ModelChoiceField(
        required=False, queryset=Article_type.objects.all()
    )
    language = forms.ModelChoiceField(required=False, queryset=Language.objects.all())

    class Meta:
        model = Article
        exclude = ["author", "created_date", "published_date", "id"]

        help_texts = {
            "title": _("Article should contain words, number and etc..."),
            "tags": _("Keywords should contain words, number and etc..."),
            "abstract": _("Abstract should contain words, number and etc..."),
            "text": _("Text should contain words, number and etc..."),
            "article_type": _("Text should contain words, number and etc..."),
            "subject": _("Text should contain words, number and etc..."),
            "language": _("Text should contain words, number and etc..."),
        }

        widgets = {
            "journal": autocomplete.ModelSelect2(url="journalautocomplete"),
            "journalvolume": autocomplete.ModelSelect2(
                url="journalvolumeautocomplete", forward=["journalyear"]
            ),
            "journalyear": autocomplete.ModelSelect2(
                url="journalyearautocomplete", forward=["journal"]
            ),
        }

articles/example.html

{% extends 'base.html' %}

{% block content %}

<form method="post">{% csrf_token %}
   {{ form.media }}

   {{form.as_p}}
   <button type='submit' name='save_article'>Save</button>
</form>
{% endblock content %}

I made the first question, maybe it’s the wrong approach, but it works :slight_smile:
I attach my code, it may be useful for readers. But I don’t know how to build my second question :frowning: I have no idea how to do that. I would welcome any ideas on that.

articles/views.py

class ArticleCreateView(LoginRequiredMixin, CreateView, SuccessMessageMixin):
    model = Article
    form_class = ArticleForm
    template_name = "articles/example.html"
    success_message = "%(title)s was updated successfully"

    def form_valid(self, form):
        form.instance.author = self.request.user
        return super(ArticleCreateView, self).form_valid(form)

    def post(self, request, *args, **kwargs):
        form = self.get_form()
        if form.is_valid():
            obj = form.save(commit=False)
            obj.author = self.request.user
            if obj.journal:
                obj.submitted = False
                messages.add_message(self.request, messages.INFO,
                                     'Your Article pending for publisher approval')
                obj.save()
                return redirect('home')
            else:
                obj.submitted = True
                messages.add_message(self.request, messages.INFO,
                                     'Your Article is good!')
                obj.save()
                return redirect('home')

I’m sorry, I’m having difficulty understanding your second question as written.

What I’m understanding so far:

  • When an article is submitted and a journal is selected, you set submitted = False.

  • When an article is submitted and no journal is selected, submitted = True.

  • You want to have a type of User identified as the “representative” of a publisher.

    • Do you already know how you want to identify the representative of a publisher?
  • You want this representative to be able to do something with an article if the article is submitted to the publisher they represent.

    • Are you tracking which Journal(s) are published by which publisher?
  • If the publisher isn’t represented on the site, what do you want the site administrator to do?

  • What does all this mean in terms of the Article model?

Right off-hand, this looks to me like you’re trying to build a “workflow” for these Articles. If so, there are a number of different ways to handle this, it just depends upon what your ultimate objectives are.

Ken, hello!
Thank you for the response and what you’re clarifying. It’s more likely that I didn’t explain it properly.

Yes, you’re right

Yes, I tried to build it by add ForeignKey to user. But I don’t know it is good approach or not. What do you think?

class Journal(models.Model):
    editor = models.ForeignKey(
        get_user_model(), on_delete=models.SET_NULL, null=True, blank=True
    )

No, I just use name journal without publisher. But I agree with you, it’s better to track this information. if I understood correctly, do I need to add ForeignKey with publisher?

Yes, you’re right

I’m sorry, I didn’t understand it.

I think you’re right.
I looked it up in the search, and that’s what I needed. If I understand correctly, I need to use third app, yes? Can you give me advice how to build it better? Maybe there are good Tutorials to figure out how to do it better. It would be nice if I didn’t build it, I could ask you again, if you don’t mind

I think it’s starting to clear up for me.

If there’s only one editor for a Journal, that’s fine. If there are multiple people who are editors for a Journal, then it would be a ManyToMany relationship

I don’t know the relationship between Journal and Publisher in your application.

If a Journal is only published by one Publisher, then you could add a ForeignKey field in the Journal that refers to its publisher. If a Journal is published by multiple publishers, but each Publisher only publishes one Journal, then the ForeignKey field belongs in the Publisher object. Or, it might be another ManyToMany relationship. But since I’m not familiar with your application domain I can’t answer that question.

You could find an implement a workflow app - but it might also be overkill.

Whether you build your own or use another app, at some point you need to define what the workflow is. Generally speaking, you want to identify all the possible statuses for the model being managed, what actions are available for each status, and who can perform those actions.

For example, if you were running a “managed blog”, where posts need to be approved before being visible, you might have a workflow that looks something like this:

|     Status     |   Action             |  New Status  |  Actor          |
----------------------------------------------------------------------------
|  <new>         |  Post                |  Written     |  Article author |
|  Written       |  Submit for approval | For Approval |  Article author |
|  For approval  |  Accept              |  Published   |  Editor         |
|  For approval  |  Reject              |  Written     |  Editor         |

(You can use any format you’re comfortable with, this is just what we use - but this is generally the type of information you need to define a workflow)

Unfortunately, I don’t have any reference materials or suggestions for apps that I can give you. You might browse through djangopackages.org to see if there’s anything there you might find of use to you.

Ken, thank you!
I found django-fsm so far. I will try to create a workflow like you wrote me.