我正在构建一个简单的Django应用程序,用于评论不同的对象(餐厅、汽车服务、洗车等)。
我从应用程序开始,但很快我就遇到了第一个问题。每个对象都有特征(但每种类型的对象都有不同的特征)。
例如:
餐厅有花园、操场、座位、厨房等。
洗车机有外部清洗、内部清洗等。
所以我开始用ManyToMany表构建一个典型的DB实现,但是后来我发现了Django模型继承,所以我在我的应用程序中实现了它,如您所见:
网址.py:

from django.urls import path
from . import views

urlpatterns = [
    path('user/<int:pk>/', views.UserObjectsView.as_view(), name='user-objects'),
    path('add/', views.add_object, name='add-object'),
    path('<str:category>/<int:pk>/', views.show_object, name='show-object'),
    path('all/<str:category>/', views.show_all_objects, name="show-all-objects"),
]

型号.py:
from django.db import models
from users.models import ProfileUser
from django.utils import timezone

# Create your models here.

class Object(models.Model):
    author = models.ForeignKey(ProfileUser, on_delete=models.CASCADE)
    title = models.CharField(max_length=300)
    address = models.CharField(max_length=300)
    content = models.TextField()
    created_date = models.DateTimeField(default=timezone.now)
    approved_object = models.BooleanField(default=False)
    admin_seen = models.BooleanField(default=False)

    def __str__(self):
        return f"{self.title}"


class Restaurant(Object):
    seats = models.IntegerField()
    bulgarian_kitchen = models.BooleanField(default=False)
    italian_kitchen = models.BooleanField(default=False)
    french_kitchen = models.BooleanField(default=False)
    is_garden = models.BooleanField(default=False)
    is_playground = models.BooleanField(default=False)


class SportFitness(Object):
    is_fitness_trainer = models.BooleanField(default=False)


class CarService(Object):
    is_parts_clients = models.BooleanField(default=False)


class BeautySalon(Object):
    is_hair_salon = models.BooleanField(default=False)
    is_laser_epilation = models.BooleanField(default=False)


class FastFood(Object):
    is_pizza = models.BooleanField(default=False)
    is_duner = models.BooleanField(default=False)
    is_seats = models.BooleanField(default=False)


class CarWash(Object):
    is_external_cleaning = models.BooleanField(default=False)
    is_internal_cleaning = models.BooleanField(default=False)
    is_engine_cleaning = models.BooleanField(default=False)


class Fun(Object):
    is_working_weekend = models.BooleanField(default=False)
    is_kids_suitable = models.BooleanField(default=False)


class Other(Object):
    is_working_weekend = models.BooleanField(default=False)


class Comment(models.Model):
    object = models.ForeignKey(Object, on_delete=models.CASCADE, related_name='comments')
    author = models.ForeignKey(ProfileUser, on_delete=models.CASCADE)
    content = models.TextField()
    rating = models.TextField()
    created_date = models.DateTimeField(default=timezone.now)

    def __str__(self):
        return f"{self.content}"

视图.py:
from django.shortcuts import render, redirect
from django.views import generic
from objects.models import Object, ProfileUser, Comment, Restaurant, SportFitness, CarService, BeautySalon, FastFood, CarWash, Fun, Other
from .forms import ObjectForm, CommentForm
from django.contrib import messages
from django.db.models import Avg
import sys, pdb

class AllObjects(generic.ListView):
    queryset = Object.objects.all()
    template_name = 'show_all_objects.html'

class UserObjectsView(generic.ListView):
    template_name = 'user_objects.html'

    def get_queryset(self):
        user_id = self.kwargs['pk']
        return Object.objects.filter(author_id = user_id)

def add_object(request):
    if not request.user.is_authenticated:
        messages.info(request, 'За да добавите нов Обект, трябва да сте регистриран потребител!')
        return redirect('account_login')
    form = ObjectForm(request.POST or None)
    if form.is_valid():
        obj = form.save(commit=False)
        obj.author = ProfileUser.objects.get(user=request.user)
        obj.save()
        messages.success(request, 'Успешно добавихте нов Обект, може да видите вашите обекти във вашия профил!')
        return redirect('home')

    context = {
        'form': form
    }

    return render(request, "add_object.html", context)

def show_object(request, pk):
    obj = Object.objects.get(id=5)

    if request.method == 'POST':
        user = request.user
        author = ProfileUser.objects.get(user=user)
        comment = Comment()
        comment.object = obj
        comment.author = author
        comment.content = request.POST.get('content')
        comment.rating = request.POST.get('rating')
        comment.save()

    form = CommentForm()
    reviews_count = Comment.objects.filter(object_id=pk).count()
    rating = Comment.objects.filter(object_id=pk).aggregate(Avg('rating'))['rating__avg']

    context = {
        'form': form,
        'object': obj,
        'reviews_count': reviews_count,
        'rating': rating
    }

    return render(request, "show_object.html", context)

