Отображение заказов пользователя в его профиле Django

Я новичок в Python и надеюсь, что кто-нибудь сможет мне помочь. Я понимаю, что это, вероятно, не уникальный вопрос, но прошу отнестись с пониманием. Я работаю над веб-приложением (это книжный магазин). Я сделал корзину и процесс формирования заказа. Теперь я пытаюсь сделать профиль пользователя, но к сожалению, я не знаю, как отобразить все заказы пользователя и сделать возможным изменение заказов (например, изменить количество книг) и как сделать изменяемой информацию профиля пользователя. Я реализовал следующую логику: Пользователь создает корзину, затем создает заказ. После создания заказа корзина также находится в базе данных.

Подводя итог вышесказанному, основными вопросами являются:

  1. Как добавить всю информацию из корзины пользователя (которая была сформирована в заказ) в профиль пользователя?
  2. Как сделать так, чтобы данные пользователя и данные заказа/корзины можно было изменять в профиле пользователя?
  3. Как отобразить несколько заказов пользователя в отдельных строках HTML таблицы (потому что в моем шаблоне все заказы в одной строке)?

Модели тележек:




User = get_user_model()


class Cart(models.Model):
    customer = models.ForeignKey(
        User, null=True, blank=True,
        related_name="Customer",
        verbose_name="Customer",
        on_delete=models.PROTECT
        )

    @property
    def total_price_cart(self):
        goods = self.goods.all()
        total_price_cart = 0
        for good in goods:
            total_price_cart += good.total_price
        return total_price_cart

    def __str__(self):
        return str(self.pk)


class BooksInCart(models.Model):
    cart = models.ForeignKey(
        Cart,
        related_name="goods",
        on_delete=models.CASCADE,
        verbose_name="Cart"
        )
    book = models.ForeignKey(
        Book,
        on_delete=models.PROTECT,
        verbose_name='Book',
    )
    quantity = models.IntegerField(
        verbose_name="Quantity",
        default=1
    )
    price = models.DecimalField(
        verbose_name='Price',
        max_digits=5,
        decimal_places=2,
    )

    @property
    def total_price(self):
        return self.price * self.quantity

Просмотры корзины:

class CartUpdate(View):
    def post(self, request):
        action = request.POST.get('submit')
        if action == "save_cart":
            cart_id = self.request.session.get('cart_id')
            cart, created = models.Cart.objects.get_or_create(
                pk=cart_id,
                defaults={},
            )
            if created:
                self.request.session['cart_id'] = cart.pk
            goods = cart.goods.all()
            if goods:
                for key, value in request.POST.items():
                    if "quantityforgood_" in key:
                        pk = int(key.split('_')[1])
                        good = goods.get(pk=pk)
                        good.quantity = int(value)
                        good.save()
            return HttpResponseRedirect(reverse_lazy("carts:cart_edit"))
        elif action == "create_order":
            return HttpResponseRedirect(reverse_lazy('order:create_order'))
        else:
            return HttpResponseRedirect(reverse_lazy("carts:cart_edit"))


class CartView(generic.DetailView):
    template_name = 'carts/cart_edit.html'
    model = models.Cart

    def get_object(self, queryset=None):
        cart_id = self.request.session.get('cart_id')
        cart, created = models.Cart.objects.get_or_create(
            pk=cart_id,
            defaults={},
        )
        if created:
            self.request.session['cart_id'] = cart.pk
        book_id = self.request.GET.get('book_pk')
        if book_id:
            book = Book.objects.get(pk=int(book_id))
            book_in_cart, flat_created = models.BooksInCart.objects.update_or_create(
                cart=cart,
                book=book,
                defaults={
                    'price': book.price
                }
            )
            if not flat_created:
                q = book_in_cart.quantity + 1
                book_in_cart.quantity = q
                book_in_cart.price = book_in_cart.book.price * q
            else:
                book_in_cart.price = book.price

            book_in_cart.save()
        return cart


class DeleteGoodInCartView(generic.DeleteView):
    model = models.BooksInCart
    template_name = 'carts/delete_book_in_cart.html'
    success_url = reverse_lazy("carts:cart_edit")

Модели заказа:

User = get_user_model()

class CustomSession(Session):
    cart = models.ForeignKey(
        Cart,
        on_delete=models.CASCADE
    )
    class Meta:
        app_label = 'cart_id'


class Status(models.Model):
    name = models.CharField(max_length=30)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = "Status"
        verbose_name_plural = "Statuses"


class Order(models.Model):
    user = models.ForeignKey(
        User, 
        on_delete=models.PROTECT, 
        related_name='orders'
        )
    cart = models.OneToOneField(
        Cart,
        on_delete=models.PROTECT,
        verbose_name="Cart"
    )
    status = models.ForeignKey(
        Status,
        on_delete=models.PROTECT
    )
    contact_info = models.TextField(
        verbose_name="Contact info",
    )
    created = models.DateTimeField(
        verbose_name="Created",
        auto_now=False,
        auto_now_add=True
    )
    updated = models.DateTimeField(
        verbose_name="Updated",
        auto_now=True,
        auto_now_add=False
    )

    def __str__(self):
        return self.contact_info

    class Meta:
        verbose_name = "Order"
        verbose_name_plural = "Orders"

Просмотры корзины:

