首页 > 解决方案 > 将当前登录的用户分配给 Django 中的 ForeignKey 字段

问题描述

我的问题是我无法在我的模型的卖家实例中自动分配我的登录用户。我尝试了许多来自 stackoverflow 的解决方案,但都没有奏效。我不知道问题是什么。我已经尝试过基于类的视图和基于函数的视图。这是基于类的方法。

我的模型:

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

class Product(models.Model):
    title = models.CharField(max_length= 100)
    price = models.DecimalField(decimal_places=2, max_digits=9, default=0.00)
    description = models.TextField()
    discount_price = models.DecimalField(decimal_places=2, max_digits=8, default=0.00)
    image = models.ImageField(upload_to='product_image/', default="default.jpg", blank=True,  
    null=True)
    seller = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        return self.title
    
    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)
        image = Image.open(self.image.path)
        if (image.height > 300 and image.width > 300):
            output_size = (300, 300)
            image.thumbnail(output_size)
            image.save(self.image.path)

我的观点:

from django.shortcuts import render, redirect
from .models import Product
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import CreateView
from django.urls import reverse_lazy

class CreateProduct(LoginRequiredMixin, CreateView):
    model = Product
    fields = '__all__'
    template_name = 'product/product_create.html'
    success_url = reverse_lazy('home')

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

我的网址:

from django.urls import path
from .views import  CreateProduct, detail_product, delete_product, update_product

app_name = 'product'

urlpatterns = [
    path('create', CreateProduct.as_view(), name='create'),
]

我的模板:

{% extends 'base.html' %}

{% load crispy_forms_tags%}

{% block main %}

<div class="container mt-3">
    <form action="{% url 'product:create' %}" method="post" enctype="multipart/form-data">
        {% csrf_token %}

        {{form|crispy}}

        <button type="submit" class="btn btn-warning">ADD</button>
    </form>
</div>

{% endblock %}

标签: django-modelsdjango-formsdjango-viewsdjango-usersdjango-request

解决方案


您不应该指定fields = '__all__',因为那时表单将在表单中包含一个表单元素seller,并覆盖request.user. 因此,这将“撤消” form.instance.seller = request.user.

您可以使用以下命令排除该字段:

class CreateProduct(LoginRequiredMixin, CreateView):
    model = Product
    # no seller
    fields = ['title', 'price', 'description', 'discount_price', 'image']
    template_name = 'product/product_create.html'
    success_url = reverse_lazy('home')

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

另一种可能更优雅的方法是将字段标记为不可编辑:

class Product(models.Model):
    # …
    seller = models.ForeignKey(User, editable=False, on_delete=models.CASCADE)

注意:通常使用settings.AUTH_USER_MODEL[Django-doc]引用用户模型比直接使用User模型 [Django-doc]更好。有关更多信息,您可以查看文档的引用User模型部分


注意:在 Django 中,基于类的视图 (CBV) 通常有一个…View后缀,以避免与模型名称发生冲突。因此,您可能会考虑将视图类重命名为CreateProductView,而不是CreateProduct


推荐阅读