def show_all_objects(request, category):
    categories = {'restaurants' : 'Restaurant', 'sportfitness' : 'SportFitness', 'carservice' : 'CarService', 'beautysalon' : 'BeautySalon', 'fastfood' : 'FastFood', 'carwash' : 'CarWash', 'fun' : 'Fun', 'other' : 'Other'}
    objects = eval(categories[category]).objects.all()
    context = {
        'object_list': objects,
    }

    return render(request, 'show_all_objects.html', context)

在我必须显示每个类别的对象之前,一切都很好,比如这样(我使用的是餐馆而不是餐馆,因为url看起来更好):
  <a href="{% url 'show-all-objects' category='restaurants' %}" class="utf_category_small_box_part"> <i class="im im-icon-Chef"></i>
    <h4>Ресторантии</h4>
    <span>22</span>
  </a>
  <a href="{% url 'show-all-objects' category='sportfitness' %}" class="utf_category_small_box_part"> <i class="im im-icon-Dumbbell"></i>
    <h4>Спортни и фитнес</h4>
    <span>15</span>
  </a>

你可以检查show_all_objects功能,所以我用eval()完成了它:
categories = {'restaurants' : 'Restaurant', 'sportfitness' : 'SportFitness', 'carservice' : 'CarService', 'beautysalon' : 'BeautySalon', 'fastfood' : 'FastFood', 'carwash' : 'CarWash', 'fun' : 'Fun', 'other' : 'Other'}
objects = eval(categories[category]).objects.all()

很好,但后来我又遇到了这个问题当我想在show_object()-方法中显示一个具有其特性的对象(您可以在上面的代码中检查它)时,我可以获取该对象,但不能获取restaurant例如,或car wash等:
def show_object(request, pk):
    obj = Object.objects.get(id=5)

现在我有了目标,但我无法得到确切的目标当我想为每种类型的对象显示不同的表单时,我又遇到了同样的问题(例如,餐馆应该有一个带有其功能的复选框的表单,带有其功能的复选框的carwashes表单等等)。
P.S:基于@SaaWhat答案,他建议我在eval()函数中使用show_object(),但我在模板中继承了所有的OJPEC,所以我不能将类似param的类别传递给它:
<div class="row">
    {% for object in object_list %}
      <div class="col-lg-12 col-md-12">
        <div class="utf_listing_item-container list-layout"> <a href="{% url 'show-object' category='' pk=object.id%}"  class="utf_listing_item">
          <div class="utf_listing_item-image">
              <img src="{% static 'core/images/utf_listing_item-01.jpg' %}" alt="">
              <span class="like-icon"></span>
              <span class="tag"><i class="im im-icon-Hotel"></i> Hotels</span>
              <div class="utf_listing_prige_block utf_half_list">
                <span class="utf_meta_listing_price"><i class="fa fa-tag"></i> $25 - $45</span>
                <span class="utp_approve_item"><i class="utf_approve_listing"></i></span>
              </div>
          </div>
          <div class="utf_listing_item_content">
            <div class="utf_listing_item-inner">
              <h3>{{ object.title }}</h3>
              <span><i class="sl sl-icon-location"></i> {{ object.address }}</span>
              <p>{{ object.content }}</p>
            </div>
          </div>
          </a>
        </div>
      </div>
    {% endfor %}
</div>

此行:
<a href="{% url 'show-object' category='' pk=object.id%}"

我不能通过分类,因为我没有

最佳答案

1:对模型put使用继承时

class Meta:
    abstract = True

在您的基础模型中,在您的情况下是Object,这样它就不会创建自己的实例/表所以在这种情况下你的模型看起来
class Object(models.Model):
    author = models.ForeignKey(ProfileUser, on_delete=models.CASCADE)
    title = models.CharField(max_length=300)
    address = models.CharField(max_length=300)
    content = models.TextField()
    created_date = models.DateTimeField(default=timezone.now)
    approved_object = models.BooleanField(default=False)
    admin_seen = models.BooleanField(default=False)

    class Meta:
        abstract = True

    def __str__(self):
        return f"{self.title}"

另一方面,将Object重命名为其他类似于BaseModel的名称。
2:当您调用doingshow_object时,传递模型的类别/名称并对其进行查询,例如:
obj = Object.objects.get(id=5) #Instead of this
obj = eval(categories[category]).objects.get(pk=pk) # Do this

3:对于Comment模型,可以为每个模型添加一堆外键,也可以使用Generic Relation in Django
4:在显示表单时,使用各自的模型而不是Object模型您无论如何都可以访问所有字段,因为您是从中继承的。
我希望我已经回答了你所有的问题,如果不让我知道的话。
更新:
关于无法从模板传递类别,请在视图中将类别也传递给模板
def show_all_objects(request, category):
    categories = {'restaurants' : 'Restaurant', 'sportfitness' : 'SportFitness', 'carservice' : 'CarService', 'beautysalon' : 'BeautySalon', 'fastfood' : 'FastFood', 'carwash' : 'CarWash', 'fun' : 'Fun', 'other' : 'Other'}
    objects = eval(categories[category]).objects.all()
    context = {
      'object_list': objects,
      'category': category
    }

    return render(request, 'show_all_objects.html', context)

现在您可以访问模板文件中的category并将其传回。

09-25 17:25