Home > database >  How to use default field values for ForeignKey?
How to use default field values for ForeignKey?

Time:04-17

I'm just starting to learn Django and building a simple blog with it. So i have two models Post and PostStatistics. When ever i add a new post, i want that PostStatistics contains all specified default values. How can i achieve this correctly?

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")

At the moment i get FOREIGN KEY constraint failed.

CodePudding user response:

You create a new one:

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')

It however does not make much sense to store the statistics in a separate model, since there is a clear one-to-one relation, and thus the statistics can be stored in the Post model.

Furthermore you can use the form to validate the input and also create the object (or at least parts of it). A better modeling thus might be:

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)

and then work with a ModelForm where you let the form do all the proper validation and cleaning:

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].

  • Related