用户无法在页面中创建对象。

huangapple go评论57阅读模式
英文:

User can't create objects in the page

问题

I made a program where users can keep track of their expenses by entering them into the system after creating their own account. The system requires users to fill in four fields: customer, category, price, and month. I would like the first field (customer) to automatically populate with the username of the logged-in user, so that users don't have to choose from all available customers.

However, I encountered an issue where users are unable to create objects in the system. I can only create objects through the admin dashboard. When I try to create an object on the page, it throws an error message saying,

RelatedObjectDoesNotExist at / User has no customer.

I suspect this problem is related to the fact that users are added in the authentication and authorization section under Users in the admin page, instead of being created under Customers by my app, alongside the Finance section where the objects are stored.

To summarize my two main issues:

  1. I want the first field to automatically populate with the username of the logged-in user.
  2. I want users to be able to create objects directly from the page, as they could in the past when this issue didn't occur.
英文:

I made a program where users can keep track of their expenses by entering them into the system after creating their own account. The system requires users to fill in four fields: customer, category, price, and month. I would like the first field (customer) to automatically populate with the username of the logged-in user, so that users don't have to choose from all available customers.

However, I encountered an issue where users are unable to create objects in the system. I can only create objects through the admin dashboard. When I try to create an object on the page, it throws an error message saying,

RelatedObjectDoesNotExist at / User has no customer.

I suspect this problem is related to the fact that users are added in the authentication and authorization section under Users in the admin page, instead of being created under Customers by my app, alongside the Finance section where the objects are stored.

To summarize my two main issues:

  1. I want the first field to automatically populate with the username of the logged-in user.
  2. I want users to be able to create objects directly from the page, as they could in the past when this issue didn't occur.

Thank you so much for your help.

models.py:

class Customer(models.Model):
    user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
    name = models.CharField(max_length=200, null=True)
    email = models.CharField(max_length=200, null=True, blank=True)
    date_created = models.DateTimeField(auto_now_add=True, null=True)

    # def __str__(self):
    #     return self.name #I don't now if it's correct


class Finance(models.Model):
    expenses_category = [
        ("Saving", "Saving"),
        ("Food", "Food"),
        ("Bills", "Bills"),
        ("Rent", "Rent"),
        ("Extra", "Extra"),
    ]

    expenses_month = [
        ("January", "January"),
        ("February", "February"),
        ("March", "March"),
        ("April", "April"),
        ("May", "May"),
        ("June", "June"),
        ("July", "July"),
        ("August", "August"),
        ("September", "September"),
        ("October", "October"),
        ("November", "November"),
        ("December", "December"),
    ]

    customer = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
    category = models.CharField(choices=expenses_category, max_length=200)
    price = models.IntegerField()
    month = models.CharField(choices=expenses_month, max_length=200)

views.py:

@csrf_exempt
def registerPage(request):
    if request.user.is_authenticated:
        return redirect('home')
    else:
        form = CreateUserForm()
        if request.method == 'POST':
            form = CreateUserForm(request.POST)
            if form.is_valid():
                # form.instance.user = request.user
                user = form.save()
                username = form.cleaned_data.get('username')

                group = Group.objects.get(name='customer')
                user.groups.add(group)

                messages.success(request, 'Account was created for ' + username)

                return redirect('login')

        context = {'form': form}
        return render(request, 'app_finance/register.html', context)


def loginPage(request):
    username = None
    if request.user.is_authenticated:
        username = request.user.customer
        return redirect('home')
    else:
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')

            user = authenticate(request, username=username, password=password)

            if user is not None:
                login(request, user)
                return redirect('home')
            else:
                messages.info(request, 'Username or password incorrect.')

        context = {}
        return render(request, 'app_finance/login.html', context)


def logoutUser(request):
    logout(request)
    return redirect('login')


def userPage(request):
    return render(request, 'app_finance/user.html')


@login_required(login_url='login')
def homeView(request):
    # customer = Customer.objects.get(id=pk) (not sure#)
    username = None
    items = Finance.objects.filter(customer_id=request.user.id)
    form = FinanceForm(initial={'customer': User})
    if request.method == 'POST':
        username = request.user.customer
        form = FinanceForm(request.POST)  # initial={'customer': user}
        if form.is_valid():
            form.save()
            return HttpResponseRedirect('/')
    else:
        form = FinanceForm()
        return render(request, 'app_finance/home.html', {'form': form, 'items': items})

forms.py:

class CustomerForm(ModelForm):
    class Meta:
        model = Customer
        fields = '__all__'
        exclude = ['user']


class CreateUserForm(UserCreationForm):
    class Meta:
        model = User
        fields = ['username', 'email', 'password1', 'password2']


class FinanceForm(ModelForm):
    class Meta:
        model = Finance
        fields = '__all__'

templates/home.html:

<div>
    <span>Hello, {{ request.user }}</span> <br>
    <span><a class="hello-msg" href="{% url 'logout' %}">Logout</a></span>
</div>


<form action="" method="post">
    {% csrf_token %}
    {{ form }}
    <!-- {{ form }} -->

    <input type="submit" value="Submit">
</form>

