首页 > 解决方案 > 使用表单创建新对象的问题(Django)

问题描述

我正在使用 Django 框架来构建一个网站。这个网站是基于用户的,每个用户都有一个个人资料模型。现在,我正在构建一个系统,每个用户都可以输入他们的工作经验。我想要它,以便您可以输入一个类别,然后为每个类别填写分数。(例如,如果您为《纽约时报》撰稿,则该类别将是“纽约时报”,然后在它的正下方将是您在项目符号中撰写的文章)。我正处于一个阶段,我只是试图让用户可以创建一个新类别。我有一个编辑个人资料页面,用户已经可以在其中编辑模型中的一些详细信息。我试图添加一个创建新类别的表单。当您提交类别时,会显示一条成功消息,但是当我查看我的管理面板时,它不会在类别下创建对象。

视图.py:

from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required

from django.utils.decorators import method_decorator
from django.views.generic import ListView
from django.contrib.auth.models import User 


from django.urls import reverse_lazy
from .models import Social, Category
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.edit import CreateView, UpdateView, DeleteView, FormView

from .forms import(
     UserRegisterForm,
     UserUpdateForm,
     ProfileUpdateForm,
     BiographyForm,
     AccessCodeForm,
     AddCategory,
 )
from django.apps import apps
Post = apps.get_model('blog', 'Post')

@login_required
def profile(request):
    if request.method == 'POST':
        u_form = UserUpdateForm(request.POST, instance=request.user)
        p_form = ProfileUpdateForm(request.POST,
                                  request.FILES, 
                                  instance=request.user.profile)
        b_form = BiographyForm(request.POST, instance=request.user.profile)
        c_form = AddCategory(request.POST, request.FILES, instance=request.user)

        if u_form.is_valid() and p_form.is_valid() and b_form.is_valid and c_form.is_valid():
            u_form.save()
            p_form.save()
            b_form.save()
            c_form.save()
            messages.success(request, f'Your account has been updated!')
            return redirect('editprofile')

    else:
        u_form = UserUpdateForm(instance=request.user)
        p_form = ProfileUpdateForm(instance=request.user.profile)
        b_form = BiographyForm(instance=request.user.profile)
        c_form = AddCategory(instance=request.user)
    
    context = {
        'u_form': u_form,
        'p_form': p_form,
        'b_form': b_form,
        'c_form': c_form
    }

    return render(request, 'users/editprofile.html', context)

模型.py:

from django.db import models
from django.contrib.auth.models import User
from PIL import Image

class Category(models.Model):
    user = models.ForeignKey(User, on_delete=models.DO_NOTHING, null=True, blank=True)
    name = models.CharField(max_length=100)
    date = models.DateTimeField(auto_now=False, auto_now_add=False, null=True, blank=True)
    

    def __str__(self):
        return self.name

class Work(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
    name = models.CharField(max_length=100)
    link = models.URLField(max_length=200, blank=True, default='') 
    date = models.DateTimeField(auto_now=False, auto_now_add=False, null=True, blank=True)
    category = models.ForeignKey(Category, on_delete=models.DO_NOTHING, null=True, blank=True)


    def __str__(self):
        return self.name

编辑配置文件.html:

{% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
    <div class="content-section">
      <div class="media">
        <img style= "float:left" src="{{ user.profile.image.url }}" width="75" height="75">
        <div class="media-body">
          <h2 class="account-heading">&nbsp;&nbsp;{{ user.username }}</h2>
          <p class="text-secondary">&nbsp;&emsp;{{ user.email }}</p>
        </div>
      </div>
      <form method="POST" enctype="multipart/form-data">
        {% csrf_token %}
        <fieldset class="form-group">
          <legend class="border-bottom mb-4">Profile Info</legend>
          {{ u_form|crispy }}
          {{ p_form|crispy }}
          {{ b_form|crispy }}  
          {{ c_form|crispy }}     
        </fieldset>
        <div class="form-group">
          <button class="btn btn-outline-info" type="submit" action="Edit">Update</button>
        </div>
      </form>
    </div>
{% endblock content %}

表格.py:

from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import Profile, Social, Category, Work

class AddCategory(forms.ModelForm):
    
    class Meta:
        model = Category
        fields = ['name', 'date', 'user']

上面的代码不起作用,它没有创建新的类别。但是,我尝试了一种方法,它可以成功创建一个新类别。我创建了一个新页面和一个新视图来显示一个单一的类别表单。此表单还将用户设置为登录用户。

views.py(第二种方法):

class CreateCategory(LoginRequiredMixin, CreateView):
    model = Category
    fields = ['name', 'date']
    success_url = reverse_lazy('editprofile')

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

category_form.html(第二种方法):

{% extends "blog/base.html" %}
{% block content %}


<h1> Category Form </h1>

<div>
    <form method="POST" action="">
        {% csrf_token %}
        {{form.as_p}}
        <input class="button" type="submit" value="Submit">
    </form>
</div>

{% endblock content %}

第二种方法成功创建了一个类别,我可以在管理页面上看到它。我希望在 editprofile.html 上使用所有其他表单创建类别。我不确定为什么第一种方法不起作用。我相信这与我的 views.py 以及模型的设置方式有关。如果我能以某种方式将第二种方法集成到 editprofile.html 中,那也会很好用。

任何帮助或见解表示赞赏。

标签: pythonhtmldjangosqliteweb-deployment

解决方案


根据你的 AddCategory 表格,它的模型是类别。因此,当您传递实例参数时,它必须是 Category 模型的实例,但您正在发送 request.user

我认为它应该类似于:(在这种情况下,您要发送分配给用户的最后一个类别)

c_form = AddCategory(request.POST, request.FILES, instance=request.user.category_set.last())

推荐阅读