class CreateOrderView(generic.FormView):
    form_class = forms.OrderCreateForm
    template_name = 'order/create_order.html'
    success_url = reverse_lazy("order:success")

    def form_valid(self, form):
        cart_id = self.request.session.get('cart_id')
        cart, created = carts_models.Cart.objects.get_or_create(
            pk=cart_id,
            defaults={},
        )
        if created:
            return HttpResponseRedirect(reverse_lazy('carts:cart_edit'))
        info = form.cleaned_data.get('contact_info')
        status = models.Status.objects.get(pk=1)
        user = self.request.user
        order = models.Order.objects.update_or_create(
            cart=cart,
            contact_info=info,
            status=status,
            user=user,
        )
        self.request.session.delete('cart_id')
        if self.request.user.is_authenticated:
            cart_id = self.request.session.get('cart_id')
            customer1 = carts_models.Cart.objects.get(pk=cart_id)
            customer1.customer = self.request.user
            customer1.save()
        return super().form_valid(form)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        cart_id = self.request.session.get('cart_id')
        cart, created = carts_models.Cart.objects.get_or_create(
            pk=cart_id,
            defaults={},
        )
        context['object'] = cart
        return context

    def get_success_url(self) -> str:
        del self.request.session['cart_id']
        return super().get_success_url()

def success(requsest):
    return render(requsest, 'order/success.html')

Просмотры профиля пользователя:

class ProfileView(generic.DetailView):


    def get(self, request, *args, **kwargs):
        user = get_object_or_404(AppUser, pk=kwargs['pk'])
        return render(request, 'app_profiles/profile_view.html', context={
            'user': user,
            'order': Order.objects.filter(user=request.user),
        })    

Шаблон профиля пользователя:

<thead>
                        <tr>
                            <th scope="col">Goods</th>
                            <th scope="col">Quantity</th>
                            <th scope="col">Total price</th>
                            <th scope="col">Status</th>
                            <th scope="col">Created</th>
                            <th scope="col">Updated</th>
                        </tr>
                      </thead>
                    <tbody>
                <tr>
                    {% for order in order.all %}    
                    <td>{{ order.created }}</td>
                    <td>{{ order.updated }}</td>
                    <td>{{ order.status }}</td>
                    {% endfor %}

Я постараюсь ответить на ваши вопросы как можно лучше, основываясь на том, что, как мне кажется, вы спрашиваете.

Ваши вопросы:

  1. Как добавить всю информацию из корзины пользователя (которая была сформирована в заказ) в профиль пользователя?
  2. Как сделать так, чтобы данные пользователя и данные заказа/корзины можно было изменять в профиле пользователя?
  3. Как отобразить несколько заказов пользователя в отдельных строках HTML таблицы? (потому что в моем шаблоне все заказы находятся в одной строке)?

1: Создайте отношение внешнего ключа от корзины к пользователю, используя ORM Django.

1.

Пример:

# Create your models here.
class Someclass(models.Model):
    user = models.CharField(max_length=255, default='none')
    subject = models.CharField(max_length=255, default='none')
    date = models.DateField(auto_now_add=True)

    def __str__(self):
        return self.subject

class Someotherclass(models.Model):
    relation = models.ForeignKey(
        "Someclass", on_delete=models.CASCADE, null=True, related_name='myFkRelation')
    detail = models.TextField()
    date = models.DateField(auto_now_add=True, null=True)

Таким образом, вы можете связать корзину с пользователем.


2: Создайте (или 2) функции в вашем views.py, где вы можете редактировать данные.

Пример (использование 2 отдельных функций):

# views.py
def change(request, id):
    something = Someclass.objects.get(id=id)
    context = {
        'something': something,
    }
    return render(request, 'change.html', context)


def addchange(request, id):
    change = request.POST['change']

    something = Someclass.objects.get(id=id)
    something.subject = change
    something.date = datetime.now()
    something.save()

    return redirect('index')


----------
# urls.py

    path('view/<int:id>/change/', views.change, name='change'),
    path('view/<int:id>/change/addchange/', views.addchange, name='addchange'),

# of course you can change the urls to what you want as long as you give the id with it as a parameter to the views function.


----------
# change.html

    <form action="addchange/" method="post">
        {% csrf_token %}

        <div class="form-group">
            <label for="change">Change: *</label>
            <textarea rows="4" cols="100" type="text" class="form-control" id="change" name="change" required></textarea>
        </div>

        <br>
        <button type="submit" class="btn btn-primary">Submit</button>
    </form>

3: Создайте цикл for внутри HTML-таблицы (учитывая контекст в представлениях, где пользователь имеет отношение к корзине)

Пример:

# views.py

def index(request):
    User = get_user_model()
    users = User.objects.all()

    context = {
        'users': users
    }
    return render(request, "index.html", context)

----------


# index.html

<table class="table table-hover table-sm">
    <thead>
    <tr>
        <th scope="col">Users</th>
        <th scope="col">Items</th>
    </tr>
    </thead>
    <tbody>
        {% for user in users %}     
                <tr>
                    <td>{{user.name}}</td>
                    <td>{{user.item}}</td>
                    # or whatever you want
                </tr>
        {% endfor %}
    </tbody>
</table>

Надеюсь, это ответит на некоторые (возможно, все?) из ваших вопросов.

Вернуться на верх