Проблема с созданием нового объекта с помощью формы (Django)
Я использую фреймворк Django для создания веб-сайта. Этот сайт основан на пользователях, и у каждого пользователя есть модель профиля. Сейчас я работаю над созданием системы, в которой каждый пользователь может ввести свой опыт работы. Я хочу, чтобы вы могли ввести категорию, а затем заполнить баллы для каждой категории. (Например, если вы писали для New York Times, категория будет "New York Times", а затем прямо под ней будут статьи, которые вы написали, в виде пунктов). Я нахожусь на этапе, когда просто пытаюсь сделать так, чтобы пользователь мог создать новую категорию. У меня есть страница редактирования профиля, где пользователь уже может редактировать некоторые детали из моделей. Я попытался добавить форму, которая создает новую категорию. Когда вы отправляете категорию, появляется сообщение об успехе, но когда я смотрю на панель администратора, она не создает объект в категории. Вот код: (Примечание: эта форма позволяет вам выбрать пользователя для категории, я должен изменить ее позже, чтобы сделать так, чтобы категория была установлена для пользователя, который в настоящее время вошел в систему)
views.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)
models.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
editprofile.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"> {{ user.username }}</h2>
<p class="text-secondary">  {{ 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 %}
Приведенный выше код не сработал и не создал новую категорию. Однако я попробовал метод different и он может успешно создать новую категорию. Я создал новую страницу и новое представление, чтобы показать только форму единственной категории. Эта форма также устанавливает пользователя на пользователя, вошедшего в систему.
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, это бы тоже отлично сработало.
Любая помощь или понимание будут оценены по достоинству.
Согласно вашей форме AddCategory ее модель - Category. Поэтому когда вы передаете параметр instance, он должен быть экземпляром модели Category, но вы посылаете request.user
Я думаю, что это должно быть что-то похожее на: (В этом случае вы отправляете последнюю категорию, назначенную пользователю)
c_form = AddCategory(request.POST, request.FILES, instance=request.user.category_set.last())