Django - 如何使用默认用户类创建一对多关系

问题描述 投票:0回答:1

我正在创建一个名为“交易日记”的应用程序,它允许用户登录并记录股票交易的结果。每个用户只能访问他们自己的条目。为此,我在 Entry 类上添加了一个外键字段,该字段与 Django 的默认 User 类相关联。但当我尝试运行 /migrate 命令时出现此错误: ValueError: Field 'id' Expected a number but getting 'andredi15' (andredi15 is one of the usernames) 所以我有两个问题:1)我如何修复这个错误,2)我应该以不同的方式解决这个问题吗?也许通过设置自定义用户模型?谢谢!

模型.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}"

表格.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
      

这是我运行迁移命令时来自控制台的错误消息:

Running migrations:
  Applying entries.0011_entry_username...Traceback (most recent call last):
  File "C:\Users\andre\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\db\models\fields\__init__.py", line 2053, in get_prep_value
    return int(value)
           ^^^^^^^^^^
ValueError: invalid literal for int() with base 10: 'andredi15'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\andre\OneDrive\Documents\Django\trading_journal\manage.py", line 22, in <module>
    main()
  File "C:\Users\andre\OneDrive\Documents\Django\trading_journal\manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "C:\Users\andre\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\core\management\__init__.py", line 442, in execute_from_command_line
    utility.execute()
  File "C:\Users\andre\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\core\management\__init__.py", line 436, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "C:\Users\andre\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\core\management\base.py", line 412, in run_from_argv
    self.execute(*args, **cmd_options)
  File "C:\Users\andre\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\core\management\base.py", line 458, in execute
    output = self.handle(*args, **options)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\andre\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\core\management\base.py", line 106, in wrapper
    res = handle_func(*args, **kwargs)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\andre\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\core\management\commands\migrate.py", line 356, in handle
    post_migrate_state = executor.migrate(
                         ^^^^^^^^^^^^^^^^^
  File "C:\Users\andre\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\db\migrations\executor.py", line 135, in migrate
    state = self._migrate_all_forwards(
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\andre\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\db\migrations\executor.py", line 167, in _migrate_all_forwards
    state = self.apply_migration(
            ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\andre\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\db\migrations\executor.py", line 252, in apply_migration
    state = migration.apply(state, schema_editor)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\andre\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\db\migrations\migration.py", line 132, in apply
    operation.database_forwards(
  File "C:\Users\andre\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\db\migrations\operations\fields.py", line 108, in database_forwards
    schema_editor.add_field(
  File "C:\Users\andre\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\db\backends\sqlite3\schema.py", line 398, in add_field
    self._remake_table(model, create_field=field)
  File "C:\Users\andre\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\db\backends\sqlite3\schema.py", line 238, in _remake_table
    self.effective_default(create_field),
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\andre\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\db\backends\base\schema.py", line 429, in effective_default
    return field.get_db_prep_save(self._effective_default(field), self.connection)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\andre\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\db\models\fields\related.py", line 1129, in get_db_prep_save
    return self.target_field.get_db_prep_save(value, connection=connection)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\andre\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\db\models\fields\__init__.py", line 954, in get_db_prep_save
    return self.get_db_prep_value(value, connection=connection, prepared=False)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\andre\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\db\models\fields\__init__.py", line 2742, in get_db_prep_value
    value = self.get_prep_value(value)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\andre\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\db\models\fields\__init__.py", line 2055, in get_prep_value
    raise e.__class__(
ValueError: Field 'id' expected a number but got 'andredi15'.

当我运行 python manage.py migrate 时,我希望使用外键更新 Entry 模型。我还尝试使用“User”作为ForeignKey的第一个参数,但我读到 get_user_model() 是推荐的方法,而不是直接调用模型。

python django
1个回答
0
投票

是的,就是这样。在之前的迁移中,我分配了一个外键。谢谢威廉

© www.soinside.com 2019 - 2024. All rights reserved.