Как использовать значения полей по умолчанию для ForeignKey?

Я только начинаю изучать Django и строить на нем простой блог. Итак, у меня есть две модели Post и PostStatistics. Когда я добавляю новый пост, я хочу, чтобы PostStatistics содержала все заданные по умолчанию значения. Как я могу добиться этого правильно?

models.py

class PostStatistics(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid4)
    post_views = models.IntegerField(default=0)
    post_likes = models.IntegerField(default=0)
    post_favorites = models.IntegerField(default=0)

class Post(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid4)
    user = models.ForeignKey(UserProfile, null=True, on_delete=models.CASCADE)
    statistics = models.ForeignKey(PostStatistics, null=True, on_delete=models.CASCADE)
    title = models.CharField(max_length=200)
    body = RichTextField(blank=True, null=True)
    draft = models.BooleanField(default=False)

views.py

def add_post(request: HttpRequest):
    form = PostForm(request.POST)
    is_draft = True if form.data.get("draft") == "on" else False
    post = Post(
        title=form.data["title"],
        body=form.data["post"],
        user=request.user,
        draft=is_draft,
        statistics = PostStatistics() -> this is not correct
    )
    post.save()
    return redirect("post")

На данный момент я получаю FOREIGN KEY constraint failed.

Вы создаете новый:

def add_post(request: HttpRequest):
    form = PostForm(request.POST)
    is_draft = form.data.get('draft') == 'on'
    post_statistics = PostStatistics.objects.create()
    Post.objects.create(
        title=form.data['title'],
        body=form.data['post'],
        user=request.user,
        draft=is_draft,
        statistics = post_statistics
    )
    return redirect('post')

Однако не имеет особого смысла хранить статистику в отдельной модели, поскольку существует четкая связь один-к-одному, и поэтому статистику можно хранить в модели Post.

Кроме того, вы можете использовать форму для проверки ввода и также создать объект (или, по крайней мере, его часть). Таким образом, лучшее моделирование может быть следующим:

from django.conf import settings

class Post(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid4)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE, editable=False)
    title = models.CharField(max_length=200)
    body = RichTextField(blank=True, null=True)
    draft = models.BooleanField(default=False)
    post_views = models.IntegerField(default=0, editable=False)
    post_likes = models.IntegerField(default=0, editable=False)
    post_favorites = models.IntegerField(default=0, editable=False)

и затем работать с ModelForm, где вы позволяете форме сделать всю необходимую валидацию и очистку:

from django.contrib.auth.decorators import login_required

@login_required
def add_post(request: HttpRequest):
    if request.method == 'POST':
        form = PostForm(request.POST)
        if form.is_valid():
            form.instance.user = request.user
            form.save()
            return redirect('post')
    else:
        form = PostForm()
    return render(request, 'name-of-some-template.html', {'form': form})

Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.


Note: You can limit views to a view to authenticated users with the @login_required decorator [Django-doc].

Вернуться на верх