<br>
<div class="row">
    <div class="col-md">
        <div class="card card-body">
            <h1>Expenses</h1>
        </div>
        <div class="card card-body">
            <table class="table">
                <tr>
                    <th>User</th>
                    <th>Category</th>
                    <th>Price</th>
                    <th>Month</th>
                </tr>
                {% for i in items %}
                    <tr>
                        <td>{{ i.customer }}</td>
                        <td>{{ i.category }}</td>
                        <td>{{ i.price }}</td>
                        <td>{{ i.month }}</td>
                        <td>  </td>
                        <td><a class="btn btn-sm btn-info" href="">Update</a></td>
                        <td><a class="btn btn-sm btn-danger" href="">Delete</a></td>
                    </tr>
                {% endfor %}
            </table>
        </div>
    </div>
</div>

Thanks again for helping.

答案1

得分: 0

根据您的要求,以下是翻译好的内容:

如您所说在您的评论中:

> 这将是财务模型。我考虑在FinanceForm中排除'customer',以便用户无需选择其用户名,但我保留它以便我可以检查是否正在正确制作表单,选择已登录的用户,目前尚未这样做。

允许用户在创建模型时选择自己是不明智的,因为有人可能使用其他用户来为他们创建“Finance”模型的对象,要解决这些问题,您需要更改“FinanceForm”通过删除'all'并指定要让用户看到的字段:

class FinanceForm(ModelForm):
    class Meta:
        model = Finance
        fields = ['month', 'price', 'category']

当您说要提交一个“Finance”模型时,您的问题中没有包含执行此操作的视图。因此,您可以使用基于函数的视图或基于类的视图来执行此操作。

使用基于函数的视图:

def create_finance(request):
    if request.method == 'POST':
        price = request.POST['price']
        month = request.POST['month']
        category = request.POST['category']
        form = FinanceForm(request.POST)
        if form.is_valid():
            new_finance_object = Finance.objects.create(customer=request.user, price=price, month=month, category=category)
            new_finance_object.save()
            return redirect('home')
    else:
        form = FinanceForm()
    return render(request, 'create_finance.html', {'form': form})

您还可以使用基于类的视图:

from django.views.generic import CreateView

class CreateFinance(CreateView):
    model = Finance
    form_class = FinanceForm
    template_name = 'create_finance.html'

    def form_valid(self, form):
        form.instance.customer = self.request.user
        return super(CreateFinance, self).form_valid(form)
英文:

As you said that on your comment:

> it would be the Finance Model. I was thinking to exclude 'customer' in FinanceForm, so the user doesn't have to select its username, but I leave it that way so I could check if it is making the Form properly, selecting the user who logged in, so far it doesn't do it.

Allowing user to select himself while creating model is unintelligent, because someone may use other user to create them an object of the Finance model, to fix these issues, you have to change your FinanceForm by removing '__all__' and specify the field you want user to see:

class FinanceForm(ModelForm):
    class Meta:
        model = Finance
        fields = ['month', 'price', 'category']

While you are saying: you want to submit a Finance model, you did not include the view that does that in your question. Therefore, you can use either a function-based view or a class-based view to do so.

Using Function base view:

def create_finance(request):
    if request.method == 'POST':
        price = request.POST['price']
        month = request.POST['month']
        category = request.POST['category']
        form = FinanceForm(request.POST)
        if form.is_valid():
            new_finance_object = Finance.objects.create(customer=request.user, price=price, month=month, category=category)
            new_finance_object.save()
            return redirect('home')
    else:
        form = FinanceForm()
    return render(request, 'create_finance.html', {'form':form})

you can use Class Base View:

from django.views.generic import CreateView 

class CreateFinance(CreateView):
    model = Finance
    form_class = FinanceForm
    template_name = 'create_finance.html'

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

答案2

得分: 0

这是我找到并完美运行的解决方案。
我做了两个更改:

  1. views.py:
    @login_required(login_url='login')
def homeView(request):
    items = Finance.objects.filter(customer=request.user).order_by(Cast('month', IntegerField())).reverse()

    if request.method == 'POST':
        form = FinanceForm(request.POST, request=request)  # 将请求对象传递给表单
        if form.is_valid():
            finance_obj = form.save(commit=False)
            finance_obj.customer = request.user
            finance_obj.save()
            return redirect('home')
    else:
        form = FinanceForm(request=request)  # 将请求对象传递给表单

    context = {'form': form, 'items': items}
    return render(request, 'app_finance/home.html', context)
  1. forms.py
    class FinanceForm(ModelForm):
    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request')  # 检索请求对象
        super().__init__(*args, **kwargs)
        self.fields['customer'].initial = self.request.user
英文:

This is the solution i found and worked perfect too.
I made 2 changes:

  1. views.py:
    @login_required(login_url='login')
def homeView(request):
items = Finance.objects.filter(customer=request.user).order_by(Cast('month', IntegerField())).reverse()
if request.method == 'POST':
form = FinanceForm(request.POST, request=request)  # Pass the request object to the form
if form.is_valid():
finance_obj = form.save(commit=False)
finance_obj.customer = request.user
finance_obj.save()
return redirect('home')
else:
form = FinanceForm(request=request)  # Pass the request object to the form
context = {'form': form, 'items': items}
return render(request, 'app_finance/home.html', context)
  1. forms.py
    class FinanceForm(ModelForm):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request')  # Retrieve the request object
super().__init__(*args, **kwargs)
self.fields['customer'].initial = self.request.user

huangapple
  • 本文由 发表于 2023年6月1日 12:17:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/76378627.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定