Django - Как создать отношения "один ко многим", используя класс User по умолчанию
Я создаю приложение под названием Trading Journal, которое позволяет пользователям входить в систему и записывать результаты своих сделок с акциями. Каждый пользователь должен иметь доступ только к своим индивидуальным записям. Для этого я добавляю поле ForeignKey в класс Entry, привязанный к стандартному классу Django User. Но при попытке выполнить команду /migrate я получаю следующую ошибку: ValueError: Поле 'id' ожидало число, но получило 'andredi15' (andredi15 - одно из имен пользователей). Поэтому у меня два вопроса: 1) Как мне исправить эту ошибку и, 2) Должен ли я пойти другим путем? Может быть, создать пользовательскую модель пользователя? Спасибо!
Models.py:
from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator
from django.urls import reverse
from django.utils.text import slugify
from django.contrib.auth.models import User
from django.contrib.auth import get_user_model
class Entry(models.Model):
ONEORB="1-Min ORB"
FIVEORB="5-Min ORB"
ABCD="ABCD"
REVERSAL="Reversal"
PROFIT="Profit"
LOSS="Loss"
RESULT_CHOICES = (
(PROFIT, "Profit"),
(LOSS, "Loss")
)
STRATEGY_CHOICES = (
(ONEORB,"1-Min ORB"),
(FIVEORB,"5-Min ORB"),
(ABCD,"ABCD"),
(REVERSAL,"Reversal")
)
entered_date=models.DateField(auto_now_add=True)
ticker=models.CharField(max_length=8, default="")
strategy=models.CharField(max_length=12, choices=STRATEGY_CHOICES, default="ONEORB")
result=models.CharField(max_length=6, choices=RESULT_CHOICES, default="PROFIT")
comments=models.TextField(max_length=300, blank=True)
image = models.ImageField(upload_to="", null=True, blank=True) #will save to default BASE_DIR which is 'uploads'
username = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, related_name="usernames", to_field="username")
def __str__(self):
return f"{self.result} {self.entered_date}"
Forms.py:
from django import forms
from .models import Entry
# Authentication modules start here
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.contrib.auth.models import User
from django.forms.widgets import PasswordInput, TextInput
# Form to create a journal entry
class EntryForm(forms.ModelForm):
class Meta:
model=Entry
fields='__all__'
# Create / register a user
class CreateUserForm(UserCreationForm):
class Meta:
model = User #default django User model
fields = ['username', 'email', 'password1', 'password2']
# Authenticate a user
class LoginForm(AuthenticationForm):
username = forms.CharField(widget=TextInput())
password = forms.CharField(widget=PasswordInput())
Views.py (все еще в процессе работы):
from django.forms.models import BaseModelForm
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect
from django.views import View
from django.contrib import messages
from django.urls import reverse_lazy
from .forms import EntryForm, CreateUserForm, LoginForm
from .models import Entry
from django.views.generic.edit import DeleteView, FormView
# Authentication models and functions
from django.contrib.auth.models import auth
from django.contrib.auth import authenticate, login, logout
#this is to ensure that even after you have your login setup, a user can't just manually type in the URL
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import TemplateView
# Create your views here.
class EntryView(View):
def get(self, request):
entries = Entry.objects.all().order_by("entered_date")
form = EntryForm()
return render(request, "entries.html", {"form":form, "entries":entries})
def post(self, request):
form = EntryForm(request.POST, request.FILES) #must add request.FILES for uploads
print(request.FILES)
if form.is_valid():
form.save()
messages.success(request, "Entry created!")
return redirect("/")
else:
messages.error(request, "Please correct the errors below.")
return render(request, "entries.html", {"form":form})
def SingleEntryView(request, pk):
entry = Entry.objects.get(pk=pk)
if request.method == 'POST':
# Initialize the form with the existing Entry data
form = EntryForm(request.POST, request.FILES, instance=entry)
if form.is_valid():
# Set the user and save the updated data
form.instance.user = request.user
form.save()
# Redirect to a success page (e.g., 'index')
else:
# Initialize the form with the existing Entry data
form = EntryForm(instance=entry)
context = {'form': form, 'entry': entry}
return render(request, "single_entry.html", context)
class SingleEntryDeleteView(DeleteView):
template_name = "single_entry.html"
model = Entry
success_url = reverse_lazy("index")
success_message = "Entry has been deleted."
def delete(self, request):
messages.success(self.request, "Successfully deleted.")
return super().delete()
class RegisterFormView(FormView):
form = CreateUserForm
template_name = "register.html"
success_url = ""
def form_valid(self, form):
pass
Когда я запускаю python manage.py migrate, я ожидаю, что модель Entry будет обновлена с помощью внешнего ключа. Я также пробовал использовать "User" в качестве первого аргумента для ForeignKey, но я читал, что рекомендуется использовать get_user_model(), а не вызывать модель напрямую.
Да, так и было. В предыдущей миграции я назначил ForeignKey. Спасибо, Виллем